Esempio n. 1
0
        private static void EmitCsel(AILEmitterCtx Context, CselOperation CselOp)
        {
            AOpCodeCsel Op = (AOpCodeCsel)Context.CurrOp;

            AILLabel LblTrue = new AILLabel();
            AILLabel LblEnd  = new AILLabel();

            Context.EmitCondBranch(LblTrue, Op.Cond);
            Context.EmitLdintzr(Op.Rm);

            if (CselOp == CselOperation.Increment)
            {
                Context.EmitLdc_I(1);

                Context.Emit(OpCodes.Add);
            }
            else if (CselOp == CselOperation.Invert)
            {
                Context.Emit(OpCodes.Not);
            }
            else if (CselOp == CselOperation.Negate)
            {
                Context.Emit(OpCodes.Neg);
            }

            Context.Emit(OpCodes.Br_S, LblEnd);

            Context.MarkLabel(LblTrue);

            Context.EmitLdintzr(Op.Rn);

            Context.MarkLabel(LblEnd);

            Context.EmitStintzr(Op.Rd);
        }
Esempio n. 2
0
        public static void EmitDataLoadOper2(AILEmitterCtx Context)
        {
            switch (Context.CurrOp)
            {
            case IAOpCodeAluImm Op:
                Context.EmitLdc_I(Op.Imm);
                break;

            case IAOpCodeAluRs Op:
                Context.EmitLdintzr(Op.Rm);

                switch (Op.ShiftType)
                {
                case AShiftType.Lsl: Context.EmitLsl(Op.Shift); break;

                case AShiftType.Lsr: Context.EmitLsr(Op.Shift); break;

                case AShiftType.Asr: Context.EmitAsr(Op.Shift); break;

                case AShiftType.Ror: Context.EmitRor(Op.Shift); break;
                }
                break;

            case IAOpCodeAluRx Op:
                Context.EmitLdintzr(Op.Rm);
                Context.EmitCast(Op.IntType);
                Context.EmitLsl(Op.Shift);
                break;
            }
        }
Esempio n. 3
0
        private static void EmitStore(AILEmitterCtx Context, AccessType AccType, bool Pair)
        {
            AOpCodeMemEx Op = (AOpCodeMemEx)Context.CurrOp;

            bool Ordered   = (AccType & AccessType.Ordered) != 0;
            bool Exclusive = (AccType & AccessType.Exclusive) != 0;

            if (Ordered)
            {
                EmitBarrier(Context);
            }

            AILLabel LblEx  = new AILLabel();
            AILLabel LblEnd = new AILLabel();

            if (Exclusive)
            {
                EmitMemoryCall(Context, nameof(AMemory.TestExclusive), Op.Rn);

                Context.Emit(OpCodes.Brtrue_S, LblEx);

                Context.EmitLdc_I8(1);
                Context.EmitStintzr(Op.Rs);

                Context.Emit(OpCodes.Br_S, LblEnd);
            }

            Context.MarkLabel(LblEx);

            Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
            Context.EmitLdint(Op.Rn);
            Context.EmitLdintzr(Op.Rt);

            EmitWriteCall(Context, Op.Size);

            if (Pair)
            {
                Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
                Context.EmitLdint(Op.Rn);
                Context.EmitLdc_I8(1 << Op.Size);

                Context.Emit(OpCodes.Add);

                Context.EmitLdintzr(Op.Rt2);

                EmitWriteCall(Context, Op.Size);
            }

            if (Exclusive)
            {
                Context.EmitLdc_I8(0);
                Context.EmitStintzr(Op.Rs);

                EmitMemoryCall(Context, nameof(AMemory.ClearExclusiveForStore));
            }

            Context.MarkLabel(LblEnd);
        }
Esempio n. 4
0
        private static void EmitSse42Crc32(AILEmitterCtx Context, Type TCrc, Type TData)
        {
            AOpCodeAluRs Op = (AOpCodeAluRs)Context.CurrOp;

            Context.EmitLdintzr(Op.Rn);
            Context.EmitLdintzr(Op.Rm);

            Context.EmitCall(typeof(Sse42).GetMethod(nameof(Sse42.Crc32), new Type[] { TCrc, TData }));

            Context.EmitStintzr(Op.Rd);
        }
Esempio n. 5
0
        public static void Umulh(AILEmitterCtx Context)
        {
            AOpCodeMul Op = (AOpCodeMul)Context.CurrOp;

            Context.EmitLdintzr(Op.Rn);
            Context.EmitLdintzr(Op.Rm);

            ASoftFallback.EmitCall(Context, nameof(ASoftFallback.UMulHi128));

            Context.EmitStintzr(Op.Rd);
        }
