예제 #1
0
        private static void EmitBranch(AILEmitterCtx Context, OpCode ILOp)
        {
            AOpCodeBImm Op = (AOpCodeBImm)Context.CurrOp;

            if (Context.CurrBlock.Next != null &&
                Context.CurrBlock.Branch != null)
            {
                Context.Emit(ILOp, Context.GetLabel(Op.Imm));
            }
            else
            {
                Context.EmitStoreState();

                AILLabel LblTaken = new AILLabel();

                Context.Emit(ILOp, LblTaken);

                Context.EmitLdc_I8(Op.Position + 4);

                Context.Emit(OpCodes.Ret);

                Context.MarkLabel(LblTaken);

                Context.EmitLdc_I8(Op.Imm);

                Context.Emit(OpCodes.Ret);
            }
        }
예제 #2
0
        public static void Und(AILEmitterCtx Context)
        {
            AOpCode Op = Context.CurrOp;

            Context.EmitStoreState();

            Context.EmitLdarg(ATranslatedSub.StateArgIdx);

            Context.EmitLdc_I8(Op.Position);
            Context.EmitLdc_I4(Op.RawOpCode);

            string MthdName = nameof(AThreadState.OnUndefined);

            MethodInfo MthdInfo = typeof(AThreadState).GetMethod(MthdName, Binding);

            Context.EmitCall(MthdInfo);

            if (Context.CurrBlock.Next != null)
            {
                Context.EmitLoadState(Context.CurrBlock.Next);
            }
            else
            {
                Context.EmitLdc_I8(Op.Position + 4);

                Context.Emit(OpCodes.Ret);
            }
        }
예제 #3
0
        private static void EmitDoublingMultiplyHighHalf(AILEmitterCtx Context, bool Round)
        {
            AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;

            int ESize = 8 << Op.Size;

            Context.Emit(OpCodes.Mul);

            if (!Round)
            {
                Context.EmitAsr(ESize - 1);
            }
            else
            {
                long RoundConst = 1L << (ESize - 1);

                AILLabel LblTrue = new AILLabel();

                Context.EmitLsl(1);

                Context.EmitLdc_I8(RoundConst);

                Context.Emit(OpCodes.Add);

                Context.EmitAsr(ESize);

                Context.Emit(OpCodes.Dup);
                Context.EmitLdc_I8((long)int.MinValue);
                Context.Emit(OpCodes.Bne_Un_S, LblTrue);

                Context.Emit(OpCodes.Neg);

                Context.MarkLabel(LblTrue);
            }
        }
예제 #4
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);
        }
예제 #5
0
        private static void EmitSimdMemMs(AILEmitterCtx Context, bool IsLoad)
        {
            AOpCodeSimdMemMs Op = (AOpCodeSimdMemMs)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.EmitLdarg(ATranslatedSub.MemoryArgIdx);
                            Context.EmitLdint(Op.Rn);
                            Context.EmitLdc_I8(Offset);

                            Context.Emit(OpCodes.Add);

                            EmitReadZxCall(Context, Op.Size);

                            EmitVectorInsert(Context, Rtt, Elem, Op.Size);

                            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);

                            EmitVectorExtractZx(Context, Rtt, Elem, Op.Size);

                            EmitWriteCall(Context, Op.Size);
                        }

                        Offset += 1 << Op.Size;
                    }
                }
            }

            if (Op.WBack)
            {
                EmitSimdMemWBack(Context, Offset);
            }
        }
예제 #6
0
        private static void EmitSimdMemSs(AILEmitterCtx Context, bool IsLoad)
        {
            AOpCodeSimdMemSs Op = (AOpCodeSimdMemSs)Context.CurrOp;

            //TODO: Replicate mode.

            int Offset = 0;

            for (int SElem = 0; SElem < Op.SElems; SElem++)
            {
                int Rt = (Op.Rt + SElem) & 0x1f;

                if (IsLoad)
                {
                    Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
                    Context.EmitLdint(Op.Rn);
                    Context.EmitLdc_I8(Offset);

                    Context.Emit(OpCodes.Add);

                    EmitReadZxCall(Context, Op.Size);

                    EmitVectorInsert(Context, Rt, Op.Index, Op.Size);

                    if (Op.RegisterSize == ARegisterSize.SIMD64)
                    {
                        EmitVectorZeroUpper(Context, Rt);
                    }
                }
                else
                {
                    Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
                    Context.EmitLdint(Op.Rn);
                    Context.EmitLdc_I8(Offset);

                    Context.Emit(OpCodes.Add);

                    EmitVectorExtractZx(Context, Rt, Op.Index, Op.Size);

                    EmitWriteCall(Context, Op.Size);
                }

                Offset += 1 << Op.Size;
            }

            if (Op.WBack)
            {
                EmitSimdMemWBack(Context, Offset);
            }
        }
