InstEmitSystem.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. using ARMeilleure.Decoders;
  2. using ARMeilleure.IntermediateRepresentation;
  3. using ARMeilleure.Translation;
  4. using System;
  5. using static ARMeilleure.Instructions.InstEmitHelper;
  6. using static ARMeilleure.IntermediateRepresentation.OperandHelper;
  7. namespace ARMeilleure.Instructions
  8. {
  9. static partial class InstEmit
  10. {
  11. private const int DczSizeLog2 = 4;
  12. public static void Hint(ArmEmitterContext context)
  13. {
  14. // Execute as no-op.
  15. }
  16. public static void Isb(ArmEmitterContext context)
  17. {
  18. // Execute as no-op.
  19. }
  20. public static void Mrs(ArmEmitterContext context)
  21. {
  22. OpCodeSystem op = (OpCodeSystem)context.CurrOp;
  23. Delegate dlg;
  24. switch (GetPackedId(op))
  25. {
  26. case 0b11_011_0000_0000_001: dlg = new _U64(NativeInterface.GetCtrEl0); break;
  27. case 0b11_011_0000_0000_111: dlg = new _U64(NativeInterface.GetDczidEl0); break;
  28. case 0b11_011_0100_0100_000: dlg = new _U64(NativeInterface.GetFpcr); break;
  29. case 0b11_011_0100_0100_001: dlg = new _U64(NativeInterface.GetFpsr); break;
  30. case 0b11_011_1101_0000_010: dlg = new _U64(NativeInterface.GetTpidrEl0); break;
  31. case 0b11_011_1101_0000_011: dlg = new _U64(NativeInterface.GetTpidr); break;
  32. case 0b11_011_1110_0000_000: dlg = new _U64(NativeInterface.GetCntfrqEl0); break;
  33. case 0b11_011_1110_0000_001: dlg = new _U64(NativeInterface.GetCntpctEl0); break;
  34. default: throw new NotImplementedException($"Unknown MRS 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
  35. }
  36. SetIntOrZR(context, op.Rt, context.Call(dlg));
  37. }
  38. public static void Msr(ArmEmitterContext context)
  39. {
  40. OpCodeSystem op = (OpCodeSystem)context.CurrOp;
  41. Delegate dlg;
  42. switch (GetPackedId(op))
  43. {
  44. case 0b11_011_0100_0100_000: dlg = new _Void_U64(NativeInterface.SetFpcr); break;
  45. case 0b11_011_0100_0100_001: dlg = new _Void_U64(NativeInterface.SetFpsr); break;
  46. case 0b11_011_1101_0000_010: dlg = new _Void_U64(NativeInterface.SetTpidrEl0); break;
  47. default: throw new NotImplementedException($"Unknown MSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
  48. }
  49. context.Call(dlg, GetIntOrZR(context, op.Rt));
  50. }
  51. public static void Nop(ArmEmitterContext context)
  52. {
  53. // Do nothing.
  54. }
  55. public static void Sys(ArmEmitterContext context)
  56. {
  57. // This instruction is used to do some operations on the CPU like cache invalidation,
  58. // address translation and the like.
  59. // We treat it as no-op here since we don't have any cache being emulated anyway.
  60. OpCodeSystem op = (OpCodeSystem)context.CurrOp;
  61. switch (GetPackedId(op))
  62. {
  63. case 0b11_011_0111_0100_001:
  64. {
  65. // DC ZVA
  66. Operand t = GetIntOrZR(context, op.Rt);
  67. for (long offset = 0; offset < (4 << DczSizeLog2); offset += 8)
  68. {
  69. Operand address = context.Add(t, Const(offset));
  70. context.Call(new _Void_U64_U64(NativeInterface.WriteUInt64), address, Const(0L));
  71. }
  72. break;
  73. }
  74. // No-op
  75. case 0b11_011_0111_1110_001: //DC CIVAC
  76. break;
  77. }
  78. }
  79. private static int GetPackedId(OpCodeSystem op)
  80. {
  81. int id;
  82. id = op.Op2 << 0;
  83. id |= op.CRm << 3;
  84. id |= op.CRn << 7;
  85. id |= op.Op1 << 11;
  86. id |= op.Op0 << 14;
  87. return id;
  88. }
  89. }
  90. }