InstEmitMemoryEx32.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. using ARMeilleure.Decoders;
  2. using ARMeilleure.IntermediateRepresentation;
  3. using ARMeilleure.State;
  4. using ARMeilleure.Translation;
  5. using static ARMeilleure.Instructions.InstEmitHelper;
  6. using static ARMeilleure.Instructions.InstEmitMemoryExHelper;
  7. using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
  8. namespace ARMeilleure.Instructions
  9. {
  10. static partial class InstEmit32
  11. {
  12. public static void Clrex(ArmEmitterContext context)
  13. {
  14. EmitClearExclusive(context);
  15. }
  16. public static void Csdb(ArmEmitterContext context)
  17. {
  18. // Execute as no-op.
  19. }
  20. public static void Dmb(ArmEmitterContext context) => EmitBarrier(context);
  21. public static void Dsb(ArmEmitterContext context) => EmitBarrier(context);
  22. public static void Ldrex(ArmEmitterContext context)
  23. {
  24. EmitExLoadOrStore(context, WordSizeLog2, AccessType.LoadZx | AccessType.Exclusive);
  25. }
  26. public static void Ldrexb(ArmEmitterContext context)
  27. {
  28. EmitExLoadOrStore(context, ByteSizeLog2, AccessType.LoadZx | AccessType.Exclusive);
  29. }
  30. public static void Ldrexd(ArmEmitterContext context)
  31. {
  32. EmitExLoadOrStore(context, DWordSizeLog2, AccessType.LoadZx | AccessType.Exclusive);
  33. }
  34. public static void Ldrexh(ArmEmitterContext context)
  35. {
  36. EmitExLoadOrStore(context, HWordSizeLog2, AccessType.LoadZx | AccessType.Exclusive);
  37. }
  38. public static void Lda(ArmEmitterContext context)
  39. {
  40. EmitExLoadOrStore(context, WordSizeLog2, AccessType.LoadZx | AccessType.Ordered);
  41. }
  42. public static void Ldab(ArmEmitterContext context)
  43. {
  44. EmitExLoadOrStore(context, ByteSizeLog2, AccessType.LoadZx | AccessType.Ordered);
  45. }
  46. public static void Ldaex(ArmEmitterContext context)
  47. {
  48. EmitExLoadOrStore(context, WordSizeLog2, AccessType.LoadZx | AccessType.Exclusive | AccessType.Ordered);
  49. }
  50. public static void Ldaexb(ArmEmitterContext context)
  51. {
  52. EmitExLoadOrStore(context, ByteSizeLog2, AccessType.LoadZx | AccessType.Exclusive | AccessType.Ordered);
  53. }
  54. public static void Ldaexd(ArmEmitterContext context)
  55. {
  56. EmitExLoadOrStore(context, DWordSizeLog2, AccessType.LoadZx | AccessType.Exclusive | AccessType.Ordered);
  57. }
  58. public static void Ldaexh(ArmEmitterContext context)
  59. {
  60. EmitExLoadOrStore(context, HWordSizeLog2, AccessType.LoadZx | AccessType.Exclusive | AccessType.Ordered);
  61. }
  62. public static void Ldah(ArmEmitterContext context)
  63. {
  64. EmitExLoadOrStore(context, HWordSizeLog2, AccessType.LoadZx | AccessType.Ordered);
  65. }
  66. // Stores.
  67. public static void Strex(ArmEmitterContext context)
  68. {
  69. EmitExLoadOrStore(context, WordSizeLog2, AccessType.Store | AccessType.Exclusive);
  70. }
  71. public static void Strexb(ArmEmitterContext context)
  72. {
  73. EmitExLoadOrStore(context, ByteSizeLog2, AccessType.Store | AccessType.Exclusive);
  74. }
  75. public static void Strexd(ArmEmitterContext context)
  76. {
  77. EmitExLoadOrStore(context, DWordSizeLog2, AccessType.Store | AccessType.Exclusive);
  78. }
  79. public static void Strexh(ArmEmitterContext context)
  80. {
  81. EmitExLoadOrStore(context, HWordSizeLog2, AccessType.Store | AccessType.Exclusive);
  82. }
  83. public static void Stl(ArmEmitterContext context)
  84. {
  85. EmitExLoadOrStore(context, WordSizeLog2, AccessType.Store | AccessType.Ordered);
  86. }
  87. public static void Stlb(ArmEmitterContext context)
  88. {
  89. EmitExLoadOrStore(context, ByteSizeLog2, AccessType.Store | AccessType.Ordered);
  90. }
  91. public static void Stlex(ArmEmitterContext context)
  92. {
  93. EmitExLoadOrStore(context, WordSizeLog2, AccessType.Store | AccessType.Exclusive | AccessType.Ordered);
  94. }
  95. public static void Stlexb(ArmEmitterContext context)
  96. {
  97. EmitExLoadOrStore(context, ByteSizeLog2, AccessType.Store | AccessType.Exclusive | AccessType.Ordered);
  98. }
  99. public static void Stlexd(ArmEmitterContext context)
  100. {
  101. EmitExLoadOrStore(context, DWordSizeLog2, AccessType.Store | AccessType.Exclusive | AccessType.Ordered);
  102. }
  103. public static void Stlexh(ArmEmitterContext context)
  104. {
  105. EmitExLoadOrStore(context, HWordSizeLog2, AccessType.Store | AccessType.Exclusive | AccessType.Ordered);
  106. }
  107. public static void Stlh(ArmEmitterContext context)
  108. {
  109. EmitExLoadOrStore(context, HWordSizeLog2, AccessType.Store | AccessType.Ordered);
  110. }
  111. private static void EmitExLoadOrStore(ArmEmitterContext context, int size, AccessType accType)
  112. {
  113. IOpCode32MemEx op = (IOpCode32MemEx)context.CurrOp;
  114. Operand address = context.Copy(GetIntA32(context, op.Rn));
  115. var exclusive = (accType & AccessType.Exclusive) != 0;
  116. var ordered = (accType & AccessType.Ordered) != 0;
  117. if (ordered)
  118. {
  119. EmitBarrier(context);
  120. }
  121. if ((accType & AccessType.Load) != 0)
  122. {
  123. if (size == DWordSizeLog2)
  124. {
  125. // Keep loads atomic - make the call to get the whole region and then decompose it into parts
  126. // for the registers.
  127. Operand value = EmitLoadExclusive(context, address, exclusive, size);
  128. Operand valueLow = context.ConvertI64ToI32(value);
  129. valueLow = context.ZeroExtend32(OperandType.I64, valueLow);
  130. Operand valueHigh = context.ShiftRightUI(value, Const(32));
  131. Operand lblBigEndian = Label();
  132. Operand lblEnd = Label();
  133. context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag));
  134. SetIntA32(context, op.Rt, valueLow);
  135. SetIntA32(context, op.Rt | 1, valueHigh);
  136. context.Branch(lblEnd);
  137. context.MarkLabel(lblBigEndian);
  138. SetIntA32(context, op.Rt | 1, valueLow);
  139. SetIntA32(context, op.Rt, valueHigh);
  140. context.MarkLabel(lblEnd);
  141. }
  142. else
  143. {
  144. SetIntA32(context, op.Rt, EmitLoadExclusive(context, address, exclusive, size));
  145. }
  146. }
  147. else
  148. {
  149. if (size == DWordSizeLog2)
  150. {
  151. // Split the result into 2 words (based on endianness)
  152. Operand lo = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt));
  153. Operand hi = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt | 1));
  154. Operand lblBigEndian = Label();
  155. Operand lblEnd = Label();
  156. context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag));
  157. Operand leResult = context.BitwiseOr(lo, context.ShiftLeft(hi, Const(32)));
  158. EmitStoreExclusive(context, address, leResult, exclusive, size, op.Rd, a32: true);
  159. context.Branch(lblEnd);
  160. context.MarkLabel(lblBigEndian);
  161. Operand beResult = context.BitwiseOr(hi, context.ShiftLeft(lo, Const(32)));
  162. EmitStoreExclusive(context, address, beResult, exclusive, size, op.Rd, a32: true);
  163. context.MarkLabel(lblEnd);
  164. }
  165. else
  166. {
  167. Operand value = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt));
  168. EmitStoreExclusive(context, address, value, exclusive, size, op.Rd, a32: true);
  169. }
  170. }
  171. }
  172. private static void EmitBarrier(ArmEmitterContext context)
  173. {
  174. // Note: This barrier is most likely not necessary, and probably
  175. // doesn't make any difference since we need to do a ton of stuff
  176. // (software MMU emulation) to read or write anything anyway.
  177. }
  178. }
  179. }