예제 #7
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.EmitLdint(Op.Rt);
                    Context.EmitLdc_I(Offs);

                    Context.Emit(OpCodes.Add);

                    Context.EmitLdc_I8(0);

                    AInstEmitMemoryHelper.EmitWriteCall(Context, 3);
                }
                break;
            }
            }
        }
예제 #8
0
        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, Op.Size, 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);
            }
        }
예제 #9
0
        public static void EmitVectorImmOp(AILEmitterCtx Context, Action Emit, bool Binary)
        {
            AOpCodeSimdImm Op = (AOpCodeSimdImm)Context.CurrOp;

            int Bytes = Context.CurrOp.GetBitsCount() >> 3;

            for (int Index = 0; Index < (Bytes >> Op.Size); 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 == ARegisterSize.SIMD64)
            {
                EmitVectorZeroUpper(Context, Op.Rd);
            }
        }
예제 #10
0
        public static void Sli_V(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            int Bytes = Op.GetBitsCount() >> 3;
            int Elems = Bytes >> Op.Size;

            int Shift = GetImmShl(Op);

            ulong Mask = Shift != 0 ? ulong.MaxValue >> (64 - Shift) : 0;

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

                Context.EmitLdc_I4(Shift);

                Context.Emit(OpCodes.Shl);

                EmitVectorExtractZx(Context, Op.Rd, Index, Op.Size);

                Context.EmitLdc_I8((long)Mask);

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

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

            if (Op.RegisterSize == ARegisterSize.SIMD64)
            {
                EmitVectorZeroUpper(Context, Op.Rd);
            }
        }
예제 #11
0
        public static void LdrLit(AILEmitterCtx Context)
        {
            IAOpCodeLit Op = (IAOpCodeLit)Context.CurrOp;

            if (Op.Prefetch)
            {
                return;
            }

            Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
            Context.EmitLdc_I8(Op.Imm);

            if (Op.Signed)
            {
                EmitReadSx64Call(Context, Op.Size);
            }
            else
            {
                EmitReadZxCall(Context, Op.Size);
            }

            if (Op is IAOpCodeSimd)
            {
                Context.EmitStvec(Op.Rt);
            }
            else
            {
                Context.EmitStint(Op.Rt);
            }
        }
예제 #12
0
        private static void EmitHighNarrow(AILEmitterCtx Context, Action Emit, bool Round)
        {
            AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;

            int Elems = 8 >> Op.Size;
            int ESize = 8 << Op.Size;

            int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0;

            for (int Index = 0; Index < Elems; Index++)
            {
                EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size + 1);
                EmitVectorExtractZx(Context, Op.Rm, Index, Op.Size + 1);

                Emit();

                if (Round)
                {
                    Context.EmitLdc_I8(1L << (ESize - 1));

                    Context.Emit(OpCodes.Add);
                }

                Context.EmitLsr(ESize);

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

            if (Part == 0)
            {
                EmitVectorZeroUpper(Context, Op.Rd);
            }
        }
예제 #13
0
        public static void Fmov_Si(AILEmitterCtx Context)
        {
            AOpCodeSimdFmov Op = (AOpCodeSimdFmov)Context.CurrOp;

            Context.EmitLdc_I8(Op.Imm);

            EmitScalarSet(Context, Op.Rd, Op.Size + 2);
        }
