| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580 |
- using ChocolArm64.Decoders;
- using ChocolArm64.State;
- using ChocolArm64.Translation;
- using System;
- using System.Reflection;
- using System.Reflection.Emit;
- using System.Runtime.Intrinsics;
- using System.Runtime.Intrinsics.X86;
- namespace ChocolArm64.Instructions
- {
- static class InstEmitSimdHelper
- {
- public static readonly Type[] IntTypesPerSizeLog2 = new Type[]
- {
- typeof(sbyte),
- typeof(short),
- typeof(int),
- typeof(long)
- };
- public static readonly Type[] UIntTypesPerSizeLog2 = new Type[]
- {
- typeof(byte),
- typeof(ushort),
- typeof(uint),
- typeof(ulong)
- };
- public static readonly Type[] VectorIntTypesPerSizeLog2 = new Type[]
- {
- typeof(Vector128<sbyte>),
- typeof(Vector128<short>),
- typeof(Vector128<int>),
- typeof(Vector128<long>)
- };
- public static readonly Type[] VectorUIntTypesPerSizeLog2 = new Type[]
- {
- typeof(Vector128<byte>),
- typeof(Vector128<ushort>),
- typeof(Vector128<uint>),
- typeof(Vector128<ulong>)
- };
- [Flags]
- public enum OperFlags
- {
- Rd = 1 << 0,
- Rn = 1 << 1,
- Rm = 1 << 2,
- Ra = 1 << 3,
- RnRm = Rn | Rm,
- RdRn = Rd | Rn,
- RaRnRm = Ra | Rn | Rm,
- RdRnRm = Rd | Rn | Rm
- }
- public static int GetImmShl(OpCodeSimdShImm64 op)
- {
- return op.Imm - (8 << op.Size);
- }
- public static int GetImmShr(OpCodeSimdShImm64 op)
- {
- return (8 << (op.Size + 1)) - op.Imm;
- }
- public static void EmitSse2Op(ILEmitterCtx context, string name)
- {
- EmitSseOp(context, name, typeof(Sse2));
- }
- public static void EmitSse41Op(ILEmitterCtx context, string name)
- {
- EmitSseOp(context, name, typeof(Sse41));
- }
- public static void EmitSse42Op(ILEmitterCtx context, string name)
- {
- EmitSseOp(context, name, typeof(Sse42));
- }
- private static void EmitSseOp(ILEmitterCtx context, string name, Type type)
- {
- OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
- context.EmitLdvec(op.Rn);
- Type baseType = VectorIntTypesPerSizeLog2[op.Size];
- if (op is OpCodeSimdReg64 binOp)
- {
- context.EmitLdvec(binOp.Rm);
- context.EmitCall(type.GetMethod(name, new Type[] { baseType, baseType }));
- }
- else
- {
- context.EmitCall(type.GetMethod(name, new Type[] { baseType }));
- }
- context.EmitStvec(op.Rd);
- if (op.RegisterSize == RegisterSize.Simd64)
- {
- EmitVectorZeroUpper(context, op.Rd);
- }
- }
- public static void EmitScalarSseOrSse2OpF(ILEmitterCtx context, string name)
- {
- EmitSseOrSse2OpF(context, name, true);
- }
- public static void EmitVectorSseOrSse2OpF(ILEmitterCtx context, string name)
- {
- EmitSseOrSse2OpF(context, name, false);
- }
- public static void EmitSseOrSse2OpF(ILEmitterCtx context, string name, bool scalar)
- {
- OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
- int sizeF = op.Size & 1;
- context.EmitLdvec(op.Rn);
- Type type;
- Type baseType;
- if (sizeF == 0)
- {
- type = typeof(Sse);
- baseType = typeof(Vector128<float>);
- }
- else /* if (sizeF == 1) */
- {
- type = typeof(Sse2);
- baseType = typeof(Vector128<double>);
- }
- if (op is OpCodeSimdReg64 binOp)
- {
- context.EmitLdvec(binOp.Rm);
- context.EmitCall(type.GetMethod(name, new Type[] { baseType, baseType }));
- }
- else
- {
- context.EmitCall(type.GetMethod(name, new Type[] { baseType }));
- }
- context.EmitStvec(op.Rd);
- if (scalar)
- {
- if (sizeF == 0)
- {
- EmitVectorZero32_128(context, op.Rd);
- }
- else /* if (sizeF == 1) */
- {
- EmitVectorZeroUpper(context, op.Rd);
- }
- }
- else if (op.RegisterSize == RegisterSize.Simd64)
- {
- EmitVectorZeroUpper(context, op.Rd);
- }
- }
- public static void EmitUnaryMathCall(ILEmitterCtx context, string name)
- {
- IOpCodeSimd64 op = (IOpCodeSimd64)context.CurrOp;
- int sizeF = op.Size & 1;
- MethodInfo mthdInfo;
- if (sizeF == 0)
- {
- mthdInfo = typeof(MathF).GetMethod(name, new Type[] { typeof(float) });
- }
- else /* if (sizeF == 1) */
- {
- mthdInfo = typeof(Math).GetMethod(name, new Type[] { typeof(double) });
- }
- context.EmitCall(mthdInfo);
- }
- public static void EmitBinaryMathCall(ILEmitterCtx context, string name)
- {
- IOpCodeSimd64 op = (IOpCodeSimd64)context.CurrOp;
- int sizeF = op.Size & 1;
- MethodInfo mthdInfo;
- if (sizeF == 0)
- {
- mthdInfo = typeof(MathF).GetMethod(name, new Type[] { typeof(float), typeof(float) });
- }
- else /* if (sizeF == 1) */
- {
- mthdInfo = typeof(Math).GetMethod(name, new Type[] { typeof(double), typeof(double) });
- }
- context.EmitCall(mthdInfo);
- }
- public static void EmitRoundMathCall(ILEmitterCtx context, MidpointRounding roundMode)
- {
- IOpCodeSimd64 op = (IOpCodeSimd64)context.CurrOp;
- int sizeF = op.Size & 1;
- MethodInfo mthdInfo;
- if (sizeF == 0)
- {
- mthdInfo = typeof(MathF).GetMethod(nameof(MathF.Round), new Type[] { typeof(float), typeof(MidpointRounding) });
- }
- else /* if (sizeF == 1) */
- {
- mthdInfo = typeof(Math).GetMethod(nameof(Math.Round), new Type[] { typeof(double), typeof(MidpointRounding) });
- }
- context.EmitLdc_I4((int)roundMode);
- context.EmitCall(mthdInfo);
- }
- public static void EmitSoftFloatCall(ILEmitterCtx context, string name)
- {
- IOpCodeSimd64 op = (IOpCodeSimd64)context.CurrOp;
- int sizeF = op.Size & 1;
- Type type = sizeF == 0
- ? typeof(SoftFloat32)
- : typeof(SoftFloat64);
- context.EmitLdarg(TranslatedSub.StateArgIdx);
- context.EmitCall(type, name);
- }
- public static void EmitScalarBinaryOpByElemF(ILEmitterCtx context, Action emit)
- {
- OpCodeSimdRegElemF64 op = (OpCodeSimdRegElemF64)context.CurrOp;
- EmitScalarOpByElemF(context, emit, op.Index, ternary: false);
- }
- public static void EmitScalarTernaryOpByElemF(ILEmitterCtx context, Action emit)
- {
- OpCodeSimdRegElemF64 op = (OpCodeSimdRegElemF64)context.CurrOp;
- EmitScalarOpByElemF(context, emit, op.Index, ternary: true);
- }
- public static void EmitScalarOpByElemF(ILEmitterCtx context, Action emit, int elem, bool ternary)
- {
- OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
- int sizeF = op.Size & 1;
- if (ternary)
- {
- EmitVectorExtractF(context, op.Rd, 0, sizeF);
- }
- EmitVectorExtractF(context, op.Rn, 0, sizeF);
- EmitVectorExtractF(context, op.Rm, elem, sizeF);
- emit();
- EmitScalarSetF(context, op.Rd, sizeF);
- }
- public static void EmitScalarUnaryOpSx(ILEmitterCtx context, Action emit)
- {
- EmitScalarOp(context, emit, OperFlags.Rn, true);
- }
- public static void EmitScalarBinaryOpSx(ILEmitterCtx context, Action emit)
- {
- EmitScalarOp(context, emit, OperFlags.RnRm, true);
- }
- public static void EmitScalarUnaryOpZx(ILEmitterCtx context, Action emit)
- {
- EmitScalarOp(context, emit, OperFlags.Rn, false);
- }
- public static void EmitScalarBinaryOpZx(ILEmitterCtx context, Action emit)
- {
- EmitScalarOp(context, emit, OperFlags.RnRm, false);
- }
- public static void EmitScalarTernaryOpZx(ILEmitterCtx context, Action emit)
- {
- EmitScalarOp(context, emit, OperFlags.RdRnRm, false);
- }
- public static void EmitScalarOp(ILEmitterCtx context, Action emit, OperFlags opers, bool signed)
- {
- OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
- bool rd = (opers & OperFlags.Rd) != 0;
- bool rn = (opers & OperFlags.Rn) != 0;
- bool rm = (opers & OperFlags.Rm) != 0;
- if (rd)
- {
- EmitVectorExtract(context, op.Rd, 0, op.Size, signed);
- }
- if (rn)
- {
- EmitVectorExtract(context, op.Rn, 0, op.Size, signed);
- }
- if (rm)
- {
- EmitVectorExtract(context, ((OpCodeSimdReg64)op).Rm, 0, op.Size, signed);
- }
- emit();
- EmitScalarSet(context, op.Rd, op.Size);
- }
- public static void EmitScalarUnaryOpF(ILEmitterCtx context, Action emit)
- {
- EmitScalarOpF(context, emit, OperFlags.Rn);
- }
- public static void EmitScalarBinaryOpF(ILEmitterCtx context, Action emit)
- {
- EmitScalarOpF(context, emit, OperFlags.RnRm);
- }
- public static void EmitScalarTernaryRaOpF(ILEmitterCtx context, Action emit)
- {
- EmitScalarOpF(context, emit, OperFlags.RaRnRm);
- }
- public static void EmitScalarOpF(ILEmitterCtx context, Action emit, OperFlags opers)
- {
- OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
- int sizeF = op.Size & 1;
- bool ra = (opers & OperFlags.Ra) != 0;
- bool rn = (opers & OperFlags.Rn) != 0;
- bool rm = (opers & OperFlags.Rm) != 0;
- if (ra)
- {
- EmitVectorExtractF(context, ((OpCodeSimdReg64)op).Ra, 0, sizeF);
- }
- if (rn)
- {
- EmitVectorExtractF(context, op.Rn, 0, sizeF);
- }
- if (rm)
- {
- EmitVectorExtractF(context, ((OpCodeSimdReg64)op).Rm, 0, sizeF);
- }
- emit();
- EmitScalarSetF(context, op.Rd, sizeF);
- }
- public static void EmitVectorUnaryOpF(ILEmitterCtx context, Action emit)
- {
- EmitVectorOpF(context, emit, OperFlags.Rn);
- }
- public static void EmitVectorBinaryOpF(ILEmitterCtx context, Action emit)
- {
- EmitVectorOpF(context, emit, OperFlags.RnRm);
- }
- public static void EmitVectorTernaryOpF(ILEmitterCtx context, Action emit)
- {
- EmitVectorOpF(context, emit, OperFlags.RdRnRm);
- }
- public static void EmitVectorOpF(ILEmitterCtx context, Action emit, OperFlags opers)
- {
- OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
- int sizeF = op.Size & 1;
- int bytes = op.GetBitsCount() >> 3;
- int elems = bytes >> sizeF + 2;
- bool rd = (opers & OperFlags.Rd) != 0;
- bool rn = (opers & OperFlags.Rn) != 0;
- bool rm = (opers & OperFlags.Rm) != 0;
- for (int index = 0; index < elems; index++)
- {
- if (rd)
- {
- EmitVectorExtractF(context, op.Rd, index, sizeF);
- }
- if (rn)
- {
- EmitVectorExtractF(context, op.Rn, index, sizeF);
- }
- if (rm)
- {
- EmitVectorExtractF(context, ((OpCodeSimdReg64)op).Rm, index, sizeF);
- }
- emit();
- EmitVectorInsertF(context, op.Rd, index, sizeF);
- }
- if (op.RegisterSize == RegisterSize.Simd64)
- {
- EmitVectorZeroUpper(context, op.Rd);
- }
- }
- public static void EmitVectorBinaryOpByElemF(ILEmitterCtx context, Action emit)
- {
- OpCodeSimdRegElemF64 op = (OpCodeSimdRegElemF64)context.CurrOp;
- EmitVectorOpByElemF(context, emit, op.Index, ternary: false);
- }
- public static void EmitVectorTernaryOpByElemF(ILEmitterCtx context, Action emit)
- {
- OpCodeSimdRegElemF64 op = (OpCodeSimdRegElemF64)context.CurrOp;
- EmitVectorOpByElemF(context, emit, op.Index, ternary: true);
- }
- public static void EmitVectorOpByElemF(ILEmitterCtx context, Action emit, int elem, bool ternary)
- {
- OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
- int sizeF = op.Size & 1;
- int bytes = op.GetBitsCount() >> 3;
- int elems = bytes >> sizeF + 2;
- for (int index = 0; index < elems; index++)
- {
- if (ternary)
- {
- EmitVectorExtractF(context, op.Rd, index, sizeF);
- }
- EmitVectorExtractF(context, op.Rn, index, sizeF);
- EmitVectorExtractF(context, op.Rm, elem, sizeF);
- emit();
- EmitVectorInsertTmpF(context, index, sizeF);
- }
- context.EmitLdvectmp();
- context.EmitStvec(op.Rd);
- if (op.RegisterSize == RegisterSize.Simd64)
- {
- EmitVectorZeroUpper(context, op.Rd);
- }
- }
- public static void EmitVectorUnaryOpSx(ILEmitterCtx context, Action emit)
- {
- EmitVectorOp(context, emit, OperFlags.Rn, true);
- }
- public static void EmitVectorBinaryOpSx(ILEmitterCtx context, Action emit)
- {
- EmitVectorOp(context, emit, OperFlags.RnRm, true);
- }
- public static void EmitVectorTernaryOpSx(ILEmitterCtx context, Action emit)
- {
- EmitVectorOp(context, emit, OperFlags.RdRnRm, true);
- }
- public static void EmitVectorUnaryOpZx(ILEmitterCtx context, Action emit)
- {
- EmitVectorOp(context, emit, OperFlags.Rn, false);
- }
- public static void EmitVectorBinaryOpZx(ILEmitterCtx context, Action emit)
- {
- EmitVectorOp(context, emit, OperFlags.RnRm, false);
- }
- public static void EmitVectorTernaryOpZx(ILEmitterCtx context, Action emit)
- {
- EmitVectorOp(context, emit, OperFlags.RdRnRm, false);
- }
- public static void EmitVectorOp(ILEmitterCtx context, Action emit, OperFlags opers, bool signed)
- {
- OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
- int bytes = op.GetBitsCount() >> 3;
- int elems = bytes >> op.Size;
- bool rd = (opers & OperFlags.Rd) != 0;
- bool rn = (opers & OperFlags.Rn) != 0;
- bool rm = (opers & OperFlags.Rm) != 0;
- for (int index = 0; index < elems; index++)
- {
- if (rd)
- {
- EmitVectorExtract(context, op.Rd, index, op.Size, signed);
- }
- if (rn)
- {
- EmitVectorExtract(context, op.Rn, index, op.Size, signed);
- }
- if (rm)
- {
- EmitVectorExtract(context, ((OpCodeSimdReg64)op).Rm, index, op.Size, signed);
- }
- emit();
- EmitVectorInsert(context, op.Rd, index, op.Size);
- }
- if (op.RegisterSize == RegisterSize.Simd64)
- {
- EmitVectorZeroUpper(context, op.Rd);
- }
- }
- public static void EmitVectorBinaryOpByElemSx(ILEmitterCtx context, Action emit)
- {
- OpCodeSimdRegElem64 op = (OpCodeSimdRegElem64)context.CurrOp;
- EmitVectorOpByElem(context, emit, op.Index, ternary: false, signed: true);
- }
- public static void EmitVectorBinaryOpByElemZx(ILEmitterCtx context, Action emit)
- {
- OpCodeSimdRegElem64 op = (OpCodeSimdRegElem64)context.CurrOp;
- EmitVectorOpByElem(context, emit, op.Index, ternary: false, signed: false);
- }
- public static void EmitVectorTernaryOpByElemZx(ILEmitterCtx context, Action emit)
- {
- OpCodeSimdRegElem64 op = (OpCodeSimdRegElem64)context.CurrOp;
- EmitVectorOpByElem(context, emit, op.Index, ternary: true, signed: false);
- }
- public static void EmitVectorOpByElem(ILEmitterCtx context, Action emit, int elem, bool ternary, bool signed)
- {
- OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
- int bytes = op.GetBitsCount() >> 3;
- int elems = bytes >> op.Size;
- EmitVectorExtract(context, op.Rm, elem, op.Size, signed);
- context.EmitSttmp();
- for (int index = 0; index < elems; index++)
- {
- if (ternary)
- {
- EmitVectorExtract(context, op.Rd, index, op.Size, signed);
- }
- EmitVectorExtract(context, op.Rn, index, op.Size, signed);
- context.EmitLdtmp();
- emit();
- EmitVectorInsert(context, op.Rd, index, op.Size);
- }
- if (op.RegisterSize == RegisterSize.Simd64)
- {
- EmitVectorZeroUpper(context, op.Rd);
- }
- }
- public static void EmitVectorImmUnaryOp(ILEmitterCtx context, Action emit)
- {
- EmitVectorImmOp(context, emit, false);
- }
- public static void EmitVectorImmBinaryOp(ILEmitterCtx context, Action emit)
- {
- EmitVectorImmOp(context, emit, true);
- }
- public static void EmitVectorImmOp(ILEmitterCtx context, Action emit, bool binary)
- {
- OpCodeSimdImm64 op = (OpCodeSimdImm64)context.CurrOp;
- int bytes = op.GetBitsCount() >> 3;
- int elems = bytes >> op.Size;
- for (int index = 0; index < elems; index++)
- {
- if (binary)
- {
- EmitVectorExtractZx(context, op.Rd, index, op.Size);
- }
- context.EmitLdc_I8(op.Imm);
- emit();
- EmitVectorInsert(context, op.Rd, index, op.Size);
- }
- if (op.RegisterSize == RegisterSize.Simd64)
- {
- EmitVectorZeroUpper(context, op.Rd);
- }
- }
- public static void EmitVectorWidenRmBinaryOpSx(ILEmitterCtx context, Action emit)
- {
- EmitVectorWidenRmBinaryOp(context, emit, true);
- }
- public static void EmitVectorWidenRmBinaryOpZx(ILEmitterCtx context, Action emit)
- {
- EmitVectorWidenRmBinaryOp(context, emit, false);
- }
- public static void EmitVectorWidenRmBinaryOp(ILEmitterCtx context, Action emit, bool signed)
- {
- OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
- int elems = 8 >> op.Size;
- int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0;
- for (int index = 0; index < elems; index++)
- {
- EmitVectorExtract(context, op.Rn, index, op.Size + 1, signed);
- EmitVectorExtract(context, op.Rm, part + index, op.Size, signed);
- emit();
- EmitVectorInsertTmp(context, index, op.Size + 1);
- }
- context.EmitLdvectmp();
- context.EmitStvec(op.Rd);
- }
- public static void EmitVectorWidenRnRmBinaryOpSx(ILEmitterCtx context, Action emit)
- {
- EmitVectorWidenRnRmOp(context, emit, false, true);
- }
- public static void EmitVectorWidenRnRmBinaryOpZx(ILEmitterCtx context, Action emit)
- {
- EmitVectorWidenRnRmOp(context, emit, false, false);
- }
- public static void EmitVectorWidenRnRmTernaryOpSx(ILEmitterCtx context, Action emit)
- {
- EmitVectorWidenRnRmOp(context, emit, true, true);
- }
- public static void EmitVectorWidenRnRmTernaryOpZx(ILEmitterCtx context, Action emit)
- {
- EmitVectorWidenRnRmOp(context, emit, true, false);
- }
- public static void EmitVectorWidenRnRmOp(ILEmitterCtx context, Action emit, bool ternary, bool signed)
- {
- OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
- int elems = 8 >> op.Size;
- int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0;
- for (int index = 0; index < elems; index++)
- {
- if (ternary)
- {
- EmitVectorExtract(context, op.Rd, index, op.Size + 1, signed);
- }
- EmitVectorExtract(context, op.Rn, part + index, op.Size, signed);
- EmitVectorExtract(context, op.Rm, part + index, op.Size, signed);
- emit();
- EmitVectorInsertTmp(context, index, op.Size + 1);
- }
- context.EmitLdvectmp();
- context.EmitStvec(op.Rd);
- }
- public static void EmitVectorWidenBinaryOpByElemSx(ILEmitterCtx context, Action emit)
- {
- OpCodeSimdRegElem64 op = (OpCodeSimdRegElem64)context.CurrOp;
- EmitVectorWidenOpByElem(context, emit, op.Index, ternary: false, signed: true);
- }
- public static void EmitVectorWidenBinaryOpByElemZx(ILEmitterCtx context, Action emit)
- {
- OpCodeSimdRegElem64 op = (OpCodeSimdRegElem64)context.CurrOp;
- EmitVectorWidenOpByElem(context, emit, op.Index, ternary: false, signed: false);
- }
- public static void EmitVectorWidenTernaryOpByElemSx(ILEmitterCtx context, Action emit)
- {
- OpCodeSimdRegElem64 op = (OpCodeSimdRegElem64)context.CurrOp;
- EmitVectorWidenOpByElem(context, emit, op.Index, ternary: true, signed: true);
- }
- public static void EmitVectorWidenTernaryOpByElemZx(ILEmitterCtx context, Action emit)
- {
- OpCodeSimdRegElem64 op = (OpCodeSimdRegElem64)context.CurrOp;
- EmitVectorWidenOpByElem(context, emit, op.Index, ternary: true, signed: false);
- }
- public static void EmitVectorWidenOpByElem(ILEmitterCtx context, Action emit, int elem, bool ternary, bool signed)
- {
- OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
- int elems = 8 >> op.Size;
- int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0;
- EmitVectorExtract(context, op.Rm, elem, op.Size, signed);
- context.EmitSttmp();
- for (int index = 0; index < elems; index++)
- {
- if (ternary)
- {
- EmitVectorExtract(context, op.Rd, index, op.Size + 1, signed);
- }
- EmitVectorExtract(context, op.Rn, part + index, op.Size, signed);
- context.EmitLdtmp();
- emit();
- EmitVectorInsertTmp(context, index, op.Size + 1);
- }
- context.EmitLdvectmp();
- context.EmitStvec(op.Rd);
- }
- public static void EmitVectorPairwiseOpSx(ILEmitterCtx context, Action emit)
- {
- EmitVectorPairwiseOp(context, emit, true);
- }
- public static void EmitVectorPairwiseOpZx(ILEmitterCtx context, Action emit)
- {
- EmitVectorPairwiseOp(context, emit, false);
- }
- public static void EmitVectorPairwiseOp(ILEmitterCtx context, Action emit, bool signed)
- {
- OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
- int words = op.GetBitsCount() >> 4;
- int pairs = words >> op.Size;
- for (int index = 0; index < pairs; index++)
- {
- int idx = index << 1;
- EmitVectorExtract(context, op.Rn, idx, op.Size, signed);
- EmitVectorExtract(context, op.Rn, idx + 1, op.Size, signed);
- emit();
- EmitVectorExtract(context, op.Rm, idx, op.Size, signed);
- EmitVectorExtract(context, op.Rm, idx + 1, op.Size, signed);
- emit();
- EmitVectorInsertTmp(context, pairs + index, op.Size);
- EmitVectorInsertTmp(context, index, op.Size);
- }
- context.EmitLdvectmp();
- context.EmitStvec(op.Rd);
- if (op.RegisterSize == RegisterSize.Simd64)
- {
- EmitVectorZeroUpper(context, op.Rd);
- }
- }
- public static void EmitVectorAcrossVectorOpSx(ILEmitterCtx context, Action emit)
- {
- EmitVectorAcrossVectorOp(context, emit, signed: true, isLong: false);
- }
- public static void EmitVectorAcrossVectorOpZx(ILEmitterCtx context, Action emit)
- {
- EmitVectorAcrossVectorOp(context, emit, signed: false, isLong: false);
- }
- public static void EmitVectorLongAcrossVectorOpSx(ILEmitterCtx context, Action emit)
- {
- EmitVectorAcrossVectorOp(context, emit, signed: true, isLong: true);
- }
- public static void EmitVectorLongAcrossVectorOpZx(ILEmitterCtx context, Action emit)
- {
- EmitVectorAcrossVectorOp(context, emit, signed: false, isLong: true);
- }
- public static void EmitVectorAcrossVectorOp(
- ILEmitterCtx context,
- Action emit,
- bool signed,
- bool isLong)
- {
- OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
- int bytes = op.GetBitsCount() >> 3;
- int elems = bytes >> op.Size;
- EmitVectorExtract(context, op.Rn, 0, op.Size, signed);
- for (int index = 1; index < elems; index++)
- {
- EmitVectorExtract(context, op.Rn, index, op.Size, signed);
- emit();
- }
- EmitScalarSet(context, op.Rd, isLong ? op.Size + 1 : op.Size);
- }
- public static void EmitVectorPairwiseOpF(ILEmitterCtx context, Action emit)
- {
- OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
- int sizeF = op.Size & 1;
- int words = op.GetBitsCount() >> 4;
- int pairs = words >> sizeF + 2;
- for (int index = 0; index < pairs; index++)
- {
- int idx = index << 1;
- EmitVectorExtractF(context, op.Rn, idx, sizeF);
- EmitVectorExtractF(context, op.Rn, idx + 1, sizeF);
- emit();
- EmitVectorExtractF(context, op.Rm, idx, sizeF);
- EmitVectorExtractF(context, op.Rm, idx + 1, sizeF);
- emit();
- EmitVectorInsertTmpF(context, pairs + index, sizeF);
- EmitVectorInsertTmpF(context, index, sizeF);
- }
- context.EmitLdvectmp();
- context.EmitStvec(op.Rd);
- if (op.RegisterSize == RegisterSize.Simd64)
- {
- EmitVectorZeroUpper(context, op.Rd);
- }
- }
- public static void EmitVectorPairwiseSseOrSse2OpF(ILEmitterCtx context, string name)
- {
- OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
- int sizeF = op.Size & 1;
- if (sizeF == 0)
- {
- if (op.RegisterSize == RegisterSize.Simd64)
- {
- Type[] types = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
- context.EmitLdvec(op.Rn);
- context.EmitLdvec(op.Rm);
- context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.UnpackLow), types));
- context.EmitStvectmp();
- context.EmitLdvectmp();
- VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero));
- context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveLowToHigh), types));
- VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero));
- context.EmitLdvectmp();
- context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveHighToLow), types));
- context.EmitCall(typeof(Sse).GetMethod(name, types));
- context.EmitStvec(op.Rd);
- }
- else /* if (op.RegisterSize == RegisterSize.Simd128) */
- {
- Type[] typesSfl = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>), typeof(byte) };
- Type[] types = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
- context.EmitLdvec(op.Rn);
- context.EmitLdvec(op.Rm);
- context.EmitLdc_I4(2 << 6 | 0 << 4 | 2 << 2 | 0 << 0);
- context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Shuffle), typesSfl));
- context.EmitLdvec(op.Rn);
- context.EmitLdvec(op.Rm);
- context.EmitLdc_I4(3 << 6 | 1 << 4 | 3 << 2 | 1 << 0);
- context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Shuffle), typesSfl));
- context.EmitCall(typeof(Sse).GetMethod(name, types));
- context.EmitStvec(op.Rd);
- }
- }
- else /* if (sizeF == 1) */
- {
- Type[] types = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) };
- context.EmitLdvec(op.Rn);
- context.EmitLdvec(op.Rm);
- context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), types));
- context.EmitLdvec(op.Rn);
- context.EmitLdvec(op.Rm);
- context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), types));
- context.EmitCall(typeof(Sse2).GetMethod(name, types));
- context.EmitStvec(op.Rd);
- }
- }
- [Flags]
- public enum SaturatingFlags
- {
- Scalar = 1 << 0,
- Signed = 1 << 1,
- Add = 1 << 2,
- Sub = 1 << 3,
- Accumulate = 1 << 4,
- ScalarSx = Scalar | Signed,
- ScalarZx = Scalar,
- VectorSx = Signed,
- VectorZx = 0
- }
- public static void EmitScalarSaturatingUnaryOpSx(ILEmitterCtx context, Action emit)
- {
- EmitSaturatingUnaryOpSx(context, emit, SaturatingFlags.ScalarSx);
- }
- public static void EmitVectorSaturatingUnaryOpSx(ILEmitterCtx context, Action emit)
- {
- EmitSaturatingUnaryOpSx(context, emit, SaturatingFlags.VectorSx);
- }
- public static void EmitSaturatingUnaryOpSx(ILEmitterCtx context, Action emit, SaturatingFlags flags)
- {
- OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
- bool scalar = (flags & SaturatingFlags.Scalar) != 0;
- int bytes = op.GetBitsCount() >> 3;
- int elems = !scalar ? bytes >> op.Size : 1;
- for (int index = 0; index < elems; index++)
- {
- EmitVectorExtractSx(context, op.Rn, index, op.Size);
- emit();
- if (op.Size <= 2)
- {
- EmitSatQ(context, op.Size, true, true);
- }
- else /* if (op.Size == 3) */
- {
- EmitUnarySignedSatQAbsOrNeg(context);
- }
- if (scalar)
- {
- EmitVectorZeroAll(context, op.Rd);
- }
- EmitVectorInsert(context, op.Rd, index, op.Size);
- }
- if (op.RegisterSize == RegisterSize.Simd64)
- {
- EmitVectorZeroUpper(context, op.Rd);
- }
- }
- public static void EmitScalarSaturatingBinaryOpSx(ILEmitterCtx context, SaturatingFlags flags)
- {
- EmitSaturatingBinaryOp(context, () => { }, SaturatingFlags.ScalarSx | flags);
- }
- public static void EmitScalarSaturatingBinaryOpZx(ILEmitterCtx context, SaturatingFlags flags)
- {
- EmitSaturatingBinaryOp(context, () => { }, SaturatingFlags.ScalarZx | flags);
- }
- public static void EmitVectorSaturatingBinaryOpSx(ILEmitterCtx context, SaturatingFlags flags)
- {
- EmitSaturatingBinaryOp(context, () => { }, SaturatingFlags.VectorSx | flags);
- }
- public static void EmitVectorSaturatingBinaryOpZx(ILEmitterCtx context, SaturatingFlags flags)
- {
- EmitSaturatingBinaryOp(context, () => { }, SaturatingFlags.VectorZx | flags);
- }
- public static void EmitSaturatingBinaryOp(ILEmitterCtx context, Action emit, SaturatingFlags flags)
- {
- OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
- bool scalar = (flags & SaturatingFlags.Scalar) != 0;
- bool signed = (flags & SaturatingFlags.Signed) != 0;
- bool add = (flags & SaturatingFlags.Add) != 0;
- bool sub = (flags & SaturatingFlags.Sub) != 0;
- bool accumulate = (flags & SaturatingFlags.Accumulate) != 0;
- int bytes = op.GetBitsCount() >> 3;
- int elems = !scalar ? bytes >> op.Size : 1;
- if (add || sub)
- {
- for (int index = 0; index < elems; index++)
- {
- EmitVectorExtract(context, op.Rn, index, op.Size, signed);
- EmitVectorExtract(context, ((OpCodeSimdReg64)op).Rm, index, op.Size, signed);
- if (op.Size <= 2)
- {
- context.Emit(add ? OpCodes.Add : OpCodes.Sub);
- EmitSatQ(context, op.Size, true, signed);
- }
- else /* if (op.Size == 3) */
- {
- if (add)
- {
- EmitBinarySatQAdd(context, signed);
- }
- else /* if (sub) */
- {
- EmitBinarySatQSub(context, signed);
- }
- }
- if (scalar)
- {
- EmitVectorZeroAll(context, op.Rd);
- }
- EmitVectorInsert(context, op.Rd, index, op.Size);
- }
- }
- else if (accumulate)
- {
- for (int index = 0; index < elems; index++)
- {
- EmitVectorExtract(context, op.Rn, index, op.Size, !signed);
- EmitVectorExtract(context, op.Rd, index, op.Size, signed);
- if (op.Size <= 2)
- {
- context.Emit(OpCodes.Add);
- EmitSatQ(context, op.Size, true, signed);
- }
- else /* if (op.Size == 3) */
- {
- EmitBinarySatQAccumulate(context, signed);
- }
- if (scalar)
- {
- EmitVectorZeroAll(context, op.Rd);
- }
- EmitVectorInsert(context, op.Rd, index, op.Size);
- }
- }
- else
- {
- for (int index = 0; index < elems; index++)
- {
- EmitVectorExtract(context, op.Rn, index, op.Size, signed);
- EmitVectorExtract(context, ((OpCodeSimdReg64)op).Rm, index, op.Size, signed);
- emit();
- EmitSatQ(context, op.Size, true, signed);
- if (scalar)
- {
- EmitVectorZeroAll(context, op.Rd);
- }
- EmitVectorInsert(context, op.Rd, index, op.Size);
- }
- }
- if (op.RegisterSize == RegisterSize.Simd64)
- {
- EmitVectorZeroUpper(context, op.Rd);
- }
- }
- [Flags]
- public enum SaturatingNarrowFlags
- {
- Scalar = 1 << 0,
- SignedSrc = 1 << 1,
- SignedDst = 1 << 2,
- ScalarSxSx = Scalar | SignedSrc | SignedDst,
- ScalarSxZx = Scalar | SignedSrc,
- ScalarZxZx = Scalar,
- VectorSxSx = SignedSrc | SignedDst,
- VectorSxZx = SignedSrc,
- VectorZxZx = 0
- }
- public static void EmitSaturatingNarrowOp(ILEmitterCtx context, SaturatingNarrowFlags flags)
- {
- OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
- bool scalar = (flags & SaturatingNarrowFlags.Scalar) != 0;
- bool signedSrc = (flags & SaturatingNarrowFlags.SignedSrc) != 0;
- bool signedDst = (flags & SaturatingNarrowFlags.SignedDst) != 0;
- int elems = !scalar ? 8 >> op.Size : 1;
- int part = !scalar && (op.RegisterSize == RegisterSize.Simd128) ? elems : 0;
- if (scalar)
- {
- EmitVectorZeroLowerTmp(context);
- }
- if (part != 0)
- {
- context.EmitLdvec(op.Rd);
- context.EmitStvectmp();
- }
- for (int index = 0; index < elems; index++)
- {
- EmitVectorExtract(context, op.Rn, index, op.Size + 1, signedSrc);
- EmitSatQ(context, op.Size, signedSrc, signedDst);
- EmitVectorInsertTmp(context, part + index, op.Size);
- }
- context.EmitLdvectmp();
- context.EmitStvec(op.Rd);
- if (part == 0)
- {
- EmitVectorZeroUpper(context, op.Rd);
- }
- }
- // TSrc (16bit, 32bit, 64bit; signed, unsigned) > TDst (8bit, 16bit, 32bit; signed, unsigned).
- public static void EmitSatQ(ILEmitterCtx context, int sizeDst, bool signedSrc, bool signedDst)
- {
- if ((uint)sizeDst > 2u)
- {
- throw new ArgumentOutOfRangeException(nameof(sizeDst));
- }
- context.EmitLdc_I4(sizeDst);
- context.EmitLdarg(TranslatedSub.StateArgIdx);
- if (signedSrc)
- {
- SoftFallback.EmitCall(context, signedDst
- ? nameof(SoftFallback.SignedSrcSignedDstSatQ)
- : nameof(SoftFallback.SignedSrcUnsignedDstSatQ));
- }
- else
- {
- SoftFallback.EmitCall(context, signedDst
- ? nameof(SoftFallback.UnsignedSrcSignedDstSatQ)
- : nameof(SoftFallback.UnsignedSrcUnsignedDstSatQ));
- }
- }
- // TSrc (64bit) == TDst (64bit); signed.
- public static void EmitUnarySignedSatQAbsOrNeg(ILEmitterCtx context)
- {
- if (((OpCodeSimd64)context.CurrOp).Size < 3)
- {
- throw new InvalidOperationException();
- }
- context.EmitLdarg(TranslatedSub.StateArgIdx);
- SoftFallback.EmitCall(context, nameof(SoftFallback.UnarySignedSatQAbsOrNeg));
- }
- // TSrcs (64bit) == TDst (64bit); signed, unsigned.
- public static void EmitBinarySatQAdd(ILEmitterCtx context, bool signed)
- {
- if (((OpCodeSimdReg64)context.CurrOp).Size < 3)
- {
- throw new InvalidOperationException();
- }
- context.EmitLdarg(TranslatedSub.StateArgIdx);
- SoftFallback.EmitCall(context, signed
- ? nameof(SoftFallback.BinarySignedSatQAdd)
- : nameof(SoftFallback.BinaryUnsignedSatQAdd));
- }
- // TSrcs (64bit) == TDst (64bit); signed, unsigned.
- public static void EmitBinarySatQSub(ILEmitterCtx context, bool signed)
- {
- if (((OpCodeSimdReg64)context.CurrOp).Size < 3)
- {
- throw new InvalidOperationException();
- }
- context.EmitLdarg(TranslatedSub.StateArgIdx);
- SoftFallback.EmitCall(context, signed
- ? nameof(SoftFallback.BinarySignedSatQSub)
- : nameof(SoftFallback.BinaryUnsignedSatQSub));
- }
- // TSrcs (64bit) == TDst (64bit); signed, unsigned.
- public static void EmitBinarySatQAccumulate(ILEmitterCtx context, bool signed)
- {
- if (((OpCodeSimd64)context.CurrOp).Size < 3)
- {
- throw new InvalidOperationException();
- }
- context.EmitLdarg(TranslatedSub.StateArgIdx);
- SoftFallback.EmitCall(context, signed
- ? nameof(SoftFallback.BinarySignedSatQAcc)
- : nameof(SoftFallback.BinaryUnsignedSatQAcc));
- }
- public static void EmitScalarSet(ILEmitterCtx context, int reg, int size)
- {
- EmitVectorZeroAll(context, reg);
- EmitVectorInsert(context, reg, 0, size);
- }
- public static void EmitScalarSetF(ILEmitterCtx context, int reg, int size)
- {
- if (Optimizations.UseSse41 && size == 0)
- {
- // If the type is float, we can perform insertion and
- // zero the upper bits with a single instruction (INSERTPS);
- context.EmitLdvec(reg);
- VectorHelper.EmitCall(context, nameof(VectorHelper.Sse41VectorInsertScalarSingle));
- context.EmitStvec(reg);
- }
- else
- {
- EmitVectorZeroAll(context, reg);
- EmitVectorInsertF(context, reg, 0, size);
- }
- }
- public static void EmitVectorExtractSx(ILEmitterCtx context, int reg, int index, int size)
- {
- EmitVectorExtract(context, reg, index, size, true);
- }
- public static void EmitVectorExtractZx(ILEmitterCtx context, int reg, int index, int size)
- {
- EmitVectorExtract(context, reg, index, size, false);
- }
- public static void EmitVectorExtract(ILEmitterCtx context, int reg, int index, int size, bool signed)
- {
- ThrowIfInvalid(index, size);
- context.EmitLdvec(reg);
- context.EmitLdc_I4(index);
- context.EmitLdc_I4(size);
- VectorHelper.EmitCall(context, signed
- ? nameof(VectorHelper.VectorExtractIntSx)
- : nameof(VectorHelper.VectorExtractIntZx));
- }
- public static void EmitVectorExtractF(ILEmitterCtx context, int reg, int index, int size)
- {
- ThrowIfInvalidF(index, size);
- context.EmitLdvec(reg);
- context.EmitLdc_I4(index);
- if (size == 0)
- {
- VectorHelper.EmitCall(context, nameof(VectorHelper.VectorExtractSingle));
- }
- else if (size == 1)
- {
- VectorHelper.EmitCall(context, nameof(VectorHelper.VectorExtractDouble));
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(size));
- }
- }
- public static void EmitVectorZeroAll(ILEmitterCtx context, int reg)
- {
- if (Optimizations.UseSse)
- {
- VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero));
- context.EmitStvec(reg);
- }
- else
- {
- EmitVectorZeroLower(context, reg);
- EmitVectorZeroUpper(context, reg);
- }
- }
- public static void EmitVectorZeroLower(ILEmitterCtx context, int reg)
- {
- EmitVectorInsert(context, reg, 0, 3, 0);
- }
- public static void EmitVectorZeroLowerTmp(ILEmitterCtx context)
- {
- if (Optimizations.UseSse)
- {
- context.EmitLdvectmp();
- VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero));
- context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveHighToLow)));
- context.EmitStvectmp();
- }
- else
- {
- EmitVectorInsertTmp(context, 0, 3, 0);
- }
- }
- public static void EmitVectorZeroUpper(ILEmitterCtx context, int reg)
- {
- if (Optimizations.UseSse)
- {
- // TODO: Use Sse2.MoveScalar once it is fixed (in .NET Core 3.0),
- // as of the time of writing it just crashes the JIT.
- /*Type[] typesMov = new Type[] { typeof(Vector128<ulong>) };
- context.EmitLdvec(reg);
- context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MoveScalar), typesMov));
- context.EmitStvec(reg);*/
- context.EmitLdvec(reg);
- VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero));
- context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveLowToHigh)));
- context.EmitStvec(reg);
- }
- else
- {
- EmitVectorInsert(context, reg, 1, 3, 0);
- }
- }
- public static void EmitVectorZero32_128(ILEmitterCtx context, int reg)
- {
- if (!Sse.IsSupported)
- {
- throw new PlatformNotSupportedException();
- }
- VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero));
- context.EmitLdvec(reg);
- context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveScalar)));
- context.EmitStvec(reg);
- }
- public static void EmitVectorInsert(ILEmitterCtx context, int reg, int index, int size)
- {
- ThrowIfInvalid(index, size);
- context.EmitLdvec(reg);
- context.EmitLdc_I4(index);
- context.EmitLdc_I4(size);
- VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInsertInt));
- context.EmitStvec(reg);
- }
- public static void EmitVectorInsertTmp(ILEmitterCtx context, int index, int size)
- {
- ThrowIfInvalid(index, size);
- context.EmitLdvectmp();
- context.EmitLdc_I4(index);
- context.EmitLdc_I4(size);
- VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInsertInt));
- context.EmitStvectmp();
- }
- public static void EmitVectorInsert(ILEmitterCtx context, int reg, int index, int size, long value)
- {
- ThrowIfInvalid(index, size);
- context.EmitLdc_I8(value);
- context.EmitLdvec(reg);
- context.EmitLdc_I4(index);
- context.EmitLdc_I4(size);
- VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInsertInt));
- context.EmitStvec(reg);
- }
- public static void EmitVectorInsertTmp(ILEmitterCtx context, int index, int size, long value)
- {
- ThrowIfInvalid(index, size);
- context.EmitLdc_I8(value);
- context.EmitLdvectmp();
- context.EmitLdc_I4(index);
- context.EmitLdc_I4(size);
- VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInsertInt));
- context.EmitStvectmp();
- }
- public static void EmitVectorInsertF(ILEmitterCtx context, int reg, int index, int size)
- {
- ThrowIfInvalidF(index, size);
- context.EmitLdvec(reg);
- context.EmitLdc_I4(index);
- if (size == 0)
- {
- VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInsertSingle));
- }
- else if (size == 1)
- {
- VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInsertDouble));
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(size));
- }
- context.EmitStvec(reg);
- }
- public static void EmitVectorInsertTmpF(ILEmitterCtx context, int index, int size)
- {
- ThrowIfInvalidF(index, size);
- context.EmitLdvectmp();
- context.EmitLdc_I4(index);
- if (size == 0)
- {
- VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInsertSingle));
- }
- else if (size == 1)
- {
- VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInsertDouble));
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(size));
- }
- context.EmitStvectmp();
- }
- private static void ThrowIfInvalid(int index, int size)
- {
- if ((uint)size > 3u)
- {
- throw new ArgumentOutOfRangeException(nameof(size));
- }
- if ((uint)index >= 16u >> size)
- {
- throw new ArgumentOutOfRangeException(nameof(index));
- }
- }
- private static void ThrowIfInvalidF(int index, int size)
- {
- if ((uint)size > 1u)
- {
- throw new ArgumentOutOfRangeException(nameof(size));
- }
- if ((uint)index >= 4u >> size)
- {
- throw new ArgumentOutOfRangeException(nameof(index));
- }
- }
- }
- }
|