AInstEmitSimdMemory.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. using ChocolArm64.Decoder;
  2. using ChocolArm64.State;
  3. using ChocolArm64.Translation;
  4. using System.Reflection.Emit;
  5. using static ChocolArm64.Instruction.AInstEmitMemoryHelper;
  6. using static ChocolArm64.Instruction.AInstEmitSimdHelper;
  7. namespace ChocolArm64.Instruction
  8. {
  9. static partial class AInstEmit
  10. {
  11. public static void Ld__Vms(AILEmitterCtx Context)
  12. {
  13. EmitSimdMemMs(Context, IsLoad: true);
  14. }
  15. public static void Ld__Vss(AILEmitterCtx Context)
  16. {
  17. EmitSimdMemSs(Context, IsLoad: true);
  18. }
  19. public static void St__Vms(AILEmitterCtx Context)
  20. {
  21. EmitSimdMemMs(Context, IsLoad: false);
  22. }
  23. public static void St__Vss(AILEmitterCtx Context)
  24. {
  25. EmitSimdMemSs(Context, IsLoad: false);
  26. }
  27. private static void EmitSimdMemMs(AILEmitterCtx Context, bool IsLoad)
  28. {
  29. AOpCodeSimdMemMs Op = (AOpCodeSimdMemMs)Context.CurrOp;
  30. int Offset = 0;
  31. for (int Rep = 0; Rep < Op.Reps; Rep++)
  32. for (int Elem = 0; Elem < Op.Elems; Elem++)
  33. for (int SElem = 0; SElem < Op.SElems; SElem++)
  34. {
  35. int Rtt = (Op.Rt + Rep + SElem) & 0x1f;
  36. if (IsLoad)
  37. {
  38. Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
  39. Context.EmitLdint(Op.Rn);
  40. Context.EmitLdc_I8(Offset);
  41. Context.Emit(OpCodes.Add);
  42. EmitReadZxCall(Context, Op.Size);
  43. EmitVectorInsert(Context, Rtt, Elem, Op.Size);
  44. if (Op.RegisterSize == ARegisterSize.SIMD64 && Elem == Op.Elems - 1)
  45. {
  46. EmitVectorZeroUpper(Context, Rtt);
  47. }
  48. }
  49. else
  50. {
  51. Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
  52. Context.EmitLdint(Op.Rn);
  53. Context.EmitLdc_I8(Offset);
  54. Context.Emit(OpCodes.Add);
  55. EmitVectorExtractZx(Context, Rtt, Elem, Op.Size);
  56. EmitWriteCall(Context, Op.Size);
  57. }
  58. Offset += 1 << Op.Size;
  59. }
  60. if (Op.WBack)
  61. {
  62. EmitSimdMemWBack(Context, Offset);
  63. }
  64. }
  65. private static void EmitSimdMemSs(AILEmitterCtx Context, bool IsLoad)
  66. {
  67. AOpCodeSimdMemSs Op = (AOpCodeSimdMemSs)Context.CurrOp;
  68. //TODO: Replicate mode.
  69. int Offset = 0;
  70. for (int SElem = 0; SElem < Op.SElems; SElem++)
  71. {
  72. int Rt = (Op.Rt + SElem) & 0x1f;
  73. if (IsLoad)
  74. {
  75. Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
  76. Context.EmitLdint(Op.Rn);
  77. Context.EmitLdc_I8(Offset);
  78. Context.Emit(OpCodes.Add);
  79. EmitReadZxCall(Context, Op.Size);
  80. EmitVectorInsert(Context, Rt, Op.Index, Op.Size);
  81. if (Op.RegisterSize == ARegisterSize.SIMD64)
  82. {
  83. EmitVectorZeroUpper(Context, Rt);
  84. }
  85. }
  86. else
  87. {
  88. Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
  89. Context.EmitLdint(Op.Rn);
  90. Context.EmitLdc_I8(Offset);
  91. Context.Emit(OpCodes.Add);
  92. EmitVectorExtractZx(Context, Rt, Op.Index, Op.Size);
  93. EmitWriteCall(Context, Op.Size);
  94. }
  95. Offset += 1 << Op.Size;
  96. }
  97. if (Op.WBack)
  98. {
  99. EmitSimdMemWBack(Context, Offset);
  100. }
  101. }
  102. private static void EmitSimdMemWBack(AILEmitterCtx Context, int Offset)
  103. {
  104. AOpCodeMemReg Op = (AOpCodeMemReg)Context.CurrOp;
  105. Context.EmitLdint(Op.Rn);
  106. if (Op.Rm != ARegisters.ZRIndex)
  107. {
  108. Context.EmitLdint(Op.Rm);
  109. }
  110. else
  111. {
  112. Context.EmitLdc_I8(Offset);
  113. }
  114. Context.Emit(OpCodes.Add);
  115. Context.EmitStint(Op.Rn);
  116. }
  117. }
  118. }