예제 #14
0
        public static void Bl(AILEmitterCtx Context)
        {
            AOpCodeBImmAl Op = (AOpCodeBImmAl)Context.CurrOp;

            if (AOptimizations.GenerateCallStack)
            {
                Context.EmitLdarg(ATranslatedSub.StateArgIdx);
                Context.EmitLdc_I8(Op.Imm);

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

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

            if (Context.TryOptEmitSubroutineCall())
            {
                //Note: the return value of the called method will be placed
                //at the Stack, the return value is always a Int64 with the
                //return address of the function. We check if the address is
                //correct, if it isn't we keep returning until we reach the dispatcher.
                Context.Emit(OpCodes.Dup);

                Context.EmitLdc_I8(Op.Position + 4);

                AILLabel LblContinue = new AILLabel();

                Context.Emit(OpCodes.Beq_S, LblContinue);
                Context.Emit(OpCodes.Ret);

                Context.MarkLabel(LblContinue);

                Context.Emit(OpCodes.Pop);

                Context.EmitLoadState(Context.CurrBlock.Next);
            }
            else
            {
                Context.EmitLdc_I8(Op.Imm);

                Context.Emit(OpCodes.Ret);
            }
        }
예제 #15
0
        private static void EmitShrImmOp(AILEmitterCtx Context, ShrImmFlags Flags)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            bool Scalar     = (Flags & ShrImmFlags.Scalar) != 0;
            bool Signed     = (Flags & ShrImmFlags.Signed) != 0;
            bool Round      = (Flags & ShrImmFlags.Round) != 0;
            bool Accumulate = (Flags & ShrImmFlags.Accumulate) != 0;

            int Shift = GetImmShr(Op);

            long RoundConst = 1L << (Shift - 1);

            int Bytes = Op.GetBitsCount() >> 3;
            int Elems = !Scalar ? Bytes >> Op.Size : 1;

            for (int Index = 0; Index < Elems; Index++)
            {
                EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed);

                if (Op.Size <= 2)
                {
                    if (Round)
                    {
                        Context.EmitLdc_I8(RoundConst);

                        Context.Emit(OpCodes.Add);
                    }

                    Context.EmitLdc_I4(Shift);

                    Context.Emit(Signed ? OpCodes.Shr : OpCodes.Shr_Un);
                }
                else /* if (Op.Size == 3) */
                {
                    EmitShrImm_64(Context, Signed, Round ? RoundConst : 0L, Shift);
                }

                if (Accumulate)
                {
                    EmitVectorExtract(Context, Op.Rd, Index, Op.Size, Signed);

                    Context.Emit(OpCodes.Add);
                }

                EmitVectorInsertTmp(Context, Index, Op.Size);
            }

            Context.EmitLdvectmp();
            Context.EmitStvec(Op.Rd);

            if ((Op.RegisterSize == ARegisterSize.SIMD64) || Scalar)
            {
                EmitVectorZeroUpper(Context, Op.Rd);
            }
        }
예제 #16
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);
        }
예제 #17
0
        private static void EmitExceptionCall(AILEmitterCtx Context, string MthdName)
        {
            AOpCodeException Op = (AOpCodeException)Context.CurrOp;

            Context.EmitStoreState();

            Context.EmitLdarg(ATranslatedSub.StateArgIdx);

            Context.EmitLdc_I4(Op.Id);

            MethodInfo MthdInfo = typeof(AThreadState).GetMethod(MthdName, Binding);

            Context.EmitCall(MthdInfo);

            //Check if the thread should still be running, if it isn't then we return 0
            //to force a return to the dispatcher and then exit the thread.
            Context.EmitLdarg(ATranslatedSub.StateArgIdx);

            Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Running));

            AILLabel LblEnd = new AILLabel();

            Context.Emit(OpCodes.Brtrue_S, LblEnd);

            Context.EmitLdc_I8(0);

            Context.Emit(OpCodes.Ret);

            Context.MarkLabel(LblEnd);

            if (Context.CurrBlock.Next != null)
            {
                Context.EmitLoadState(Context.CurrBlock.Next);
            }
            else
            {
                Context.EmitLdc_I8(Op.Position + 4);

                Context.Emit(OpCodes.Ret);
            }
        }
예제 #18
0
        public static void Fmov_S(AILEmitterCtx Context)
        {
            AOpCodeSimdFmov Op = (AOpCodeSimdFmov)Context.CurrOp;

            Context.EmitLdc_I8(Op.Imm);
            Context.EmitLdc_I4(0);
            Context.EmitLdc_I4(Op.Size + 2);

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

            Context.EmitStvec(Op.Rd);
        }
예제 #19
0
        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);
            });
        }
예제 #20
0
        // Dst_64 = (Int(Src_64, Signed) + RoundConst) >> Shift;
        private static void EmitShrImm_64(
            AILEmitterCtx Context,
            bool Signed,
            long RoundConst,
            int Shift)
        {
            Context.EmitLdc_I8(RoundConst);
            Context.EmitLdc_I4(Shift);

            ASoftFallback.EmitCall(Context, Signed
                ? nameof(ASoftFallback.SignedShrImm_64)
                : nameof(ASoftFallback.UnsignedShrImm_64));
        }
