AInstEmitSystem.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. using ChocolArm64.Decoder;
  2. using ChocolArm64.State;
  3. using ChocolArm64.Translation;
  4. using System;
  5. using System.Reflection;
  6. using System.Reflection.Emit;
  7. namespace ChocolArm64.Instruction
  8. {
  9. static partial class AInstEmit
  10. {
  11. public static void Hint(AILEmitterCtx Context)
  12. {
  13. //Execute as no-op.
  14. }
  15. public static void Isb(AILEmitterCtx Context)
  16. {
  17. //Execute as no-op.
  18. }
  19. public static void Mrs(AILEmitterCtx Context)
  20. {
  21. AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp;
  22. Context.EmitLdarg(ATranslatedSub.StateArgIdx);
  23. string PropName;
  24. switch (GetPackedId(Op))
  25. {
  26. case 0b11_011_0000_0000_001: PropName = nameof(AThreadState.CtrEl0); break;
  27. case 0b11_011_0000_0000_111: PropName = nameof(AThreadState.DczidEl0); break;
  28. case 0b11_011_0100_0100_000: PropName = nameof(AThreadState.Fpcr); break;
  29. case 0b11_011_0100_0100_001: PropName = nameof(AThreadState.Fpsr); break;
  30. case 0b11_011_1101_0000_010: PropName = nameof(AThreadState.TpidrEl0); break;
  31. case 0b11_011_1101_0000_011: PropName = nameof(AThreadState.Tpidr); break;
  32. case 0b11_011_1110_0000_000: PropName = nameof(AThreadState.CntfrqEl0); break;
  33. case 0b11_011_1110_0000_001: PropName = nameof(AThreadState.CntpctEl0); break;
  34. default: throw new NotImplementedException($"Unknown MRS at {Op.Position:x16}");
  35. }
  36. Context.EmitCallPropGet(typeof(AThreadState), PropName);
  37. PropertyInfo PropInfo = typeof(AThreadState).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(AILEmitterCtx Context)
  46. {
  47. AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp;
  48. Context.EmitLdarg(ATranslatedSub.StateArgIdx);
  49. Context.EmitLdintzr(Op.Rt);
  50. string PropName;
  51. switch (GetPackedId(Op))
  52. {
  53. case 0b11_011_0100_0100_000: PropName = nameof(AThreadState.Fpcr); break;
  54. case 0b11_011_0100_0100_001: PropName = nameof(AThreadState.Fpsr); break;
  55. case 0b11_011_1101_0000_010: PropName = nameof(AThreadState.TpidrEl0); break;
  56. default: throw new NotImplementedException($"Unknown MSR at {Op.Position:x16}");
  57. }
  58. PropertyInfo PropInfo = typeof(AThreadState).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(AThreadState), PropName);
  65. }
  66. public static void Nop(AILEmitterCtx Context)
  67. {
  68. //Do nothing.
  69. }
  70. public static void Sys(AILEmitterCtx 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. AOpCodeSystem Op = (AOpCodeSystem)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 << AThreadState.DczSizeLog2); Offs += 8)
  82. {
  83. Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
  84. Context.EmitLdintzr(Op.Rt);
  85. Context.EmitLdc_I(Offs);
  86. Context.Emit(OpCodes.Add);
  87. Context.EmitLdc_I8(0);
  88. AInstEmitMemoryHelper.EmitWriteCall(Context, 3);
  89. }
  90. break;
  91. }
  92. //No-op
  93. case 0b11_011_0111_1110_001: //DC CIVAC
  94. break;
  95. }
  96. }
  97. private static int GetPackedId(AOpCodeSystem Op)
  98. {
  99. int Id;
  100. Id = Op.Op2 << 0;
  101. Id |= Op.CRm << 3;
  102. Id |= Op.CRn << 7;
  103. Id |= Op.Op1 << 11;
  104. Id |= Op.Op0 << 14;
  105. return Id;
  106. }
  107. }
  108. }