InstEmitSystem.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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 InstEmit
  11. {
  12. private const int DczSizeLog2 = 4;
  13. public static void Hint(ArmEmitterContext context)
  14. {
  15. // Execute as no-op.
  16. }
  17. public static void Isb(ArmEmitterContext context)
  18. {
  19. // Execute as no-op.
  20. }
  21. public static void Mrs(ArmEmitterContext context)
  22. {
  23. OpCodeSystem op = (OpCodeSystem)context.CurrOp;
  24. Delegate dlg;
  25. switch (GetPackedId(op))
  26. {
  27. case 0b11_011_0000_0000_001: dlg = new _U64(NativeInterface.GetCtrEl0); break;
  28. case 0b11_011_0000_0000_111: dlg = new _U64(NativeInterface.GetDczidEl0); break;
  29. case 0b11_011_0100_0010_000: EmitGetNzcv(context); return;
  30. case 0b11_011_0100_0100_000: dlg = new _U64(NativeInterface.GetFpcr); break;
  31. case 0b11_011_0100_0100_001: dlg = new _U64(NativeInterface.GetFpsr); break;
  32. case 0b11_011_1101_0000_010: dlg = new _U64(NativeInterface.GetTpidrEl0); break;
  33. case 0b11_011_1101_0000_011: dlg = new _U64(NativeInterface.GetTpidr); break;
  34. case 0b11_011_1110_0000_000: dlg = new _U64(NativeInterface.GetCntfrqEl0); break;
  35. case 0b11_011_1110_0000_001: dlg = new _U64(NativeInterface.GetCntpctEl0); break;
  36. case 0b11_011_1110_0000_010: dlg = new _U64(NativeInterface.GetCntvctEl0); break;
  37. default: throw new NotImplementedException($"Unknown MRS 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
  38. }
  39. SetIntOrZR(context, op.Rt, context.Call(dlg));
  40. }
  41. public static void Msr(ArmEmitterContext context)
  42. {
  43. OpCodeSystem op = (OpCodeSystem)context.CurrOp;
  44. Delegate dlg;
  45. switch (GetPackedId(op))
  46. {
  47. case 0b11_011_0100_0010_000: EmitSetNzcv(context); return;
  48. case 0b11_011_0100_0100_000: dlg = new _Void_U64(NativeInterface.SetFpcr); break;
  49. case 0b11_011_0100_0100_001: dlg = new _Void_U64(NativeInterface.SetFpsr); break;
  50. case 0b11_011_1101_0000_010: dlg = new _Void_U64(NativeInterface.SetTpidrEl0); break;
  51. default: throw new NotImplementedException($"Unknown MSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
  52. }
  53. context.Call(dlg, GetIntOrZR(context, op.Rt));
  54. }
  55. public static void Nop(ArmEmitterContext context)
  56. {
  57. // Do nothing.
  58. }
  59. public static void Sys(ArmEmitterContext context)
  60. {
  61. // This instruction is used to do some operations on the CPU like cache invalidation,
  62. // address translation and the like.
  63. // We treat it as no-op here since we don't have any cache being emulated anyway.
  64. OpCodeSystem op = (OpCodeSystem)context.CurrOp;
  65. switch (GetPackedId(op))
  66. {
  67. case 0b11_011_0111_0100_001:
  68. {
  69. // DC ZVA
  70. Operand t = GetIntOrZR(context, op.Rt);
  71. for (long offset = 0; offset < (4 << DczSizeLog2); offset += 8)
  72. {
  73. Operand address = context.Add(t, Const(offset));
  74. context.Call(new _Void_U64_U64(NativeInterface.WriteUInt64), address, Const(0L));
  75. }
  76. break;
  77. }
  78. // No-op
  79. case 0b11_011_0111_1110_001: //DC CIVAC
  80. break;
  81. }
  82. }
  83. private static int GetPackedId(OpCodeSystem op)
  84. {
  85. int id;
  86. id = op.Op2 << 0;
  87. id |= op.CRm << 3;
  88. id |= op.CRn << 7;
  89. id |= op.Op1 << 11;
  90. id |= op.Op0 << 14;
  91. return id;
  92. }
  93. private static void EmitGetNzcv(ArmEmitterContext context)
  94. {
  95. OpCodeSystem op = (OpCodeSystem)context.CurrOp;
  96. Operand vSh = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
  97. Operand cSh = context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag));
  98. Operand zSh = context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag));
  99. Operand nSh = context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag));
  100. Operand nzcvSh = context.BitwiseOr(context.BitwiseOr(nSh, zSh), context.BitwiseOr(cSh, vSh));
  101. SetIntOrZR(context, op.Rt, nzcvSh);
  102. }
  103. private static void EmitSetNzcv(ArmEmitterContext context)
  104. {
  105. OpCodeSystem op = (OpCodeSystem)context.CurrOp;
  106. Operand t = GetIntOrZR(context, op.Rt);
  107. t = context.ConvertI64ToI32(t);
  108. Operand v = context.ShiftRightUI(t, Const((int)PState.VFlag));
  109. v = context.BitwiseAnd (v, Const(1));
  110. Operand c = context.ShiftRightUI(t, Const((int)PState.CFlag));
  111. c = context.BitwiseAnd (c, Const(1));
  112. Operand z = context.ShiftRightUI(t, Const((int)PState.ZFlag));
  113. z = context.BitwiseAnd (z, Const(1));
  114. Operand n = context.ShiftRightUI(t, Const((int)PState.NFlag));
  115. n = context.BitwiseAnd (n, Const(1));
  116. SetFlag(context, PState.VFlag, v);
  117. SetFlag(context, PState.CFlag, c);
  118. SetFlag(context, PState.ZFlag, z);
  119. SetFlag(context, PState.NFlag, n);
  120. }
  121. }
  122. }