InstEmitSystem.cs 6.7 KB

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