InstEmit32Helper.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. using ChocolArm64.Decoders;
  2. using ChocolArm64.State;
  3. using ChocolArm64.Translation;
  4. using System;
  5. namespace ChocolArm64.Instructions
  6. {
  7. static class InstEmit32Helper
  8. {
  9. public static bool IsThumb(OpCode64 op)
  10. {
  11. return op is OpCodeT16;
  12. }
  13. public static void EmitLoadFromRegister(ILEmitterCtx context, int register)
  14. {
  15. if (register == RegisterAlias.Aarch32Pc)
  16. {
  17. OpCode32 op = (OpCode32)context.CurrOp;
  18. context.EmitLdc_I4((int)op.GetPc());
  19. }
  20. else
  21. {
  22. context.EmitLdint(InstEmit32Helper.GetRegisterAlias(context.Mode, register));
  23. }
  24. }
  25. public static int GetRegisterAlias(Aarch32Mode mode, int register)
  26. {
  27. //Only registers >= 8 are banked, with registers in the range [8, 12] being
  28. //banked for the FIQ mode, and registers 13 and 14 being banked for all modes.
  29. if ((uint)register < 8)
  30. {
  31. return register;
  32. }
  33. return GetBankedRegisterAlias(mode, register);
  34. }
  35. public static int GetBankedRegisterAlias(Aarch32Mode mode, int register)
  36. {
  37. switch (register)
  38. {
  39. case 8: return mode == Aarch32Mode.Fiq
  40. ? RegisterAlias.R8Fiq
  41. : RegisterAlias.R8Usr;
  42. case 9: return mode == Aarch32Mode.Fiq
  43. ? RegisterAlias.R9Fiq
  44. : RegisterAlias.R9Usr;
  45. case 10: return mode == Aarch32Mode.Fiq
  46. ? RegisterAlias.R10Fiq
  47. : RegisterAlias.R10Usr;
  48. case 11: return mode == Aarch32Mode.Fiq
  49. ? RegisterAlias.R11Fiq
  50. : RegisterAlias.R11Usr;
  51. case 12: return mode == Aarch32Mode.Fiq
  52. ? RegisterAlias.R12Fiq
  53. : RegisterAlias.R12Usr;
  54. case 13:
  55. switch (mode)
  56. {
  57. case Aarch32Mode.User:
  58. case Aarch32Mode.System: return RegisterAlias.SpUsr;
  59. case Aarch32Mode.Fiq: return RegisterAlias.SpFiq;
  60. case Aarch32Mode.Irq: return RegisterAlias.SpIrq;
  61. case Aarch32Mode.Supervisor: return RegisterAlias.SpSvc;
  62. case Aarch32Mode.Abort: return RegisterAlias.SpAbt;
  63. case Aarch32Mode.Hypervisor: return RegisterAlias.SpHyp;
  64. case Aarch32Mode.Undefined: return RegisterAlias.SpUnd;
  65. default: throw new ArgumentException(nameof(mode));
  66. }
  67. case 14:
  68. switch (mode)
  69. {
  70. case Aarch32Mode.User:
  71. case Aarch32Mode.Hypervisor:
  72. case Aarch32Mode.System: return RegisterAlias.LrUsr;
  73. case Aarch32Mode.Fiq: return RegisterAlias.LrFiq;
  74. case Aarch32Mode.Irq: return RegisterAlias.LrIrq;
  75. case Aarch32Mode.Supervisor: return RegisterAlias.LrSvc;
  76. case Aarch32Mode.Abort: return RegisterAlias.LrAbt;
  77. case Aarch32Mode.Undefined: return RegisterAlias.LrUnd;
  78. default: throw new ArgumentException(nameof(mode));
  79. }
  80. default: throw new ArgumentOutOfRangeException(nameof(register));
  81. }
  82. }
  83. }
  84. }