InstEmitSystem32.cs 12 KB

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