예제 #21
0
        public static void Bl(AILEmitterCtx Context)
        {
            AOpCodeBImmAl Op = (AOpCodeBImmAl)Context.CurrOp;

            Context.EmitLdc_I(Op.Position + 4);
            Context.EmitStint(ARegisters.LRIndex);
            Context.EmitStoreState();

            if (Context.TryOptEmitSubroutineCall())
            {
                //Note: the return value of the called method will be placed
                //at the Stack, the return value is always a Int64 with the
                //return address of the function. We check if the address is
                //correct, if it isn't we keep returning until we reach the dispatcher.
                Context.Emit(OpCodes.Dup);

                Context.EmitLdc_I8(Op.Position + 4);

                AILLabel LblContinue = new AILLabel();

                Context.Emit(OpCodes.Beq_S, LblContinue);
                Context.Emit(OpCodes.Ret);

                Context.MarkLabel(LblContinue);

                Context.Emit(OpCodes.Pop);

                if (Context.CurrBlock.Next != null)
                {
                    Context.EmitLoadState(Context.CurrBlock.Next);
                }
            }
            else
            {
                Context.EmitLdc_I8(Op.Imm);

                Context.Emit(OpCodes.Ret);
            }
        }
예제 #22
0
        public static void EmitVectorInsert(AILEmitterCtx 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);

            AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertInt));

            Context.EmitStvec(Reg);
        }
예제 #23
0
        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);
        }
예제 #24
0
        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);
        }
예제 #25
0
        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);
        }
예제 #26
0
        // TSrc (8bit, 16bit, 32bit, 64bit) == TDst (8bit, 16bit, 32bit, 64bit); signed.
        public static void EmitUnarySignedSatQAbsOrNeg(AILEmitterCtx Context, int Size)
        {
            int ESize = 8 << Size;

            long TMaxValue = (1L << (ESize - 1)) - 1L;
            long TMinValue = -(1L << (ESize - 1));

            AILLabel LblFalse = new AILLabel();

            Context.Emit(OpCodes.Dup);
            Context.Emit(OpCodes.Neg);
            Context.EmitLdc_I8(TMinValue);
            Context.Emit(OpCodes.Ceq);
            Context.Emit(OpCodes.Brfalse_S, LblFalse);

            Context.Emit(OpCodes.Pop);

            EmitSetFpsrQCFlag(Context);

            Context.EmitLdc_I8(TMaxValue);

            Context.MarkLabel(LblFalse);
        }
예제 #27
0
        public static void Und(AILEmitterCtx Context)
        {
            AOpCode Op = Context.CurrOp;

            Context.EmitStoreState();

            Context.EmitLdarg(ATranslatedSub.StateArgIdx);

            Context.EmitLdc_I8(Op.Position);
            Context.EmitLdc_I4(Op.RawOpCode);

            Context.EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.OnUndefined));

            if (Context.CurrBlock.Next != null)
            {
                Context.EmitLoadState(Context.CurrBlock.Next);
            }
            else
            {
                Context.EmitLdc_I8(Op.Position + 4);

                Context.Emit(OpCodes.Ret);
            }
        }
예제 #28
0
        public static void B(AILEmitterCtx Context)
        {
            AOpCodeBImmAl Op = (AOpCodeBImmAl)Context.CurrOp;

            if (Context.CurrBlock.Branch != null)
            {
                Context.Emit(OpCodes.Br, Context.GetLabel(Op.Imm));
            }
            else
            {
                Context.EmitStoreState();
                Context.EmitLdc_I8(Op.Imm);

                Context.Emit(OpCodes.Ret);
            }
        }
예제 #29
0
        public static void EmitVectorInsert(AILEmitterCtx Context, int Reg, int Index, int Size, long Value)
        {
            if (Size < 0 || Size > 3)
            {
                throw new ArgumentOutOfRangeException(nameof(Size));
            }

            Context.EmitLdc_I8(Value);
            Context.EmitLdvec(Reg);
            Context.EmitLdc_I4(Index);
            Context.EmitLdc_I4(Size);

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

            Context.EmitStvec(Reg);
        }
예제 #30
0
        public static void Fmov_V(AILEmitterCtx Context)
        {
            AOpCodeSimdImm Op = (AOpCodeSimdImm)Context.CurrOp;

            int Elems = Op.RegisterSize == ARegisterSize.SIMD128 ? 4 : 2;

            for (int Index = 0; Index < (Elems >> Op.Size); Index++)
            {
                Context.EmitLdc_I8(Op.Imm);

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

            if (Op.RegisterSize == ARegisterSize.SIMD64)
            {
                EmitVectorZeroUpper(Context, Op.Rd);
            }
        }