InstEmitMemoryEx32.cs 8.1 KB

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