AILOpCodeConst.cs 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. using System.Reflection.Emit;
  2. using System.Runtime.InteropServices;
  3. namespace ChocolArm64.Translation
  4. {
  5. class AILOpCodeConst : IAILEmit
  6. {
  7. [StructLayout(LayoutKind.Explicit, Size = 8)]
  8. private struct ImmVal
  9. {
  10. [FieldOffset(0)] public int I4;
  11. [FieldOffset(0)] public long I8;
  12. [FieldOffset(0)] public float R4;
  13. [FieldOffset(0)] public double R8;
  14. }
  15. private ImmVal Value;
  16. private enum ConstType
  17. {
  18. Int32,
  19. Int64,
  20. Single,
  21. Double
  22. }
  23. private ConstType Type;
  24. private AILOpCodeConst(ConstType Type)
  25. {
  26. this.Type = Type;
  27. }
  28. public AILOpCodeConst(int Value) : this(ConstType.Int32)
  29. {
  30. this.Value = new ImmVal { I4 = Value };
  31. }
  32. public AILOpCodeConst(long Value) : this(ConstType.Int64)
  33. {
  34. this.Value = new ImmVal { I8 = Value };
  35. }
  36. public AILOpCodeConst(float Value) : this(ConstType.Single)
  37. {
  38. this.Value = new ImmVal { R4 = Value };
  39. }
  40. public AILOpCodeConst(double Value) : this(ConstType.Double)
  41. {
  42. this.Value = new ImmVal { R8 = Value };
  43. }
  44. public void Emit(AILEmitter Context)
  45. {
  46. switch (Type)
  47. {
  48. case ConstType.Int32: Context.Generator.EmitLdc_I4(Value.I4); break;
  49. case ConstType.Int64:
  50. {
  51. if (Value.I8 >= int.MinValue &&
  52. Value.I8 <= int.MaxValue)
  53. {
  54. Context.Generator.EmitLdc_I4(Value.I4);
  55. Context.Generator.Emit(OpCodes.Conv_I8);
  56. }
  57. else
  58. {
  59. Context.Generator.Emit(OpCodes.Ldc_I8, Value.I8);
  60. }
  61. break;
  62. }
  63. case ConstType.Single: Context.Generator.Emit(OpCodes.Ldc_R4, Value.R4); break;
  64. case ConstType.Double: Context.Generator.Emit(OpCodes.Ldc_R8, Value.R8); break;
  65. }
  66. }
  67. }
  68. }