InstEmitMemory.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. using ARMeilleure.Decoders;
  2. using ARMeilleure.IntermediateRepresentation;
  3. using ARMeilleure.Translation;
  4. using static ARMeilleure.Instructions.InstEmitHelper;
  5. using static ARMeilleure.Instructions.InstEmitMemoryHelper;
  6. using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
  7. namespace ARMeilleure.Instructions
  8. {
  9. static partial class InstEmit
  10. {
  11. public static void Adr(ArmEmitterContext context)
  12. {
  13. OpCodeAdr op = (OpCodeAdr)context.CurrOp;
  14. SetIntOrZR(context, op.Rd, Const(op.Address + (ulong)op.Immediate));
  15. }
  16. public static void Adrp(ArmEmitterContext context)
  17. {
  18. OpCodeAdr op = (OpCodeAdr)context.CurrOp;
  19. ulong address = (op.Address & ~0xfffUL) + ((ulong)op.Immediate << 12);
  20. SetIntOrZR(context, op.Rd, Const(address));
  21. }
  22. public static void Ldr(ArmEmitterContext context) => EmitLdr(context, signed: false);
  23. public static void Ldrs(ArmEmitterContext context) => EmitLdr(context, signed: true);
  24. private static void EmitLdr(ArmEmitterContext context, bool signed)
  25. {
  26. OpCodeMem op = (OpCodeMem)context.CurrOp;
  27. Operand address = GetAddress(context);
  28. if (signed && op.Extend64)
  29. {
  30. EmitLoadSx64(context, address, op.Rt, op.Size);
  31. }
  32. else if (signed)
  33. {
  34. EmitLoadSx32(context, address, op.Rt, op.Size);
  35. }
  36. else
  37. {
  38. EmitLoadZx(context, address, op.Rt, op.Size);
  39. }
  40. EmitWBackIfNeeded(context, address);
  41. }
  42. public static void Ldr_Literal(ArmEmitterContext context)
  43. {
  44. IOpCodeLit op = (IOpCodeLit)context.CurrOp;
  45. if (op.Prefetch)
  46. {
  47. return;
  48. }
  49. if (op.Signed)
  50. {
  51. EmitLoadSx64(context, Const(op.Immediate), op.Rt, op.Size);
  52. }
  53. else
  54. {
  55. EmitLoadZx(context, Const(op.Immediate), op.Rt, op.Size);
  56. }
  57. }
  58. public static void Ldp(ArmEmitterContext context)
  59. {
  60. OpCodeMemPair op = (OpCodeMemPair)context.CurrOp;
  61. void EmitLoad(int rt, Operand ldAddr)
  62. {
  63. if (op.Extend64)
  64. {
  65. EmitLoadSx64(context, ldAddr, rt, op.Size);
  66. }
  67. else
  68. {
  69. EmitLoadZx(context, ldAddr, rt, op.Size);
  70. }
  71. }
  72. Operand address = GetAddress(context);
  73. Operand address2 = GetAddress(context, 1L << op.Size);
  74. EmitLoad(op.Rt, address);
  75. EmitLoad(op.Rt2, address2);
  76. EmitWBackIfNeeded(context, address);
  77. }
  78. public static void Str(ArmEmitterContext context)
  79. {
  80. OpCodeMem op = (OpCodeMem)context.CurrOp;
  81. Operand address = GetAddress(context);
  82. InstEmitMemoryHelper.EmitStore(context, address, op.Rt, op.Size);
  83. EmitWBackIfNeeded(context, address);
  84. }
  85. public static void Stp(ArmEmitterContext context)
  86. {
  87. OpCodeMemPair op = (OpCodeMemPair)context.CurrOp;
  88. Operand address = GetAddress(context);
  89. Operand address2 = GetAddress(context, 1L << op.Size);
  90. InstEmitMemoryHelper.EmitStore(context, address, op.Rt, op.Size);
  91. InstEmitMemoryHelper.EmitStore(context, address2, op.Rt2, op.Size);
  92. EmitWBackIfNeeded(context, address);
  93. }
  94. private static Operand GetAddress(ArmEmitterContext context, long addend = 0)
  95. {
  96. Operand address = default;
  97. switch (context.CurrOp)
  98. {
  99. case OpCodeMemImm op:
  100. {
  101. address = context.Copy(GetIntOrSP(context, op.Rn));
  102. // Pre-indexing.
  103. if (!op.PostIdx)
  104. {
  105. address = context.Add(address, Const(op.Immediate + addend));
  106. }
  107. else if (addend != 0)
  108. {
  109. address = context.Add(address, Const(addend));
  110. }
  111. break;
  112. }
  113. case OpCodeMemReg op:
  114. {
  115. Operand n = GetIntOrSP(context, op.Rn);
  116. Operand m = GetExtendedM(context, op.Rm, op.IntType);
  117. if (op.Shift)
  118. {
  119. m = context.ShiftLeft(m, Const(op.Size));
  120. }
  121. address = context.Add(n, m);
  122. if (addend != 0)
  123. {
  124. address = context.Add(address, Const(addend));
  125. }
  126. break;
  127. }
  128. }
  129. return address;
  130. }
  131. private static void EmitWBackIfNeeded(ArmEmitterContext context, Operand address)
  132. {
  133. // Check whenever the current OpCode has post-indexed write back, if so write it.
  134. if (context.CurrOp is OpCodeMemImm op && op.WBack)
  135. {
  136. if (op.PostIdx)
  137. {
  138. address = context.Add(address, Const(op.Immediate));
  139. }
  140. SetIntOrSP(context, op.Rn, address);
  141. }
  142. }
  143. }
  144. }