InstEmitSimdMemory.cs
1 using ARMeilleure.Decoders; 2 using ARMeilleure.IntermediateRepresentation; 3 using ARMeilleure.State; 4 using ARMeilleure.Translation; 5 using System.Diagnostics; 6 7 using static ARMeilleure.Instructions.InstEmitHelper; 8 using static ARMeilleure.Instructions.InstEmitMemoryHelper; 9 using static ARMeilleure.IntermediateRepresentation.Operand.Factory; 10 11 namespace ARMeilleure.Instructions 12 { 13 static partial class InstEmit 14 { 15 public static void Ld__Vms(ArmEmitterContext context) 16 { 17 EmitSimdMemMs(context, isLoad: true); 18 } 19 20 public static void Ld__Vss(ArmEmitterContext context) 21 { 22 EmitSimdMemSs(context, isLoad: true); 23 } 24 25 public static void St__Vms(ArmEmitterContext context) 26 { 27 EmitSimdMemMs(context, isLoad: false); 28 } 29 30 public static void St__Vss(ArmEmitterContext context) 31 { 32 EmitSimdMemSs(context, isLoad: false); 33 } 34 35 private static void EmitSimdMemMs(ArmEmitterContext context, bool isLoad) 36 { 37 OpCodeSimdMemMs op = (OpCodeSimdMemMs)context.CurrOp; 38 39 Operand n = GetIntOrSP(context, op.Rn); 40 41 long offset = 0; 42 43 #pragma warning disable IDE0055 // Disable formatting 44 for (int rep = 0; rep < op.Reps; rep++) 45 for (int elem = 0; elem < op.Elems; elem++) 46 for (int sElem = 0; sElem < op.SElems; sElem++) 47 { 48 int rtt = (op.Rt + rep + sElem) & 0x1f; 49 50 Operand tt = GetVec(rtt); 51 52 Operand address = context.Add(n, Const(offset)); 53 54 if (isLoad) 55 { 56 EmitLoadSimd(context, address, tt, rtt, elem, op.Size); 57 58 if (op.RegisterSize == RegisterSize.Simd64 && elem == op.Elems - 1) 59 { 60 context.Copy(tt, context.VectorZeroUpper64(tt)); 61 } 62 } 63 else 64 { 65 EmitStoreSimd(context, address, rtt, elem, op.Size); 66 } 67 68 offset += 1 << op.Size; 69 } 70 #pragma warning restore IDE0055 71 72 if (op.WBack) 73 { 74 EmitSimdMemWBack(context, offset); 75 } 76 } 77 78 private static void EmitSimdMemSs(ArmEmitterContext context, bool isLoad) 79 { 80 OpCodeSimdMemSs op = (OpCodeSimdMemSs)context.CurrOp; 81 82 Operand n = GetIntOrSP(context, op.Rn); 83 84 long offset = 0; 85 86 if (op.Replicate) 87 { 88 // Only loads uses the replicate mode. 89 Debug.Assert(isLoad, "Replicate mode is not valid for stores."); 90 91 int elems = op.GetBytesCount() >> op.Size; 92 93 for (int sElem = 0; sElem < op.SElems; sElem++) 94 { 95 int rt = (op.Rt + sElem) & 0x1f; 96 97 Operand t = GetVec(rt); 98 99 Operand address = context.Add(n, Const(offset)); 100 101 for (int index = 0; index < elems; index++) 102 { 103 EmitLoadSimd(context, address, t, rt, index, op.Size); 104 } 105 106 if (op.RegisterSize == RegisterSize.Simd64) 107 { 108 context.Copy(t, context.VectorZeroUpper64(t)); 109 } 110 111 offset += 1 << op.Size; 112 } 113 } 114 else 115 { 116 for (int sElem = 0; sElem < op.SElems; sElem++) 117 { 118 int rt = (op.Rt + sElem) & 0x1f; 119 120 Operand t = GetVec(rt); 121 122 Operand address = context.Add(n, Const(offset)); 123 124 if (isLoad) 125 { 126 EmitLoadSimd(context, address, t, rt, op.Index, op.Size); 127 } 128 else 129 { 130 EmitStoreSimd(context, address, rt, op.Index, op.Size); 131 } 132 133 offset += 1 << op.Size; 134 } 135 } 136 137 if (op.WBack) 138 { 139 EmitSimdMemWBack(context, offset); 140 } 141 } 142 143 private static void EmitSimdMemWBack(ArmEmitterContext context, long offset) 144 { 145 OpCodeMemReg op = (OpCodeMemReg)context.CurrOp; 146 147 Operand n = GetIntOrSP(context, op.Rn); 148 Operand m; 149 150 if (op.Rm != RegisterAlias.Zr) 151 { 152 m = GetIntOrZR(context, op.Rm); 153 } 154 else 155 { 156 m = Const(offset); 157 } 158 159 context.Copy(n, context.Add(n, m)); 160 } 161 } 162 }