| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513 |
- 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;
- EmitLdvecWithSignedCast(context, op.Rn, op.Size);
- Type baseType = VectorIntTypesPerSizeLog2[op.Size];
- if (op is OpCodeSimdReg64 binOp)
- {
- EmitLdvecWithSignedCast(context, binOp.Rm, op.Size);
- context.EmitCall(type.GetMethod(name, new Type[] { baseType, baseType }));
- }
- else
- {
- context.EmitCall(type.GetMethod(name, new Type[] { baseType }));
- }
- EmitStvecWithSignedCast(context, op.Rd, op.Size);
- if (op.RegisterSize == RegisterSize.Simd64)
- {
- EmitVectorZeroUpper(context, op.Rd);
- }
- }
- public static void EmitLdvecWithSignedCast(ILEmitterCtx context, int reg, int size)
- {
- context.EmitLdvec(reg);
- switch (size)
- {
- case 0: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleToSByte)); break;
- case 1: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleToInt16)); break;
- case 2: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleToInt32)); break;
- case 3: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleToInt64)); break;
- default: throw new ArgumentOutOfRangeException(nameof(size));
- }
- }
- public static void EmitLdvecWithCastToDouble(ILEmitterCtx context, int reg)
- {
- context.EmitLdvec(reg);
- VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleToDouble));
- }
- public static void EmitStvecWithCastFromDouble(ILEmitterCtx context, int reg)
- {
- VectorHelper.EmitCall(context, nameof(VectorHelper.VectorDoubleToSingle));
- context.EmitStvec(reg);
- }
- public static void EmitLdvecWithUnsignedCast(ILEmitterCtx context, int reg, int size)
- {
- context.EmitLdvec(reg);
- switch (size)
- {
- case 0: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleToByte)); break;
- case 1: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleToUInt16)); break;
- case 2: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleToUInt32)); break;
- case 3: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleToUInt64)); break;
- default: throw new ArgumentOutOfRangeException(nameof(size));
- }
- }
- public static void EmitStvecWithSignedCast(ILEmitterCtx context, int reg, int size)
- {
- switch (size)
- {
- case 0: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSByteToSingle)); break;
- case 1: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInt16ToSingle)); break;
- case 2: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInt32ToSingle)); break;
- case 3: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInt64ToSingle)); break;
- default: throw new ArgumentOutOfRangeException(nameof(size));
- }
- context.EmitStvec(reg);
- }
- public static void EmitStvecWithUnsignedCast(ILEmitterCtx context, int reg, int size)
- {
- switch (size)
- {
- case 0: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorByteToSingle)); break;
- case 1: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorUInt16ToSingle)); break;
- case 2: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorUInt32ToSingle)); break;
- case 3: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorUInt64ToSingle)); break;
- default: throw new ArgumentOutOfRangeException(nameof(size));
- }
- context.EmitStvec(reg);
- }
- 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;
- void Ldvec(int reg)
- {
- context.EmitLdvec(reg);
- if (sizeF == 1)
- {
- VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleToDouble));
- }
- }
- Ldvec(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)
- {
- Ldvec(binOp.Rm);
- context.EmitCall(type.GetMethod(name, new Type[] { baseType, baseType }));
- }
- else
- {
- context.EmitCall(type.GetMethod(name, new Type[] { baseType }));
- }
- if (sizeF == 1)
- {
- VectorHelper.EmitCall(context, nameof(VectorHelper.VectorDoubleToSingle));
- }
- 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 EmitUnarySoftFloatCall(ILEmitterCtx context, string name)
- {
- IOpCodeSimd64 op = (IOpCodeSimd64)context.CurrOp;
- int sizeF = op.Size & 1;
- MethodInfo mthdInfo;
- if (sizeF == 0)
- {
- mthdInfo = typeof(SoftFloat).GetMethod(name, new Type[] { typeof(float) });
- }
- else /* if (sizeF == 1) */
- {
- mthdInfo = typeof(SoftFloat).GetMethod(name, new Type[] { typeof(double) });
- }
- context.EmitCall(mthdInfo);
- }
- public static void EmitSoftFloatCall(ILEmitterCtx context, string name)
- {
- IOpCodeSimd64 op = (IOpCodeSimd64)context.CurrOp;
- Type type = (op.Size & 1) == 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, false, true);
- }
- public static void EmitVectorBinaryOpByElemZx(ILEmitterCtx context, Action emit)
- {
- OpCodeSimdRegElem64 op = (OpCodeSimdRegElem64)context.CurrOp;
- EmitVectorOpByElem(context, emit, op.Index, false, false);
- }
- public static void EmitVectorTernaryOpByElemZx(ILEmitterCtx context, Action emit)
- {
- OpCodeSimdRegElem64 op = (OpCodeSimdRegElem64)context.CurrOp;
- EmitVectorOpByElem(context, emit, op.Index, true, 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();
- EmitVectorInsertTmp(context, index, op.Size);
- }
- context.EmitLdvectmp();
- context.EmitStvec(op.Rd);
- 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 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 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);
- }
- }
- [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;
- if (scalar)
- {
- EmitVectorZeroLowerTmp(context);
- }
- 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);
- }
- EmitVectorInsertTmp(context, index, op.Size);
- }
- context.EmitLdvectmp();
- context.EmitStvec(op.Rd);
- if ((op.RegisterSize == RegisterSize.Simd64) || scalar)
- {
- 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 (scalar)
- {
- EmitVectorZeroLowerTmp(context);
- }
- 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);
- }
- }
- EmitVectorInsertTmp(context, 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);
- }
- EmitVectorInsertTmp(context, 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);
- EmitVectorInsertTmp(context, index, op.Size);
- }
- }
- context.EmitLdvectmp();
- context.EmitStvec(op.Rd);
- if ((op.RegisterSize == RegisterSize.Simd64) || scalar)
- {
- 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 (sizeDst > 2)
- {
- 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,
- //as of the time of writing it just crashes the JIT (SDK 2.1.500).
- /*Type[] typesMov = new Type[] { typeof(Vector128<ulong>) };
- EmitLdvecWithUnsignedCast(context, reg, 3);
- context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MoveScalar), typesMov));
- EmitStvecWithUnsignedCast(context, reg, 3);*/
- 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));
- }
- }
- }
- }
|