Esempio n. 6
0
        public static void Sbfm(AILEmitterCtx Context)
        {
            AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;

            int BitsCount = Op.GetBitsCount();

            if (Op.Pos + 1 == BitsCount)
            {
                EmitSbfmShift(Context);
            }
            else if (Op.Pos < Op.Shift)
            {
                EmitSbfiz(Context);
            }
            else if (Op.Pos == 7 && Op.Shift == 0)
            {
                EmitSbfmCast(Context, OpCodes.Conv_I1);
            }
            else if (Op.Pos == 15 && Op.Shift == 0)
            {
                EmitSbfmCast(Context, OpCodes.Conv_I2);
            }
            else if (Op.Pos == 31 && Op.Shift == 0)
            {
                EmitSbfmCast(Context, OpCodes.Conv_I4);
            }
            else if (Op.Shift == 0)
            {
                Context.EmitLdintzr(Op.Rn);

                Context.EmitLsl(BitsCount - 1 - Op.Pos);
                Context.EmitAsr(BitsCount - 1);

                Context.EmitStintzr(Op.Rd);
            }
            else
            {
                EmitBfmLoadRn(Context);

                Context.EmitLdintzr(Op.Rn);

                Context.EmitLsl(BitsCount - 1 - Op.Pos);
                Context.EmitAsr(BitsCount - 1);

                Context.EmitLdc_I(~Op.TMask);

                Context.Emit(OpCodes.And);
                Context.Emit(OpCodes.Or);

                Context.EmitStintzr(Op.Rd);
            }
        }
Esempio n. 7
0
        private static void EmitMul(AILEmitterCtx Context, OpCode ILOp)
        {
            AOpCodeMul Op = (AOpCodeMul)Context.CurrOp;

            Context.EmitLdintzr(Op.Ra);
            Context.EmitLdintzr(Op.Rn);
            Context.EmitLdintzr(Op.Rm);

            Context.Emit(OpCodes.Mul);
            Context.Emit(ILOp);

            Context.EmitStintzr(Op.Rd);
        }
Esempio n. 8
0
        public static void Msr(AILEmitterCtx Context)
        {
            AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp;

            Context.EmitLdarg(ATranslatedSub.StateArgIdx);
            Context.EmitLdintzr(Op.Rt);

            string PropName;

            switch (GetPackedId(Op))
            {
            case 0b11_011_0100_0100_000: PropName = nameof(AThreadState.Fpcr);     break;

            case 0b11_011_0100_0100_001: PropName = nameof(AThreadState.Fpsr);     break;

            case 0b11_011_1101_0000_010: PropName = nameof(AThreadState.TpidrEl0); break;

            default: throw new NotImplementedException($"Unknown MSR at {Op.Position:x16}");
            }

            PropertyInfo PropInfo = typeof(AThreadState).GetProperty(PropName);

            if (PropInfo.PropertyType != typeof(long) &&
                PropInfo.PropertyType != typeof(ulong))
            {
                Context.Emit(OpCodes.Conv_U4);
            }

            Context.EmitCallPropSet(typeof(AThreadState), PropName);
        }
Esempio n. 9
0
        private static void EmitLoadAddress(AILEmitterCtx Context)
        {
            switch (Context.CurrOp)
            {
            case AOpCodeMemImm Op:
                Context.EmitLdint(Op.Rn);

                if (!Op.PostIdx)
                {
                    //Pre-indexing.
                    Context.EmitLdc_I(Op.Imm);

                    Context.Emit(OpCodes.Add);
                }
                break;

            case AOpCodeMemReg Op:
                Context.EmitLdint(Op.Rn);
                Context.EmitLdintzr(Op.Rm);
                Context.EmitCast(Op.IntType);

                if (Op.Shift)
                {
                    Context.EmitLsl(Op.Size);
                }

                Context.Emit(OpCodes.Add);
                break;
            }

            //Save address to Scratch var since the register value may change.
            Context.Emit(OpCodes.Dup);

            Context.EmitSttmp();
        }
Esempio n. 10
0
        public static void Sys(AILEmitterCtx Context)
        {
            //This instruction is used to do some operations on the CPU like cache invalidation,
            //address translation and the like.
            //We treat it as no-op here since we don't have any cache being emulated anyway.
            AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp;

            switch (GetPackedId(Op))
            {
            case 0b11_011_0111_0100_001:
            {
                //DC ZVA
                for (int Offs = 0; Offs < (4 << AThreadState.DczSizeLog2); Offs += 8)
                {
                    Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
                    Context.EmitLdintzr(Op.Rt);
                    Context.EmitLdc_I(Offs);

                    Context.Emit(OpCodes.Add);

                    Context.EmitLdc_I8(0);

                    AInstEmitMemoryHelper.EmitWriteCall(Context, 3);
                }

                break;
            }

            //No-op
            case 0b11_011_0111_1110_001:     //DC CIVAC
                break;
            }
        }
