InstEmitSystem32.cs 8.8 KB

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