| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352 |
- using ARMeilleure.Decoders;
- using ARMeilleure.IntermediateRepresentation;
- using ARMeilleure.State;
- using ARMeilleure.Translation;
- using static ARMeilleure.Instructions.InstEmitHelper;
- using static ARMeilleure.Instructions.InstEmitMemoryHelper;
- using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
- namespace ARMeilleure.Instructions
- {
- static partial class InstEmit32
- {
- public static void Vld1(ArmEmitterContext context)
- {
- EmitVStoreOrLoadN(context, 1, true);
- }
- public static void Vld2(ArmEmitterContext context)
- {
- EmitVStoreOrLoadN(context, 2, true);
- }
- public static void Vld3(ArmEmitterContext context)
- {
- EmitVStoreOrLoadN(context, 3, true);
- }
- public static void Vld4(ArmEmitterContext context)
- {
- EmitVStoreOrLoadN(context, 4, true);
- }
- public static void Vst1(ArmEmitterContext context)
- {
- EmitVStoreOrLoadN(context, 1, false);
- }
- public static void Vst2(ArmEmitterContext context)
- {
- EmitVStoreOrLoadN(context, 2, false);
- }
- public static void Vst3(ArmEmitterContext context)
- {
- EmitVStoreOrLoadN(context, 3, false);
- }
- public static void Vst4(ArmEmitterContext context)
- {
- EmitVStoreOrLoadN(context, 4, false);
- }
- public static void EmitVStoreOrLoadN(ArmEmitterContext context, int count, bool load)
- {
- if (context.CurrOp is OpCode32SimdMemSingle)
- {
- OpCode32SimdMemSingle op = (OpCode32SimdMemSingle)context.CurrOp;
- int eBytes = 1 << op.Size;
- Operand n = context.Copy(GetIntA32(context, op.Rn));
- // TODO: Check alignment.
- int offset = 0;
- int d = op.Vd;
- for (int i = 0; i < count; i++)
- {
- // Accesses an element from a double simd register.
- Operand address = context.Add(n, Const(offset));
- if (eBytes == 8)
- {
- if (load)
- {
- EmitDVectorLoad(context, address, d);
- }
- else
- {
- EmitDVectorStore(context, address, d);
- }
- }
- else
- {
- int index = ((d & 1) << (3 - op.Size)) + op.Index;
- if (load)
- {
- if (op.Replicate)
- {
- var regs = (count > 1) ? 1 : op.Increment;
- for (int reg = 0; reg < regs; reg++)
- {
- int dreg = reg + d;
- int rIndex = ((dreg & 1) << (3 - op.Size));
- int limit = rIndex + (1 << (3 - op.Size));
- while (rIndex < limit)
- {
- EmitLoadSimd(context, address, GetVecA32(dreg >> 1), dreg >> 1, rIndex++, op.Size);
- }
- }
- }
- else
- {
- EmitLoadSimd(context, address, GetVecA32(d >> 1), d >> 1, index, op.Size);
- }
- }
- else
- {
- EmitStoreSimd(context, address, d >> 1, index, op.Size);
- }
- }
- offset += eBytes;
- d += op.Increment;
- }
- if (op.WBack)
- {
- if (op.RegisterIndex)
- {
- Operand m = GetIntA32(context, op.Rm);
- SetIntA32(context, op.Rn, context.Add(n, m));
- }
- else
- {
- SetIntA32(context, op.Rn, context.Add(n, Const(count * eBytes)));
- }
- }
- }
- else
- {
- OpCode32SimdMemPair op = (OpCode32SimdMemPair)context.CurrOp;
- int increment = count > 1 ? op.Increment : 1;
- int eBytes = 1 << op.Size;
- Operand n = context.Copy(GetIntA32(context, op.Rn));
- int offset = 0;
- int d = op.Vd;
- for (int reg = 0; reg < op.Regs; reg++)
- {
- for (int elem = 0; elem < op.Elems; elem++)
- {
- int elemD = d + reg;
- for (int i = 0; i < count; i++)
- {
- // Accesses an element from a double simd register,
- // add ebytes for each element.
- Operand address = context.Add(n, Const(offset));
- int index = ((elemD & 1) << (3 - op.Size)) + elem;
- if (eBytes == 8)
- {
- if (load)
- {
- EmitDVectorLoad(context, address, elemD);
- }
- else
- {
- EmitDVectorStore(context, address, elemD);
- }
- }
- else
- {
- if (load)
- {
- EmitLoadSimd(context, address, GetVecA32(elemD >> 1), elemD >> 1, index, op.Size);
- }
- else
- {
- EmitStoreSimd(context, address, elemD >> 1, index, op.Size);
- }
- }
- offset += eBytes;
- elemD += increment;
- }
- }
- }
- if (op.WBack)
- {
- if (op.RegisterIndex)
- {
- Operand m = GetIntA32(context, op.Rm);
- SetIntA32(context, op.Rn, context.Add(n, m));
- }
- else
- {
- SetIntA32(context, op.Rn, context.Add(n, Const(count * 8 * op.Regs)));
- }
- }
- }
- }
- public static void Vldm(ArmEmitterContext context)
- {
- OpCode32SimdMemMult op = (OpCode32SimdMemMult)context.CurrOp;
- Operand n = context.Copy(GetIntA32(context, op.Rn));
- Operand baseAddress = context.Add(n, Const(op.Offset));
- bool writeBack = op.PostOffset != 0;
- if (writeBack)
- {
- SetIntA32(context, op.Rn, context.Add(n, Const(op.PostOffset)));
- }
- int range = op.RegisterRange;
- int sReg = (op.DoubleWidth) ? (op.Vd << 1) : op.Vd;
- int offset = 0;
- int byteSize = 4;
- for (int num = 0; num < range; num++, sReg++)
- {
- Operand address = context.Add(baseAddress, Const(offset));
- Operand vec = GetVecA32(sReg >> 2);
- EmitLoadSimd(context, address, vec, sReg >> 2, sReg & 3, WordSizeLog2);
- offset += byteSize;
- }
- }
- public static void Vstm(ArmEmitterContext context)
- {
- OpCode32SimdMemMult op = (OpCode32SimdMemMult)context.CurrOp;
- Operand n = context.Copy(GetIntA32(context, op.Rn));
- Operand baseAddress = context.Add(n, Const(op.Offset));
- bool writeBack = op.PostOffset != 0;
- if (writeBack)
- {
- SetIntA32(context, op.Rn, context.Add(n, Const(op.PostOffset)));
- }
- int offset = 0;
- int range = op.RegisterRange;
- int sReg = (op.DoubleWidth) ? (op.Vd << 1) : op.Vd;
- int byteSize = 4;
- for (int num = 0; num < range; num++, sReg++)
- {
- Operand address = context.Add(baseAddress, Const(offset));
- EmitStoreSimd(context, address, sReg >> 2, sReg & 3, WordSizeLog2);
- offset += byteSize;
- }
- }
- public static void Vldr(ArmEmitterContext context)
- {
- EmitVLoadOrStore(context, AccessType.Load);
- }
- public static void Vstr(ArmEmitterContext context)
- {
- EmitVLoadOrStore(context, AccessType.Store);
- }
- private static void EmitDVectorStore(ArmEmitterContext context, Operand address, int vecD)
- {
- int vecQ = vecD >> 1;
- int vecSElem = (vecD & 1) << 1;
- Operand lblBigEndian = Label();
- Operand lblEnd = Label();
- context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag));
- EmitStoreSimd(context, address, vecQ, vecSElem, WordSizeLog2);
- EmitStoreSimd(context, context.Add(address, Const(4)), vecQ, vecSElem | 1, WordSizeLog2);
- context.Branch(lblEnd);
- context.MarkLabel(lblBigEndian);
- EmitStoreSimd(context, address, vecQ, vecSElem | 1, WordSizeLog2);
- EmitStoreSimd(context, context.Add(address, Const(4)), vecQ, vecSElem, WordSizeLog2);
- context.MarkLabel(lblEnd);
- }
- private static void EmitDVectorLoad(ArmEmitterContext context, Operand address, int vecD)
- {
- int vecQ = vecD >> 1;
- int vecSElem = (vecD & 1) << 1;
- Operand vec = GetVecA32(vecQ);
- Operand lblBigEndian = Label();
- Operand lblEnd = Label();
- context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag));
- EmitLoadSimd(context, address, vec, vecQ, vecSElem, WordSizeLog2);
- EmitLoadSimd(context, context.Add(address, Const(4)), vec, vecQ, vecSElem | 1, WordSizeLog2);
- context.Branch(lblEnd);
- context.MarkLabel(lblBigEndian);
- EmitLoadSimd(context, address, vec, vecQ, vecSElem | 1, WordSizeLog2);
- EmitLoadSimd(context, context.Add(address, Const(4)), vec, vecQ, vecSElem, WordSizeLog2);
- context.MarkLabel(lblEnd);
- }
- private static void EmitVLoadOrStore(ArmEmitterContext context, AccessType accType)
- {
- OpCode32SimdMemImm op = (OpCode32SimdMemImm)context.CurrOp;
- Operand n = context.Copy(GetIntA32(context, op.Rn));
- Operand m = GetMemM(context, setCarry: false);
- Operand address = op.Add
- ? context.Add(n, m)
- : context.Subtract(n, m);
- int size = op.Size;
- if ((accType & AccessType.Load) != 0)
- {
- if (size == DWordSizeLog2)
- {
- EmitDVectorLoad(context, address, op.Vd);
- }
- else
- {
- Operand vec = GetVecA32(op.Vd >> 2);
- EmitLoadSimd(context, address, vec, op.Vd >> 2, (op.Vd & 3) << (2 - size), size);
- }
- }
- else
- {
- if (size == DWordSizeLog2)
- {
- EmitDVectorStore(context, address, op.Vd);
- }
- else
- {
- EmitStoreSimd(context, address, op.Vd >> 2, (op.Vd & 3) << (2 - size), size);
- }
- }
- }
- }
- }
|