Esempio n. 11
0
        public static void Fmov_Itof(AILEmitterCtx Context)
        {
            AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;

            Context.EmitLdintzr(Op.Rn);
            Context.EmitStvecsi(Op.Rd);
        }
Esempio n. 12
0
        public static void Br(AILEmitterCtx Context)
        {
            AOpCodeBReg Op = (AOpCodeBReg)Context.CurrOp;

            if (AOptimizations.GenerateCallStack)
            {
                Context.EmitLdarg(ATranslatedSub.StateArgIdx);
                Context.EmitLdintzr(Op.Rn);

                Context.EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.JumpMethod));
            }

            Context.EmitStoreState();
            Context.EmitLdintzr(Op.Rn);

            Context.Emit(OpCodes.Ret);
        }
Esempio n. 13
0
        public static void Ins_Gp(AILEmitterCtx Context)
        {
            AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;

            Context.EmitLdintzr(Op.Rn);

            EmitVectorInsert(Context, Op.Rd, Op.DstIndex, Op.Size);
        }
Esempio n. 14
0
        public static void Dup_Gp(AILEmitterCtx Context)
        {
            AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;

            if (AOptimizations.UseSse2)
            {
                Context.EmitLdintzr(Op.Rn);

                switch (Op.Size)
                {
                case 0: Context.Emit(OpCodes.Conv_U1); break;

                case 1: Context.Emit(OpCodes.Conv_U2); break;

                case 2: Context.Emit(OpCodes.Conv_U4); break;
                }

                Type[] Types = new Type[] { UIntTypesPerSizeLog2[Op.Size] };

                Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), Types));

                EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);

                if (Op.RegisterSize == ARegisterSize.SIMD64)
                {
                    EmitVectorZeroUpper(Context, Op.Rd);
                }
            }
            else
            {
                int Bytes = Op.GetBitsCount() >> 3;
                int Elems = Bytes >> Op.Size;

                for (int Index = 0; Index < Elems; Index++)
                {
                    Context.EmitLdintzr(Op.Rn);

                    EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
                }

                if (Op.RegisterSize == ARegisterSize.SIMD64)
                {
                    EmitVectorZeroUpper(Context, Op.Rd);
                }
            }
        }
Esempio n. 15
0
        private static void EmitCb(AILEmitterCtx Context, OpCode ILOp)
        {
            AOpCodeBImmCmp Op = (AOpCodeBImmCmp)Context.CurrOp;

            Context.EmitLdintzr(Op.Rt);
            Context.EmitLdc_I(0);

            EmitBranch(Context, ILOp);
        }
Esempio n. 16
0
        public static void Br(AILEmitterCtx Context)
        {
            AOpCodeBReg Op = (AOpCodeBReg)Context.CurrOp;

            Context.EmitStoreState();
            Context.EmitLdintzr(Op.Rn);

            Context.Emit(OpCodes.Ret);
        }
Esempio n. 17
0
        private static void EmitCb(AILEmitterCtx Context, OpCode ILOp)
        {
            AOpCodeBImmCmp Op = (AOpCodeBImmCmp)Context.CurrOp;

            Context.EmitLdintzr(Op.Rt);
            Context.EmitLdc_I(0);

            Context.Emit(ILOp, Context.GetLabel(Op.Imm));
        }
Esempio n. 18
0
        private static void EmitBfmLsl(AILEmitterCtx Context)
        {
            AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;

            Context.EmitLdintzr(Op.Rn);

            Context.EmitLsl(Op.GetBitsCount() - Op.Shift);

            Context.EmitStintzr(Op.Rd);
        }
Esempio n. 19
0
        public static void Scvtf_Gp(AILEmitterCtx Context)
        {
            AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;

            Context.EmitLdintzr(Op.Rn);

            EmitFloatCast(Context, Op.Size);

            Context.EmitStvecsf(Op.Rd);
        }
Esempio n. 20
0
        public static void Fmov_Itof(AILEmitterCtx Context)
        {
            AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;

            Context.EmitLdintzr(Op.Rn);

            EmitIntZeroHigherIfNeeded(Context);

            EmitScalarSet(Context, Op.Rd, 3);
        }
