InstEmit32Helper.cs 4.8 KB

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