InstEmitSystem32.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. using ARMeilleure.Decoders;
  2. using ARMeilleure.IntermediateRepresentation;
  3. using ARMeilleure.State;
  4. using ARMeilleure.Translation;
  5. using System;
  6. using System.Reflection;
  7. using static ARMeilleure.Instructions.InstEmitHelper;
  8. using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
  9. namespace ARMeilleure.Instructions
  10. {
  11. static partial class InstEmit32
  12. {
  13. public static void Mcr(ArmEmitterContext context)
  14. {
  15. OpCode32System op = (OpCode32System)context.CurrOp;
  16. if (op.Coproc != 15 || op.Opc1 != 0)
  17. {
  18. InstEmit.Und(context);
  19. return;
  20. }
  21. MethodInfo info;
  22. switch (op.CRn)
  23. {
  24. case 13: // Process and Thread Info.
  25. if (op.CRm != 0)
  26. {
  27. throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
  28. }
  29. switch (op.Opc2)
  30. {
  31. case 2:
  32. info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032)); break;
  33. default:
  34. throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
  35. }
  36. break;
  37. case 7:
  38. switch (op.CRm) // Cache and Memory barrier.
  39. {
  40. case 10:
  41. switch (op.Opc2)
  42. {
  43. case 5: // Data Memory Barrier Register.
  44. return; // No-op.
  45. default:
  46. throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16} (0x{op.RawOpCode:X}).");
  47. }
  48. default:
  49. throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16} (0x{op.RawOpCode:X}).");
  50. }
  51. default:
  52. throw new NotImplementedException($"Unknown MRC 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
  53. }
  54. context.Call(info, GetIntA32(context, op.Rt));
  55. }
  56. public static void Mrc(ArmEmitterContext context)
  57. {
  58. OpCode32System op = (OpCode32System)context.CurrOp;
  59. if (op.Coproc != 15 || op.Opc1 != 0)
  60. {
  61. InstEmit.Und(context);
  62. return;
  63. }
  64. MethodInfo info;
  65. switch (op.CRn)
  66. {
  67. case 13: // Process and Thread Info.
  68. if (op.CRm != 0)
  69. {
  70. throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
  71. }
  72. switch (op.Opc2)
  73. {
  74. case 2:
  75. info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrEl032)); break;
  76. case 3:
  77. info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidr32)); break;
  78. default:
  79. throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
  80. }
  81. break;
  82. default:
  83. throw new NotImplementedException($"Unknown MRC 0x{op.RawOpCode:X} at 0x{op.Address:X}.");
  84. }
  85. if (op.Rt == RegisterAlias.Aarch32Pc)
  86. {
  87. // Special behavior: copy NZCV flags into APSR.
  88. EmitSetNzcv(context, context.Call(info));
  89. return;
  90. }
  91. else
  92. {
  93. SetIntA32(context, op.Rt, context.Call(info));
  94. }
  95. }
  96. public static void Mrrc(ArmEmitterContext context)
  97. {
  98. OpCode32System op = (OpCode32System)context.CurrOp;
  99. if (op.Coproc != 15)
  100. {
  101. InstEmit.Und(context);
  102. return;
  103. }
  104. int opc = op.MrrcOp;
  105. MethodInfo info;
  106. switch (op.CRm)
  107. {
  108. case 14: // Timer.
  109. switch (opc)
  110. {
  111. case 0:
  112. info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntpctEl0)); break;
  113. default:
  114. throw new NotImplementedException($"Unknown MRRC Opc1 0x{opc:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
  115. }
  116. break;
  117. default:
  118. throw new NotImplementedException($"Unknown MRRC 0x{op.RawOpCode:X} at 0x{op.Address:X}.");
  119. }
  120. Operand result = context.Call(info);
  121. SetIntA32(context, op.Rt, context.ConvertI64ToI32(result));
  122. SetIntA32(context, op.CRn, context.ConvertI64ToI32(context.ShiftRightUI(result, Const(32))));
  123. }
  124. public static void Mrs(ArmEmitterContext context)
  125. {
  126. OpCode32Mrs op = (OpCode32Mrs)context.CurrOp;
  127. if (op.R)
  128. {
  129. throw new NotImplementedException("SPSR");
  130. }
  131. else
  132. {
  133. Operand spsr = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
  134. spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag)));
  135. spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag)));
  136. spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag)));
  137. spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.QFlag), Const((int)PState.QFlag)));
  138. // TODO: Remaining flags.
  139. SetIntA32(context, op.Rd, spsr);
  140. }
  141. }
  142. public static void Msr(ArmEmitterContext context)
  143. {
  144. OpCode32MsrReg op = (OpCode32MsrReg)context.CurrOp;
  145. if (op.R)
  146. {
  147. throw new NotImplementedException("SPSR");
  148. }
  149. else
  150. {
  151. if ((op.Mask & 8) != 0)
  152. {
  153. Operand value = GetIntA32(context, op.Rn);
  154. EmitSetNzcv(context, value);
  155. Operand q = context.BitwiseAnd(context.ShiftRightUI(value, Const((int)PState.QFlag)), Const(1));
  156. SetFlag(context, PState.QFlag, q);
  157. }
  158. if ((op.Mask & 4) != 0)
  159. {
  160. throw new NotImplementedException("APSR_g");
  161. }
  162. if ((op.Mask & 2) != 0)
  163. {
  164. throw new NotImplementedException("CPSR_x");
  165. }
  166. if ((op.Mask & 1) != 0)
  167. {
  168. throw new NotImplementedException("CPSR_c");
  169. }
  170. }
  171. }
  172. public static void Nop(ArmEmitterContext context) { }
  173. public static void Vmrs(ArmEmitterContext context)
  174. {
  175. OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
  176. if (op.Rt == RegisterAlias.Aarch32Pc && op.Sreg == 0b0001)
  177. {
  178. // Special behavior: copy NZCV flags into APSR.
  179. SetFlag(context, PState.VFlag, GetFpFlag(FPState.VFlag));
  180. SetFlag(context, PState.CFlag, GetFpFlag(FPState.CFlag));
  181. SetFlag(context, PState.ZFlag, GetFpFlag(FPState.ZFlag));
  182. SetFlag(context, PState.NFlag, GetFpFlag(FPState.NFlag));
  183. return;
  184. }
  185. switch (op.Sreg)
  186. {
  187. case 0b0000: // FPSID
  188. throw new NotImplementedException("Supervisor Only");
  189. case 0b0001: // FPSCR
  190. EmitGetFpscr(context); return;
  191. case 0b0101: // MVFR2
  192. throw new NotImplementedException("MVFR2");
  193. case 0b0110: // MVFR1
  194. throw new NotImplementedException("MVFR1");
  195. case 0b0111: // MVFR0
  196. throw new NotImplementedException("MVFR0");
  197. case 0b1000: // FPEXC
  198. throw new NotImplementedException("Supervisor Only");
  199. default:
  200. throw new NotImplementedException($"Unknown VMRS 0x{op.RawOpCode:X} at 0x{op.Address:X}.");
  201. }
  202. }
  203. public static void Vmsr(ArmEmitterContext context)
  204. {
  205. OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
  206. switch (op.Sreg)
  207. {
  208. case 0b0000: // FPSID
  209. throw new NotImplementedException("Supervisor Only");
  210. case 0b0001: // FPSCR
  211. EmitSetFpscr(context); return;
  212. case 0b0101: // MVFR2
  213. throw new NotImplementedException("MVFR2");
  214. case 0b0110: // MVFR1
  215. throw new NotImplementedException("MVFR1");
  216. case 0b0111: // MVFR0
  217. throw new NotImplementedException("MVFR0");
  218. case 0b1000: // FPEXC
  219. throw new NotImplementedException("Supervisor Only");
  220. default:
  221. throw new NotImplementedException($"Unknown VMSR 0x{op.RawOpCode:X} at 0x{op.Address:X}.");
  222. }
  223. }
  224. private static void EmitSetNzcv(ArmEmitterContext context, Operand t)
  225. {
  226. Operand v = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.VFlag)), Const(1));
  227. Operand c = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.CFlag)), Const(1));
  228. Operand z = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.ZFlag)), Const(1));
  229. Operand n = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.NFlag)), Const(1));
  230. SetFlag(context, PState.VFlag, v);
  231. SetFlag(context, PState.CFlag, c);
  232. SetFlag(context, PState.ZFlag, z);
  233. SetFlag(context, PState.NFlag, n);
  234. }
  235. private static void EmitGetFpscr(ArmEmitterContext context)
  236. {
  237. OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
  238. Operand fpscr = Const(0);
  239. for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
  240. {
  241. if (FPSCR.Mask.HasFlag((FPSCR)(1u << flag)))
  242. {
  243. fpscr = context.BitwiseOr(fpscr, context.ShiftLeft(GetFpFlag((FPState)flag), Const(flag)));
  244. }
  245. }
  246. SetIntA32(context, op.Rt, fpscr);
  247. }
  248. private static void EmitSetFpscr(ArmEmitterContext context)
  249. {
  250. OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
  251. Operand fpscr = GetIntA32(context, op.Rt);
  252. for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
  253. {
  254. if (FPSCR.Mask.HasFlag((FPSCR)(1u << flag)))
  255. {
  256. SetFpFlag(context, (FPState)flag, context.BitwiseAnd(context.ShiftRightUI(fpscr, Const(flag)), Const(1)));
  257. }
  258. }
  259. }
  260. }
  261. }