InstEmitSystem32.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. using ARMeilleure.Decoders;
  2. using ARMeilleure.IntermediateRepresentation;
  3. using ARMeilleure.State;
  4. using ARMeilleure.Translation;
  5. using System;
  6. using static ARMeilleure.Instructions.InstEmitHelper;
  7. using static ARMeilleure.IntermediateRepresentation.OperandHelper;
  8. namespace ARMeilleure.Instructions
  9. {
  10. static partial class InstEmit32
  11. {
  12. public static void Mcr(ArmEmitterContext context)
  13. {
  14. OpCode32System op = (OpCode32System)context.CurrOp;
  15. if (op.Coproc != 15)
  16. {
  17. InstEmit.Und(context);
  18. return;
  19. }
  20. if (op.Opc1 != 0)
  21. {
  22. throw new NotImplementedException($"Unknown MRC Opc1 0x{op.Opc1:X16} at 0x{op.Address:X16}.");
  23. }
  24. Delegate dlg;
  25. switch (op.CRn)
  26. {
  27. case 13: // Process and Thread Info.
  28. if (op.CRm != 0)
  29. {
  30. throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16}.");
  31. }
  32. switch (op.Opc2)
  33. {
  34. case 2:
  35. dlg = new _Void_U32(NativeInterface.SetTpidrEl032); break;
  36. default:
  37. throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16}.");
  38. }
  39. break;
  40. case 7:
  41. switch (op.CRm) // Cache and Memory barrier.
  42. {
  43. case 10:
  44. switch (op.Opc2)
  45. {
  46. case 5: // Data Memory Barrier Register.
  47. return; // No-op.
  48. default:
  49. throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16}.");
  50. }
  51. default:
  52. throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16}.");
  53. }
  54. default:
  55. throw new NotImplementedException($"Unknown MRC 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
  56. }
  57. context.Call(dlg, GetIntA32(context, op.Rt));
  58. }
  59. public static void Mrc(ArmEmitterContext context)
  60. {
  61. OpCode32System op = (OpCode32System)context.CurrOp;
  62. if (op.Coproc != 15)
  63. {
  64. InstEmit.Und(context);
  65. return;
  66. }
  67. if (op.Opc1 != 0)
  68. {
  69. throw new NotImplementedException($"Unknown MRC Opc1 0x{op.Opc1:X16} at 0x{op.Address:X16}.");
  70. }
  71. Delegate dlg;
  72. switch (op.CRn)
  73. {
  74. case 13: // Process and Thread Info.
  75. if (op.CRm != 0)
  76. {
  77. throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16}.");
  78. }
  79. switch (op.Opc2)
  80. {
  81. case 2:
  82. dlg = new _U32(NativeInterface.GetTpidrEl032); break;
  83. case 3:
  84. dlg = new _U32(NativeInterface.GetTpidr32); break;
  85. default:
  86. throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16}.");
  87. }
  88. break;
  89. default:
  90. throw new NotImplementedException($"Unknown MRC 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
  91. }
  92. if (op.Rt == RegisterAlias.Aarch32Pc)
  93. {
  94. // Special behavior: copy NZCV flags into APSR.
  95. EmitSetNzcv(context, context.Call(dlg));
  96. return;
  97. }
  98. else
  99. {
  100. SetIntA32(context, op.Rt, context.Call(dlg));
  101. }
  102. }
  103. public static void Mrrc(ArmEmitterContext context)
  104. {
  105. OpCode32System op = (OpCode32System)context.CurrOp;
  106. if (op.Coproc != 15)
  107. {
  108. InstEmit.Und(context);
  109. return;
  110. }
  111. var opc = op.MrrcOp;
  112. Delegate dlg;
  113. switch (op.CRm)
  114. {
  115. case 14: // Timer.
  116. switch (opc)
  117. {
  118. case 0:
  119. dlg = new _U64(NativeInterface.GetCntpctEl0); break;
  120. default:
  121. throw new NotImplementedException($"Unknown MRRC Opc1 0x{opc:X16} at 0x{op.Address:X16}.");
  122. }
  123. break;
  124. default:
  125. throw new NotImplementedException($"Unknown MRRC 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
  126. }
  127. Operand result = context.Call(dlg);
  128. SetIntA32(context, op.Rt, context.ConvertI64ToI32(result));
  129. SetIntA32(context, op.CRn, context.ConvertI64ToI32(context.ShiftRightUI(result, Const(32))));
  130. }
  131. public static void Nop(ArmEmitterContext context) { }
  132. public static void Vmrs(ArmEmitterContext context)
  133. {
  134. OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
  135. if (op.Rt == RegisterAlias.Aarch32Pc && op.Sreg == 0b0001)
  136. {
  137. // Special behavior: copy NZCV flags into APSR.
  138. SetFlag(context, PState.VFlag, GetFpFlag(FPState.VFlag));
  139. SetFlag(context, PState.CFlag, GetFpFlag(FPState.CFlag));
  140. SetFlag(context, PState.ZFlag, GetFpFlag(FPState.ZFlag));
  141. SetFlag(context, PState.NFlag, GetFpFlag(FPState.NFlag));
  142. return;
  143. }
  144. Delegate dlg;
  145. switch (op.Sreg)
  146. {
  147. case 0b0000: // FPSID
  148. throw new NotImplementedException("Supervisor Only");
  149. case 0b0001: // FPSCR
  150. dlg = new _U32(NativeInterface.GetFpscr); break;
  151. case 0b0101: // MVFR2
  152. throw new NotImplementedException("MVFR2");
  153. case 0b0110: // MVFR1
  154. throw new NotImplementedException("MVFR1");
  155. case 0b0111: // MVFR0
  156. throw new NotImplementedException("MVFR0");
  157. case 0b1000: // FPEXC
  158. throw new NotImplementedException("Supervisor Only");
  159. default:
  160. throw new NotImplementedException($"Unknown VMRS 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
  161. }
  162. SetIntA32(context, op.Rt, context.Call(dlg));
  163. }
  164. public static void Vmsr(ArmEmitterContext context)
  165. {
  166. OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
  167. Delegate dlg;
  168. switch (op.Sreg)
  169. {
  170. case 0b0000: // FPSID
  171. throw new NotImplementedException("Supervisor Only");
  172. case 0b0001: // FPSCR
  173. dlg = new _Void_U32(NativeInterface.SetFpscr); break;
  174. case 0b0101: // MVFR2
  175. throw new NotImplementedException("MVFR2");
  176. case 0b0110: // MVFR1
  177. throw new NotImplementedException("MVFR1");
  178. case 0b0111: // MVFR0
  179. throw new NotImplementedException("MVFR0");
  180. case 0b1000: // FPEXC
  181. throw new NotImplementedException("Supervisor Only");
  182. default:
  183. throw new NotImplementedException($"Unknown VMSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
  184. }
  185. context.Call(dlg, GetIntA32(context, op.Rt));
  186. }
  187. private static void EmitSetNzcv(ArmEmitterContext context, Operand t)
  188. {
  189. Operand v = context.ShiftRightUI(t, Const((int)PState.VFlag));
  190. v = context.BitwiseAnd(v, Const(1));
  191. Operand c = context.ShiftRightUI(t, Const((int)PState.CFlag));
  192. c = context.BitwiseAnd(c, Const(1));
  193. Operand z = context.ShiftRightUI(t, Const((int)PState.ZFlag));
  194. z = context.BitwiseAnd(z, Const(1));
  195. Operand n = context.ShiftRightUI(t, Const((int)PState.NFlag));
  196. n = context.BitwiseAnd(n, Const(1));
  197. SetFlag(context, PState.VFlag, v);
  198. SetFlag(context, PState.CFlag, c);
  199. SetFlag(context, PState.ZFlag, z);
  200. SetFlag(context, PState.NFlag, n);
  201. }
  202. }
  203. }