InstEmit32Helper.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. using ChocolArm64.Decoders;
  2. using ChocolArm64.IntermediateRepresentation;
  3. using ChocolArm64.State;
  4. using ChocolArm64.Translation;
  5. using System;
  6. using System.Reflection.Emit;
  7. namespace ChocolArm64.Instructions
  8. {
  9. static class InstEmit32Helper
  10. {
  11. public static bool IsThumb(OpCode64 op)
  12. {
  13. return op is OpCodeT16;
  14. }
  15. public static void EmitLoadFromRegister(ILEmitterCtx context, int register)
  16. {
  17. if (register == RegisterAlias.Aarch32Pc)
  18. {
  19. OpCode32 op = (OpCode32)context.CurrOp;
  20. context.EmitLdc_I4((int)op.GetPc());
  21. }
  22. else
  23. {
  24. context.EmitLdint(GetRegisterAlias(context.Mode, register));
  25. }
  26. }
  27. public static void EmitStoreToRegister(ILEmitterCtx context, int register)
  28. {
  29. if (register == RegisterAlias.Aarch32Pc)
  30. {
  31. context.EmitStoreContext();
  32. EmitBxWritePc(context);
  33. }
  34. else
  35. {
  36. context.EmitStint(GetRegisterAlias(context.Mode, register));
  37. }
  38. }
  39. public static void EmitBxWritePc(ILEmitterCtx context)
  40. {
  41. context.Emit(OpCodes.Dup);
  42. context.EmitLdc_I4(1);
  43. context.Emit(OpCodes.And);
  44. context.Emit(OpCodes.Dup);
  45. context.EmitStflg((int)PState.TBit);
  46. ILLabel lblArmMode = new ILLabel();
  47. ILLabel lblEnd = new ILLabel();
  48. context.Emit(OpCodes.Brtrue_S, lblArmMode);
  49. context.EmitLdc_I4(~1);
  50. context.Emit(OpCodes.Br_S, lblEnd);
  51. context.MarkLabel(lblArmMode);
  52. context.EmitLdc_I4(~3);
  53. context.MarkLabel(lblEnd);
  54. context.Emit(OpCodes.And);
  55. context.Emit(OpCodes.Conv_U8);
  56. context.Emit(OpCodes.Ret);
  57. }
  58. public static int GetRegisterAlias(Aarch32Mode mode, int register)
  59. {
  60. //Only registers >= 8 are banked, with registers in the range [8, 12] being
  61. //banked for the FIQ mode, and registers 13 and 14 being banked for all modes.
  62. if ((uint)register < 8)
  63. {
  64. return register;
  65. }
  66. return GetBankedRegisterAlias(mode, register);
  67. }
  68. public static int GetBankedRegisterAlias(Aarch32Mode mode, int register)
  69. {
  70. switch (register)
  71. {
  72. case 8: return mode == Aarch32Mode.Fiq
  73. ? RegisterAlias.R8Fiq
  74. : RegisterAlias.R8Usr;
  75. case 9: return mode == Aarch32Mode.Fiq
  76. ? RegisterAlias.R9Fiq
  77. : RegisterAlias.R9Usr;
  78. case 10: return mode == Aarch32Mode.Fiq
  79. ? RegisterAlias.R10Fiq
  80. : RegisterAlias.R10Usr;
  81. case 11: return mode == Aarch32Mode.Fiq
  82. ? RegisterAlias.R11Fiq
  83. : RegisterAlias.R11Usr;
  84. case 12: return mode == Aarch32Mode.Fiq
  85. ? RegisterAlias.R12Fiq
  86. : RegisterAlias.R12Usr;
  87. case 13:
  88. switch (mode)
  89. {
  90. case Aarch32Mode.User:
  91. case Aarch32Mode.System: return RegisterAlias.SpUsr;
  92. case Aarch32Mode.Fiq: return RegisterAlias.SpFiq;
  93. case Aarch32Mode.Irq: return RegisterAlias.SpIrq;
  94. case Aarch32Mode.Supervisor: return RegisterAlias.SpSvc;
  95. case Aarch32Mode.Abort: return RegisterAlias.SpAbt;
  96. case Aarch32Mode.Hypervisor: return RegisterAlias.SpHyp;
  97. case Aarch32Mode.Undefined: return RegisterAlias.SpUnd;
  98. default: throw new ArgumentException(nameof(mode));
  99. }
  100. case 14:
  101. switch (mode)
  102. {
  103. case Aarch32Mode.User:
  104. case Aarch32Mode.Hypervisor:
  105. case Aarch32Mode.System: return RegisterAlias.LrUsr;
  106. case Aarch32Mode.Fiq: return RegisterAlias.LrFiq;
  107. case Aarch32Mode.Irq: return RegisterAlias.LrIrq;
  108. case Aarch32Mode.Supervisor: return RegisterAlias.LrSvc;
  109. case Aarch32Mode.Abort: return RegisterAlias.LrAbt;
  110. case Aarch32Mode.Undefined: return RegisterAlias.LrUnd;
  111. default: throw new ArgumentException(nameof(mode));
  112. }
  113. default: throw new ArgumentOutOfRangeException(nameof(register));
  114. }
  115. }
  116. }
  117. }