InstEmitSystem.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. using ChocolArm64.Decoders;
  2. using ChocolArm64.State;
  3. using ChocolArm64.Translation;
  4. using System;
  5. using System.Reflection;
  6. using System.Reflection.Emit;
  7. namespace ChocolArm64.Instructions
  8. {
  9. static partial class InstEmit
  10. {
  11. public static void Hint(ILEmitterCtx context)
  12. {
  13. // Execute as no-op.
  14. }
  15. public static void Isb(ILEmitterCtx context)
  16. {
  17. // Execute as no-op.
  18. }
  19. public static void Mrs(ILEmitterCtx context)
  20. {
  21. OpCodeSystem64 op = (OpCodeSystem64)context.CurrOp;
  22. context.EmitLdarg(TranslatedSub.StateArgIdx);
  23. string propName;
  24. switch (GetPackedId(op))
  25. {
  26. case 0b11_011_0000_0000_001: propName = nameof(CpuThreadState.CtrEl0); break;
  27. case 0b11_011_0000_0000_111: propName = nameof(CpuThreadState.DczidEl0); break;
  28. case 0b11_011_0100_0100_000: propName = nameof(CpuThreadState.CFpcr); break;
  29. case 0b11_011_0100_0100_001: propName = nameof(CpuThreadState.CFpsr); break;
  30. case 0b11_011_1101_0000_010: propName = nameof(CpuThreadState.TpidrEl0); break;
  31. case 0b11_011_1101_0000_011: propName = nameof(CpuThreadState.Tpidr); break;
  32. case 0b11_011_1110_0000_000: propName = nameof(CpuThreadState.CntfrqEl0); break;
  33. case 0b11_011_1110_0000_001: propName = nameof(CpuThreadState.CntpctEl0); break;
  34. default: throw new NotImplementedException($"Unknown MRS at {op.Position:x16}");
  35. }
  36. context.EmitCallPropGet(typeof(CpuThreadState), propName);
  37. PropertyInfo propInfo = typeof(CpuThreadState).GetProperty(propName);
  38. if (propInfo.PropertyType != typeof(long) &&
  39. propInfo.PropertyType != typeof(ulong))
  40. {
  41. context.Emit(OpCodes.Conv_U8);
  42. }
  43. context.EmitStintzr(op.Rt);
  44. }
  45. public static void Msr(ILEmitterCtx context)
  46. {
  47. OpCodeSystem64 op = (OpCodeSystem64)context.CurrOp;
  48. context.EmitLdarg(TranslatedSub.StateArgIdx);
  49. context.EmitLdintzr(op.Rt);
  50. string propName;
  51. switch (GetPackedId(op))
  52. {
  53. case 0b11_011_0100_0100_000: propName = nameof(CpuThreadState.CFpcr); break;
  54. case 0b11_011_0100_0100_001: propName = nameof(CpuThreadState.CFpsr); break;
  55. case 0b11_011_1101_0000_010: propName = nameof(CpuThreadState.TpidrEl0); break;
  56. default: throw new NotImplementedException($"Unknown MSR at {op.Position:x16}");
  57. }
  58. PropertyInfo propInfo = typeof(CpuThreadState).GetProperty(propName);
  59. if (propInfo.PropertyType != typeof(long) &&
  60. propInfo.PropertyType != typeof(ulong))
  61. {
  62. context.Emit(OpCodes.Conv_U4);
  63. }
  64. context.EmitCallPropSet(typeof(CpuThreadState), propName);
  65. }
  66. public static void Nop(ILEmitterCtx context)
  67. {
  68. // Do nothing.
  69. }
  70. public static void Sys(ILEmitterCtx context)
  71. {
  72. // This instruction is used to do some operations on the CPU like cache invalidation,
  73. // address translation and the like.
  74. // We treat it as no-op here since we don't have any cache being emulated anyway.
  75. OpCodeSystem64 op = (OpCodeSystem64)context.CurrOp;
  76. switch (GetPackedId(op))
  77. {
  78. case 0b11_011_0111_0100_001:
  79. {
  80. // DC ZVA
  81. for (int offs = 0; offs < (4 << CpuThreadState.DczSizeLog2); offs += 8)
  82. {
  83. context.EmitLdintzr(op.Rt);
  84. context.EmitLdc_I(offs);
  85. context.Emit(OpCodes.Add);
  86. context.EmitLdc_I8(0);
  87. InstEmitMemoryHelper.EmitWriteCall(context, 3);
  88. }
  89. break;
  90. }
  91. // No-op
  92. case 0b11_011_0111_1110_001: //DC CIVAC
  93. break;
  94. }
  95. }
  96. private static int GetPackedId(OpCodeSystem64 op)
  97. {
  98. int id;
  99. id = op.Op2 << 0;
  100. id |= op.CRm << 3;
  101. id |= op.CRn << 7;
  102. id |= op.Op1 << 11;
  103. id |= op.Op0 << 14;
  104. return id;
  105. }
  106. }
  107. }