Esempio n. 21
0
        public static void Fmov_Itof1(AILEmitterCtx Context)
        {
            AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;

            Context.EmitLdintzr(Op.Rn);

            EmitIntZeroUpperIfNeeded(Context);

            EmitVectorInsert(Context, Op.Rd, 1, 3);
        }
Esempio n. 22
0
        public static void Rev64(AILEmitterCtx Context)
        {
            AOpCodeAlu Op = (AOpCodeAlu)Context.CurrOp;

            Context.EmitLdintzr(Op.Rn);

            ASoftFallback.EmitCall(Context, nameof(ASoftFallback.ReverseBytes64));

            Context.EmitStintzr(Op.Rd);
        }
Esempio n. 23
0
        public static void Bfm(AILEmitterCtx Context)
        {
            AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;

            EmitBfmLoadRn(Context);

            Context.EmitLdintzr(Op.Rd);
            Context.EmitLdc_I(~Op.WMask & Op.TMask);

            Context.Emit(OpCodes.And);
            Context.Emit(OpCodes.Or);

            Context.EmitLdintzr(Op.Rd);
            Context.EmitLdc_I(~Op.TMask);

            Context.Emit(OpCodes.And);
            Context.Emit(OpCodes.Or);

            Context.EmitStintzr(Op.Rd);
        }
Esempio n. 24
0
        public static void Blr(AILEmitterCtx Context)
        {
            AOpCodeBReg Op = (AOpCodeBReg)Context.CurrOp;

            Context.EmitLdc_I(Op.Position + 4);
            Context.EmitStint(AThreadState.LRIndex);
            Context.EmitStoreState();
            Context.EmitLdintzr(Op.Rn);

            Context.Emit(OpCodes.Ret);
        }
Esempio n. 25
0
        public static void Clz(AILEmitterCtx Context)
        {
            AOpCodeAlu Op = (AOpCodeAlu)Context.CurrOp;

            Context.EmitLdintzr(Op.Rn);

            Context.EmitLdc_I4(Op.RegisterSize == ARegisterSize.Int32 ? 32 : 64);

            ASoftFallback.EmitCall(Context, nameof(ASoftFallback.CountLeadingZeros));

            Context.EmitStintzr(Op.Rd);
        }
Esempio n. 26
0
        public static void Fmov_Itof1(AILEmitterCtx Context)
        {
            AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;

            Context.EmitLdintzr(Op.Rn);
            Context.EmitLdc_I4(1);
            Context.EmitLdc_I4(3);

            ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Fmov_S));

            Context.EmitStvec(Op.Rd);
        }
Esempio n. 27
0
        private static void EmitBfmLoadRn(AILEmitterCtx Context)
        {
            AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;

            Context.EmitLdintzr(Op.Rn);

            Context.EmitRor(Op.Shift);

            Context.EmitLdc_I(Op.WMask & Op.TMask);

            Context.Emit(OpCodes.And);
        }
Esempio n. 28
0
        private static void EmitCrc32(AILEmitterCtx Context, string Name)
        {
            AOpCodeAluRs Op = (AOpCodeAluRs)Context.CurrOp;

            Context.EmitLdintzr(Op.Rn);

            if (Op.RegisterSize != ARegisterSize.Int32)
            {
                Context.Emit(OpCodes.Conv_U4);
            }

            Context.EmitLdintzr(Op.Rm);

            ASoftFallback.EmitCall(Context, Name);

            if (Op.RegisterSize != ARegisterSize.Int32)
            {
                Context.Emit(OpCodes.Conv_U8);
            }

            Context.EmitStintzr(Op.Rd);
        }
Esempio n. 29
0
        private static void EmitBfmShift(AILEmitterCtx Context, bool Signed)
        {
            AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;

            Context.EmitLdintzr(Op.Rn);
            Context.EmitLdc_I4(Op.Shift);

            Context.Emit(Signed
                ? OpCodes.Shr
                : OpCodes.Shr_Un);

            Context.EmitStintzr(Op.Rd);
        }
Esempio n. 30
0
        public static void Extr(AILEmitterCtx Context)
        {
            //TODO: Ensure that the Shift is valid for the Is64Bits.
            AOpCodeAluRs Op = (AOpCodeAluRs)Context.CurrOp;

            Context.EmitLdintzr(Op.Rm);

            if (Op.Shift > 0)
            {
                Context.EmitLdc_I4(Op.Shift);

                Context.Emit(OpCodes.Shr_Un);

                Context.EmitLdintzr(Op.Rn);
                Context.EmitLdc_I4(Op.GetBitsCount() - Op.Shift);

                Context.Emit(OpCodes.Shl);
                Context.Emit(OpCodes.Or);
            }

            EmitDataStore(Context);
        }