| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005 |
- using ChocolArm64.Decoder;
- using ChocolArm64.State;
- using ChocolArm64.Translation;
- using System;
- using System.Reflection;
- using System.Reflection.Emit;
- using static ChocolArm64.Instruction.AInstEmitMemoryHelper;
- namespace ChocolArm64.Instruction
- {
- static partial class AInstEmit
- {
- public static void Add_V(AILEmitterCtx Context) => EmitVectorBinaryZx(Context, OpCodes.Add);
- public static void Addp_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
- Context.EmitLdc_I4(Op.Size);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Addp64),
- nameof(ASoftFallback.Addp128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Addv_V(AILEmitterCtx Context) => EmitVectorAddv(Context);
- public static void And_V(AILEmitterCtx Context) => EmitVectorBinaryZx(Context, OpCodes.And);
- public static void Bic_V(AILEmitterCtx Context) => EmitVectorBic(Context);
- public static void Bic_Vi(AILEmitterCtx Context)
- {
- AOpCodeSimdImm Op = (AOpCodeSimdImm)Context.CurrOp;
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdc_I8(Op.Imm);
- Context.EmitLdc_I4(Op.Size);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Bic_Vi64),
- nameof(ASoftFallback.Bic_Vi128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Bsl_V(AILEmitterCtx Context) => EmitVectorBsl(Context);
- public static void Cmeq_V(AILEmitterCtx Context) => EmitVectorCmp(Context, OpCodes.Beq_S);
- public static void Cmge_V(AILEmitterCtx Context) => EmitVectorCmp(Context, OpCodes.Bge_S);
- public static void Cmgt_V(AILEmitterCtx Context) => EmitVectorCmp(Context, OpCodes.Bgt_S);
- public static void Cmhi_V(AILEmitterCtx Context) => EmitVectorCmp(Context, OpCodes.Bgt_Un_S);
- public static void Cmhs_V(AILEmitterCtx Context) => EmitVectorCmp(Context, OpCodes.Bge_Un_S);
- public static void Cmle_V(AILEmitterCtx Context) => EmitVectorCmp(Context, OpCodes.Ble_S);
- public static void Cmlt_V(AILEmitterCtx Context) => EmitVectorCmp(Context, OpCodes.Blt_S);
- public static void Cnt_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Cnt64),
- nameof(ASoftFallback.Cnt128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Dup_Gp(AILEmitterCtx Context)
- {
- AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
- Context.EmitLdintzr(Op.Rn);
- Context.EmitLdc_I4(Op.Size);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Dup_Gp64),
- nameof(ASoftFallback.Dup_Gp128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Dup_V(AILEmitterCtx Context)
- {
- AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdc_I4(Op.DstIndex);
- Context.EmitLdc_I4(Op.Size);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Dup_V64),
- nameof(ASoftFallback.Dup_V128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Eor_V(AILEmitterCtx Context) => EmitVectorBinaryZx(Context, OpCodes.Xor);
- public static void Fadd_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
- Context.EmitLdc_I4(Op.SizeF);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Fadd64),
- nameof(ASoftFallback.Fadd128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Fcvtzs_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdc_I4(Op.SizeF);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Fcvtzs_V64),
- nameof(ASoftFallback.Fcvtzs_V128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Fcvtzu_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdc_I4(0);
- Context.EmitLdc_I4(Op.SizeF);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Fcvtzu_V_64),
- nameof(ASoftFallback.Fcvtzu_V_128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Fcvtzu_V_Fix(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdc_I4((8 << (Op.Size + 1)) - Op.Imm);
- Context.EmitLdc_I4(Op.Size - 2);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Fcvtzu_V_64),
- nameof(ASoftFallback.Fcvtzu_V_128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Fmla_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
- Context.EmitLdc_I4(Op.SizeF);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Fmla64),
- nameof(ASoftFallback.Fmla128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Fmla_Vs(AILEmitterCtx Context)
- {
- AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp;
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
- Context.EmitLdc_I4(Op.Index);
- Context.EmitLdc_I4(Op.SizeF);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Fmla_Ve64),
- nameof(ASoftFallback.Fmla_Ve128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Fmov_V(AILEmitterCtx Context)
- {
- AOpCodeSimdImm Op = (AOpCodeSimdImm)Context.CurrOp;
- Context.EmitLdc_I8(Op.Imm);
- Context.EmitLdc_I4(Op.Size + 2);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Dup_Gp64),
- nameof(ASoftFallback.Dup_Gp128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Fmul_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
- Context.EmitLdc_I4(Op.SizeF);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Fmul64),
- nameof(ASoftFallback.Fmul128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Fmul_Vs(AILEmitterCtx Context)
- {
- AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
- Context.EmitLdc_I4(Op.Index);
- Context.EmitLdc_I4(Op.SizeF);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Fmul_Ve64),
- nameof(ASoftFallback.Fmul_Ve128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Fsub_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
- Context.EmitLdc_I4(Op.SizeF);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Fsub64),
- nameof(ASoftFallback.Fsub128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Ins_Gp(AILEmitterCtx Context)
- {
- AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdintzr(Op.Rn);
- Context.EmitLdc_I4(Op.DstIndex);
- Context.EmitLdc_I4(Op.Size);
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Ins_Gp));
- Context.EmitStvec(Op.Rd);
- }
- public static void Ins_V(AILEmitterCtx Context)
- {
- AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdc_I4(Op.SrcIndex);
- Context.EmitLdc_I4(Op.DstIndex);
- Context.EmitLdc_I4(Op.Size);
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Ins_V));
- Context.EmitStvec(Op.Rd);
- }
- public static void Ld__V(AILEmitterCtx Context) => EmitSimdMultLdSt(Context, IsLoad: true);
- public static void Mla_V(AILEmitterCtx Context) => EmitVectorMla(Context);
- public static void Movi_V(AILEmitterCtx Context) => EmitMovi_V(Context, false);
- public static void Mul_V(AILEmitterCtx Context) => EmitVectorBinaryZx(Context, OpCodes.Mul);
- public static void Mvni_V(AILEmitterCtx Context) => EmitMovi_V(Context, true);
- private static void EmitMovi_V(AILEmitterCtx Context, bool Not)
- {
- AOpCodeSimdImm Op = (AOpCodeSimdImm)Context.CurrOp;
- Context.EmitLdc_I8(Not ? ~Op.Imm : Op.Imm);
- Context.EmitLdc_I4(Op.Size);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Dup_Gp64),
- nameof(ASoftFallback.Dup_Gp128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Neg_V(AILEmitterCtx Context) => EmitVectorUnarySx(Context, OpCodes.Neg);
- public static void Not_V(AILEmitterCtx Context) => EmitVectorUnaryZx(Context, OpCodes.Not);
- public static void Orr_V(AILEmitterCtx Context) => EmitVectorBinaryZx(Context, OpCodes.Or);
- public static void Orr_Vi(AILEmitterCtx Context)
- {
- AOpCodeSimdImm Op = (AOpCodeSimdImm)Context.CurrOp;
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdc_I8(Op.Imm);
- Context.EmitLdc_I4(Op.Size);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Orr_Vi64),
- nameof(ASoftFallback.Orr_Vi128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Saddw_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
- Context.EmitLdc_I4(Op.Size);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Saddw),
- nameof(ASoftFallback.Saddw2));
- Context.EmitStvec(Op.Rd);
- }
- public static void Scvtf_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdc_I4(Op.SizeF);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Scvtf_V64),
- nameof(ASoftFallback.Scvtf_V128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Shl_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
- EmitVectorImmBinaryZx(Context, OpCodes.Shl, Op.Imm - (8 << Op.Size));
- }
- public static void Smax_V(AILEmitterCtx Context) => EmitVectorSmax(Context);
- public static void Smin_V(AILEmitterCtx Context) => EmitVectorSmin(Context);
- public static void Sshl_V(AILEmitterCtx Context) => EmitVectorSshl(Context);
- public static void Sshll_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdc_I4(Op.Imm - (8 << Op.Size));
- Context.EmitLdc_I4(Op.Size);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Sshll),
- nameof(ASoftFallback.Sshll2));
- Context.EmitStvec(Op.Rd);
- }
- public static void Sshr_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
- EmitVectorImmBinarySx(Context, OpCodes.Shr, (8 << (Op.Size + 1)) - Op.Imm);
- }
- public static void St__V(AILEmitterCtx Context) => EmitSimdMultLdSt(Context, IsLoad: false);
- public static void Sub_V(AILEmitterCtx Context) => EmitVectorBinaryZx(Context, OpCodes.Sub);
- public static void Tbl_V(AILEmitterCtx Context)
- {
- AOpCodeSimdTbl Op = (AOpCodeSimdTbl)Context.CurrOp;
- Context.EmitLdvec(Op.Rm);
- for (int Index = 0; Index < Op.Size; Index++)
- {
- Context.EmitLdvec((Op.Rn + Index) & 0x1f);
- }
- switch (Op.Size)
- {
- case 1: ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Tbl1_V64),
- nameof(ASoftFallback.Tbl1_V128)); break;
- case 2: ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Tbl2_V64),
- nameof(ASoftFallback.Tbl2_V128)); break;
- case 3: ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Tbl3_V64),
- nameof(ASoftFallback.Tbl3_V128)); break;
- case 4: ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Tbl4_V64),
- nameof(ASoftFallback.Tbl4_V128)); break;
- default: throw new InvalidOperationException();
- }
- Context.EmitStvec(Op.Rd);
- }
- public static void Uaddlv_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdc_I4(Op.Size);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Uaddlv64),
- nameof(ASoftFallback.Uaddlv128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Uaddw_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
- Context.EmitLdc_I4(Op.Size);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Uaddw),
- nameof(ASoftFallback.Uaddw2));
- Context.EmitStvec(Op.Rd);
- }
- public static void Ucvtf_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- if (Op.Size == 0)
- {
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Ucvtf_V_F));
- }
- else if (Op.Size == 1)
- {
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Ucvtf_V_D));
- }
- else
- {
- throw new InvalidOperationException();
- }
- Context.EmitStvec(Op.Rd);
- }
- public static void Umov_S(AILEmitterCtx Context)
- {
- AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdc_I4(Op.DstIndex);
- Context.EmitLdc_I4(Op.Size);
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.ExtractVec));
- Context.EmitStintzr(Op.Rd);
- }
- public static void Ushl_V(AILEmitterCtx Context) => EmitVectorUshl(Context);
- public static void Ushll_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdc_I4(Op.Imm - (8 << Op.Size));
- Context.EmitLdc_I4(Op.Size);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Ushll),
- nameof(ASoftFallback.Ushll2));
- Context.EmitStvec(Op.Rd);
- }
- public static void Ushr_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdc_I4((8 << (Op.Size + 1)) - Op.Imm);
- Context.EmitLdc_I4(Op.Size);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Ushr64),
- nameof(ASoftFallback.Ushr128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Usra_V(AILEmitterCtx Context)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdc_I4((8 << (Op.Size + 1)) - Op.Imm);
- Context.EmitLdc_I4(Op.Size);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Usra64),
- nameof(ASoftFallback.Usra128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Uzp1_V(AILEmitterCtx Context)
- {
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdvec(Op.Rm);
- Context.EmitLdc_I4(Op.Size);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Uzp1_V64),
- nameof(ASoftFallback.Uzp1_V128));
- Context.EmitStvec(Op.Rd);
- }
- public static void Xtn_V(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
- Context.EmitLdvec(Op.Rn);
- Context.EmitLdc_I4(Op.Size);
- ASoftFallback.EmitCall(Context,
- nameof(ASoftFallback.Xtn),
- nameof(ASoftFallback.Xtn2));
- Context.EmitStvec(Op.Rd);
- }
- private static void EmitSimdMultLdSt(AILEmitterCtx Context, bool IsLoad)
- {
- AOpCodeSimdMemMult Op = (AOpCodeSimdMemMult)Context.CurrOp;
- int Offset = 0;
- for (int Rep = 0; Rep < Op.Reps; Rep++)
- for (int Elem = 0; Elem < Op.Elems; Elem++)
- for (int SElem = 0; SElem < Op.SElems; SElem++)
- {
- int Rtt = (Op.Rt + Rep + SElem) & 0x1f;
- if (IsLoad)
- {
- Context.EmitLdvec(Rtt);
- Context.EmitLdc_I4(Elem);
- Context.EmitLdc_I4(Op.Size);
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdint(Op.Rn);
- Context.EmitLdc_I8(Offset);
- Context.Emit(OpCodes.Add);
- EmitReadZxCall(Context, Op.Size);
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.InsertVec));
- Context.EmitStvec(Rtt);
- if (Op.RegisterSize == ARegisterSize.SIMD64 && Elem == Op.Elems - 1)
- {
- EmitVectorZeroUpper(Context, Rtt);
- }
- }
- else
- {
- Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
- Context.EmitLdint(Op.Rn);
- Context.EmitLdc_I8(Offset);
- Context.Emit(OpCodes.Add);
- Context.EmitLdvec(Rtt);
- Context.EmitLdc_I4(Elem);
- Context.EmitLdc_I4(Op.Size);
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.ExtractVec));
- EmitWriteCall(Context, Op.Size);
- }
- Offset += 1 << Op.Size;
- }
- if (Op.WBack)
- {
- Context.EmitLdint(Op.Rn);
- if (Op.Rm != ARegisters.ZRIndex)
- {
- Context.EmitLdint(Op.Rm);
- }
- else
- {
- Context.EmitLdc_I8(Offset);
- }
- Context.Emit(OpCodes.Add);
- Context.EmitStint(Op.Rn);
- }
- }
- private static void EmitVectorAddv(AILEmitterCtx Context)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
- int Bytes = Context.CurrOp.GetBitsCount() >> 3;
- EmitVectorZeroLower(Context, Op.Rd);
- EmitVectorZeroUpper(Context, Op.Rd);
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdc_I4(0);
- Context.EmitLdc_I4(Op.Size);
- EmitVectorExtractZx(Context, Op.Rn, 0);
- for (int Index = 1; Index < (Bytes >> Op.Size); Index++)
- {
- EmitVectorExtractZx(Context, Op.Rn, Index);
- Context.Emit(OpCodes.Add);
- }
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.InsertVec));
- Context.EmitStvec(Op.Rd);
- }
- private static void EmitVectorBic(AILEmitterCtx Context)
- {
- EmitVectorBinaryZx(Context, () =>
- {
- Context.Emit(OpCodes.Not);
- Context.Emit(OpCodes.And);
- });
- }
- private static void EmitVectorBsl(AILEmitterCtx Context)
- {
- EmitVectorTernaryZx(Context, () =>
- {
- Context.EmitSttmp();
- Context.EmitLdtmp();
- Context.Emit(OpCodes.Xor);
- Context.Emit(OpCodes.And);
- Context.EmitLdtmp();
- Context.Emit(OpCodes.Xor);
- });
- }
- private static void EmitVectorMla(AILEmitterCtx Context)
- {
- EmitVectorTernaryZx(Context, () =>
- {
- Context.Emit(OpCodes.Mul);
- Context.Emit(OpCodes.Add);
- });
- }
- private static void EmitVectorSmax(AILEmitterCtx Context)
- {
- Type[] Types = new Type[] { typeof(long), typeof(long) };
- MethodInfo MthdInfo = typeof(Math).GetMethod(nameof(Math.Max), Types);
- EmitVectorBinarySx(Context, () => Context.EmitCall(MthdInfo));
- }
- private static void EmitVectorSmin(AILEmitterCtx Context)
- {
- Type[] Types = new Type[] { typeof(long), typeof(long) };
- MethodInfo MthdInfo = typeof(Math).GetMethod(nameof(Math.Min), Types);
- EmitVectorBinarySx(Context, () => Context.EmitCall(MthdInfo));
- }
- private static void EmitVectorSshl(AILEmitterCtx Context) => EmitVectorShl(Context, true);
- private static void EmitVectorUshl(AILEmitterCtx Context) => EmitVectorShl(Context, false);
- private static void EmitVectorShl(AILEmitterCtx Context, bool Signed)
- {
- //This instruction shifts the value on vector A by the number of bits
- //specified on the signed, lower 8 bits of vector B. If the shift value
- //is greater or equal to the data size of each lane, then the result is zero.
- //Additionally, negative shifts produces right shifts by the negated shift value.
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
- int MaxShift = 8 << Op.Size;
- EmitVectorBinaryZx(Context, () =>
- {
- AILLabel LblShl = new AILLabel();
- AILLabel LblZero = new AILLabel();
- AILLabel LblEnd = new AILLabel();
- void EmitShift(OpCode ILOp)
- {
- Context.Emit(OpCodes.Dup);
- Context.EmitLdc_I4(MaxShift);
- Context.Emit(OpCodes.Bge_S, LblZero);
- Context.Emit(ILOp);
- Context.Emit(OpCodes.Br_S, LblEnd);
- }
- Context.Emit(OpCodes.Conv_I1);
- Context.Emit(OpCodes.Dup);
- Context.EmitLdc_I4(0);
- Context.Emit(OpCodes.Bge_S, LblShl);
- Context.Emit(OpCodes.Neg);
- EmitShift(Signed
- ? OpCodes.Shr
- : OpCodes.Shr_Un);
- Context.MarkLabel(LblShl);
- EmitShift(OpCodes.Shl);
- Context.MarkLabel(LblZero);
- Context.Emit(OpCodes.Pop);
- Context.Emit(OpCodes.Pop);
- Context.EmitLdc_I8(0);
- Context.MarkLabel(LblEnd);
- });
- }
- private static void EmitVectorUnarySx(AILEmitterCtx Context, OpCode ILOp)
- {
- EmitVectorUnarySx(Context, () => Context.Emit(ILOp));
- }
- private static void EmitVectorUnaryZx(AILEmitterCtx Context, OpCode ILOp)
- {
- EmitVectorUnaryZx(Context, () => Context.Emit(ILOp));
- }
- private static void EmitVectorBinaryZx(AILEmitterCtx Context, OpCode ILOp)
- {
- EmitVectorBinaryZx(Context, () => Context.Emit(ILOp));
- }
- private static void EmitVectorUnarySx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOp(Context, Emit, 1, true);
- }
- private static void EmitVectorBinarySx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOp(Context, Emit, 2, true);
- }
- private static void EmitVectorUnaryZx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOp(Context, Emit, 1, false);
- }
- private static void EmitVectorBinaryZx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOp(Context, Emit, 2, false);
- }
- private static void EmitVectorTernaryZx(AILEmitterCtx Context, Action Emit)
- {
- EmitVectorOp(Context, Emit, 3, false);
- }
- private static void EmitVectorOp(AILEmitterCtx Context, Action Emit, int Opers, bool Signed)
- {
- if (Opers < 1 || Opers > 3)
- {
- throw new ArgumentOutOfRangeException(nameof(Opers));
- }
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
- int Bytes = Context.CurrOp.GetBitsCount() >> 3;
- for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
- {
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdc_I4(Index);
- Context.EmitLdc_I4(Op.Size);
- if (Opers == 3)
- {
- EmitVectorExtract(Context, Op.Rd, Index, Signed);
- }
- if (Opers >= 1)
- {
- EmitVectorExtract(Context, Op.Rn, Index, Signed);
- }
- if (Opers >= 2)
- {
- EmitVectorExtract(Context, ((AOpCodeSimdReg)Op).Rm, Index, Signed);
- }
- Emit();
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.InsertVec));
- Context.EmitStvec(Op.Rd);
- }
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- private static void EmitVectorImmBinarySx(AILEmitterCtx Context, OpCode ILOp, long Imm)
- {
- EmitVectorImmBinarySx(Context, () => Context.Emit(ILOp), Imm);
- }
- private static void EmitVectorImmBinaryZx(AILEmitterCtx Context, OpCode ILOp, long Imm)
- {
- EmitVectorImmBinaryZx(Context, () => Context.Emit(ILOp), Imm);
- }
- private static void EmitVectorImmBinarySx(AILEmitterCtx Context, Action Emit, long Imm)
- {
- EmitVectorImmBinaryOp(Context, Emit, Imm, true);
- }
- private static void EmitVectorImmBinaryZx(AILEmitterCtx Context, Action Emit, long Imm)
- {
- EmitVectorImmBinaryOp(Context, Emit, Imm, false);
- }
- private static void EmitVectorImmBinaryOp(AILEmitterCtx Context, Action Emit, long Imm, bool Signed)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
- int Bytes = Context.CurrOp.GetBitsCount() >> 3;
- for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
- {
- Context.EmitLdvec(Op.Rd);
- Context.EmitLdc_I4(Index);
- Context.EmitLdc_I4(Op.Size);
- EmitVectorExtract(Context, Op.Rn, Index, Signed);
- Context.EmitLdc_I8(Imm);
- Emit();
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.InsertVec));
- Context.EmitStvec(Op.Rd);
- }
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- private static void EmitVectorCmp(AILEmitterCtx Context, OpCode ILOp)
- {
- AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
- int Bytes = Context.CurrOp.GetBitsCount() >> 3;
- ulong SzMask = ulong.MaxValue >> (64 - (8 << Op.Size));
- for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
- {
- EmitVectorExtractSx(Context, Op.Rn, Index);
- if (Op is AOpCodeSimdReg BinOp)
- {
- EmitVectorExtractSx(Context, BinOp.Rm, Index);
- }
- else
- {
- Context.EmitLdc_I8(0);
- }
- AILLabel LblTrue = new AILLabel();
- AILLabel LblEnd = new AILLabel();
- Context.Emit(ILOp, LblTrue);
- EmitVectorInsert(Context, Op.Rd, Index, Op.Size, 0);
- Context.Emit(OpCodes.Br_S, LblEnd);
- Context.MarkLabel(LblTrue);
- EmitVectorInsert(Context, Op.Rd, Index, Op.Size, (long)SzMask);
- Context.MarkLabel(LblEnd);
- }
- if (Op.RegisterSize == ARegisterSize.SIMD64)
- {
- EmitVectorZeroUpper(Context, Op.Rd);
- }
- }
- private static void EmitVectorExtractSx(AILEmitterCtx Context, int Reg, int Index)
- {
- EmitVectorExtract(Context, Reg, Index, true);
- }
- private static void EmitVectorExtractZx(AILEmitterCtx Context, int Reg, int Index)
- {
- EmitVectorExtract(Context, Reg, Index, false);
- }
- private static void EmitVectorExtract(AILEmitterCtx Context, int Reg, int Index, bool Signed)
- {
- IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
- Context.EmitLdvec(Reg);
- Context.EmitLdc_I4(Index);
- Context.EmitLdc_I4(Op.Size);
- ASoftFallback.EmitCall(Context, Signed
- ? nameof(ASoftFallback.ExtractSVec)
- : nameof(ASoftFallback.ExtractVec));
- }
- private static void EmitVectorZeroLower(AILEmitterCtx Context, int Rd)
- {
- EmitVectorInsert(Context, Rd, 0, 3, 0);
- }
- private static void EmitVectorZeroUpper(AILEmitterCtx Context, int Rd)
- {
- EmitVectorInsert(Context, Rd, 1, 3, 0);
- }
- private static void EmitVectorInsert(AILEmitterCtx Context, int Reg, int Index, int Size, long Value)
- {
- Context.EmitLdvec(Reg);
- Context.EmitLdc_I4(Index);
- Context.EmitLdc_I4(Size);
- Context.EmitLdc_I8(Value);
- ASoftFallback.EmitCall(Context, nameof(ASoftFallback.InsertVec));
- Context.EmitStvec(Reg);
- }
- }
- }
|