예제 #1
0
        private static void EmitLoad(AILEmitterCtx Context, AccessType AccType, bool Pair)
        {
            AOpCodeMemEx Op = (AOpCodeMemEx)Context.CurrOp;

            if (AccType.HasFlag(AccessType.Ordered))
            {
                EmitBarrier(Context);
            }

            if (AccType.HasFlag(AccessType.Exclusive))
            {
                EmitMemoryCall(Context, nameof(AMemory.SetExclusive), Op.Rn);
            }

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

            EmitReadZxCall(Context, Op.Size);

            Context.EmitStintzr(Op.Rt);

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

                Context.Emit(OpCodes.Add);

                EmitReadZxCall(Context, Op.Size);

                Context.EmitStintzr(Op.Rt2);
            }
        }
예제 #2
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);
        }
예제 #3
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);
            }
        }
예제 #4
0
        private static void EmitMemoryCall(AILEmitterCtx Context, string Name, int Rn = -1)
        {
            Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
            Context.EmitLdarg(ATranslatedSub.StateArgIdx);

            if (Rn != -1)
            {
                Context.EmitLdint(Rn);
            }

            Context.EmitCall(typeof(AMemory), Name);
        }
예제 #5
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);
            }
        }
예제 #6
0
        public static void EmitSetFpsrQCFlag(AILEmitterCtx Context)
        {
            const int QCFlagBit = 27;

            Context.EmitLdarg(ATranslatedSub.StateArgIdx);

            Context.EmitLdarg(ATranslatedSub.StateArgIdx);
            Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpsr));

            Context.EmitLdc_I4(1 << QCFlagBit);

            Context.Emit(OpCodes.Or);

            Context.EmitCallPropSet(typeof(AThreadState), nameof(AThreadState.Fpsr));
        }
예제 #7
0
        public static void EmitLdr(AILEmitterCtx Context, bool Signed)
        {
            AOpCodeMem Op = (AOpCodeMem)Context.CurrOp;

            Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);

            EmitLoadAddress(Context);

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

            if (Op is IAOpCodeSimd)
            {
                Context.EmitStvec(Op.Rt);
            }
            else
            {
                Context.EmitStintzr(Op.Rt);
            }

            EmitWBackIfNeeded(Context);
        }
예제 #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);
        }
예제 #9
0
        public static void Fcvtl_V(AILEmitterCtx Context)
        {
            AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;

            int SizeF = Op.Size & 1;

            int Elems = 4 >> SizeF;

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

            for (int Index = 0; Index < Elems; Index++)
            {
                if (SizeF == 0)
                {
                    EmitVectorExtractZx(Context, Op.Rn, Part + Index, 1);
                    Context.Emit(OpCodes.Conv_U2);

                    Context.EmitLdarg(ATranslatedSub.StateArgIdx);

                    Context.EmitCall(typeof(ASoftFloat16_32), nameof(ASoftFloat16_32.FPConvert));
                }
                else /* if (SizeF == 1) */
                {
                    EmitVectorExtractF(Context, Op.Rn, Part + Index, 0);

                    Context.Emit(OpCodes.Conv_R8);
                }

                EmitVectorInsertTmpF(Context, Index, SizeF);
            }

            Context.EmitLdvectmp();
            Context.EmitStvec(Op.Rd);
        }
예제 #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.EmitLdint(Op.Rt);
                    Context.EmitLdc_I(Offs);

                    Context.Emit(OpCodes.Add);

                    Context.EmitLdc_I8(0);

                    AInstEmitMemoryHelper.EmitWriteCall(Context, 3);
                }
                break;
            }
            }
        }
예제 #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
        // TSrc (16bit, 32bit, 64bit; signed, unsigned) > TDst (8bit, 16bit, 32bit; signed, unsigned).
        public static void EmitSatQ(
            AILEmitterCtx Context,
            int SizeDst,
            bool SignedSrc,
            bool SignedDst)
        {
            if (SizeDst > 2)
            {
                throw new ArgumentOutOfRangeException(nameof(SizeDst));
            }

            Context.EmitLdc_I4(SizeDst);
            Context.EmitLdarg(ATranslatedSub.StateArgIdx);

            if (SignedSrc)
            {
                ASoftFallback.EmitCall(Context, SignedDst
                    ? nameof(ASoftFallback.SignedSrcSignedDstSatQ)
                    : nameof(ASoftFallback.SignedSrcUnsignedDstSatQ));
            }
            else
            {
                ASoftFallback.EmitCall(Context, SignedDst
                    ? nameof(ASoftFallback.UnsignedSrcSignedDstSatQ)
                    : nameof(ASoftFallback.UnsignedSrcUnsignedDstSatQ));
            }
        }
예제 #13
0
        public static void Frinti_V(AILEmitterCtx Context)
        {
            AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;

            int SizeF = Op.Size & 1;

            EmitVectorUnaryOpF(Context, () =>
            {
                Context.EmitLdarg(ATranslatedSub.StateArgIdx);

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

                if (SizeF == 0)
                {
                    AVectorHelper.EmitCall(Context, nameof(AVectorHelper.RoundF));
                }
                else if (SizeF == 1)
                {
                    AVectorHelper.EmitCall(Context, nameof(AVectorHelper.Round));
                }
                else
                {
                    throw new InvalidOperationException();
                }
            });
        }
예제 #14
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);
            }
        }
예제 #15
0
        // TSrc (64bit) == TDst (64bit); signed.
        public static void EmitUnarySignedSatQAbsOrNeg(AILEmitterCtx Context)
        {
            if (((AOpCodeSimd)Context.CurrOp).Size < 3)
            {
                throw new InvalidOperationException();
            }

            Context.EmitLdarg(ATranslatedSub.StateArgIdx);

            ASoftFallback.EmitCall(Context, nameof(ASoftFallback.UnarySignedSatQAbsOrNeg));
        }
예제 #16
0
        public static void Ldp(AILEmitterCtx Context)
        {
            AOpCodeMemPair Op = (AOpCodeMemPair)Context.CurrOp;

            void EmitReadAndStore(int Rt)
            {
                if (Op.Extend64)
                {
                    EmitReadSx64Call(Context, Op.Size);
                }
                else
                {
                    EmitReadZxCall(Context, Op.Size);
                }

                if (Op is IAOpCodeSimd)
                {
                    Context.EmitStvec(Rt);
                }
                else
                {
                    Context.EmitStintzr(Rt);
                }
            }

            Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);

            EmitLoadAddress(Context);

            EmitReadAndStore(Op.Rt);

            Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
            Context.EmitLdtmp();
            Context.EmitLdc_I8(1 << Op.Size);

            Context.Emit(OpCodes.Add);

            EmitReadAndStore(Op.Rt2);

            EmitWBackIfNeeded(Context);
        }
예제 #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 EmitSoftFloatCall(AILEmitterCtx Context, string Name)
        {
            IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;

            Type Type = (Op.Size & 1) == 0
                ? typeof(ASoftFloat_32)
                : typeof(ASoftFloat_64);

            Context.EmitLdarg(ATranslatedSub.StateArgIdx);

            Context.EmitCall(Type, Name);
        }
예제 #19
0
        // TSrcs (64bit) == TDst (64bit); signed, unsigned.
        public static void EmitBinarySatQAccumulate(AILEmitterCtx Context, bool Signed)
        {
            if (((AOpCodeSimd)Context.CurrOp).Size < 3)
            {
                throw new InvalidOperationException();
            }

            Context.EmitLdarg(ATranslatedSub.StateArgIdx);

            ASoftFallback.EmitCall(Context, Signed
                ? nameof(ASoftFallback.BinarySignedSatQAcc)
                : nameof(ASoftFallback.BinaryUnsignedSatQAcc));
        }
예제 #20
0
        public static void Stp(AILEmitterCtx Context)
        {
            AOpCodeMemPair Op = (AOpCodeMemPair)Context.CurrOp;

            Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);

            EmitLoadAddress(Context);

            if (Op is IAOpCodeSimd)
            {
                Context.EmitLdvec(Op.Rt);
            }
            else
            {
                Context.EmitLdintzr(Op.Rt);
            }

            EmitWriteCall(Context, Op.Size);

            Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
            Context.EmitLdtmp();
            Context.EmitLdc_I8(1 << Op.Size);

            Context.Emit(OpCodes.Add);

            if (Op is IAOpCodeSimd)
            {
                Context.EmitLdvec(Op.Rt2);
            }
            else
            {
                Context.EmitLdintzr(Op.Rt2);
            }

            EmitWriteCall(Context, Op.Size);

            EmitWBackIfNeeded(Context);
        }
예제 #21
0
        public static void Ret(AILEmitterCtx Context)
        {
            if (AOptimizations.GenerateCallStack)
            {
                Context.EmitLdarg(ATranslatedSub.StateArgIdx);

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

            Context.EmitStoreState();
            Context.EmitLdint(AThreadState.LRIndex);

            Context.Emit(OpCodes.Ret);
        }
예제 #22
0
        public static void Svc(AILEmitterCtx Context)
        {
            AOpCodeException Op = (AOpCodeException)Context.CurrOp;

            Context.EmitStoreState();

            Context.EmitLdarg(ATranslatedSub.RegistersArgIdx);

            Context.EmitLdc_I4(Op.Id);

            Context.EmitCall(typeof(ARegisters), nameof(ARegisters.OnSvcCall));

            if (Context.CurrBlock.Next != null)
            {
                Context.EmitLoadState(Context.CurrBlock.Next);
            }
        }
예제 #23
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);
        }
예제 #24
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);
            }
        }
예제 #25
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);

            if (Context.CurrBlock.Next != null)
            {
                Context.EmitLoadState(Context.CurrBlock.Next);
            }
        }
예제 #26
0
        public static void Mrs(AILEmitterCtx Context)
        {
            AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp;

            Context.EmitLdarg(ATranslatedSub.RegistersArgIdx);

            string PropName;

            switch (GetPackedId(Op))
            {
            case 0b11_011_0000_0000_001: PropName = nameof(ARegisters.CtrEl0);    break;

            case 0b11_011_0000_0000_111: PropName = nameof(ARegisters.DczidEl0);  break;

            case 0b11_011_0100_0100_000: PropName = nameof(ARegisters.Fpcr);      break;

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

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

            case 0b11_011_1101_0000_011: PropName = nameof(ARegisters.Tpidr);     break;

            case 0b11_011_1110_0000_001: PropName = nameof(ARegisters.CntpctEl0); break;

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

            Context.EmitCallPropGet(typeof(ARegisters), PropName);

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

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

            Context.EmitStintzr(Op.Rt);
        }
예제 #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 Frintx_S(AILEmitterCtx Context)
        {
            AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;

            EmitScalarUnaryOpF(Context, () =>
            {
                Context.EmitLdarg(ATranslatedSub.StateArgIdx);

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

                if (Op.Size == 0)
                {
                    ASoftFallback.EmitCall(Context, nameof(ASoftFallback.RoundF));
                }
                else if (Op.Size == 1)
                {
                    ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Round));
                }
                else
                {
                    throw new InvalidOperationException();
                }
            });
        }
예제 #29
0
        private static void EmitQxtn(AILEmitterCtx Context, bool Signed, bool Scalar)
        {
            AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;

            int Elems = (!Scalar ? 8 >> Op.Size : 1);
            int ESize = 8 << Op.Size;

            int TMaxValue = (Signed ? (1 << (ESize - 1)) - 1 : (int)((1L << ESize) - 1L));
            int TMinValue = (Signed ? -((1 << (ESize - 1))) : 0);

            int Part = (!Scalar & (Op.RegisterSize == ARegisterSize.SIMD128) ? Elems : 0);

            Context.EmitLdc_I8(0L);
            Context.EmitSttmp();

            for (int Index = 0; Index < Elems; Index++)
            {
                AILLabel LblLe    = new AILLabel();
                AILLabel LblGeEnd = new AILLabel();

                EmitVectorExtract(Context, Op.Rn, Index, Op.Size + 1, Signed);

                Context.Emit(OpCodes.Dup);

                Context.EmitLdc_I4(TMaxValue);
                Context.Emit(OpCodes.Conv_U8);

                Context.Emit(Signed ? OpCodes.Ble_S : OpCodes.Ble_Un_S, LblLe);

                Context.Emit(OpCodes.Pop);

                Context.EmitLdc_I4(TMaxValue);

                Context.EmitLdc_I8(0x8000000L);
                Context.EmitSttmp();

                Context.Emit(OpCodes.Br_S, LblGeEnd);

                Context.MarkLabel(LblLe);

                Context.Emit(OpCodes.Dup);

                Context.EmitLdc_I4(TMinValue);
                Context.Emit(OpCodes.Conv_I8);

                Context.Emit(Signed ? OpCodes.Bge_S : OpCodes.Bge_Un_S, LblGeEnd);

                Context.Emit(OpCodes.Pop);

                Context.EmitLdc_I4(TMinValue);

                Context.EmitLdc_I8(0x8000000L);
                Context.EmitSttmp();

                Context.MarkLabel(LblGeEnd);

                if (Scalar)
                {
                    EmitVectorZeroLower(Context, Op.Rd);
                }

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

            if (Part == 0)
            {
                EmitVectorZeroUpper(Context, Op.Rd);
            }

            Context.EmitLdarg(ATranslatedSub.StateArgIdx);
            Context.EmitLdarg(ATranslatedSub.StateArgIdx);
            Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpsr));
            Context.EmitLdtmp();
            Context.Emit(OpCodes.Conv_I4);
            Context.Emit(OpCodes.Or);
            Context.EmitCallPropSet(typeof(AThreadState), nameof(AThreadState.Fpsr));
        }
예제 #30
0
        private static void EmitSimdMemSs(AILEmitterCtx Context, bool IsLoad)
        {
            AOpCodeSimdMemSs Op = (AOpCodeSimdMemSs)Context.CurrOp;

            int Offset = 0;

            void EmitMemAddress()
            {
                Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
                Context.EmitLdint(Op.Rn);
                Context.EmitLdc_I8(Offset);

                Context.Emit(OpCodes.Add);
            }

            if (Op.Replicate)
            {
                //Only loads uses the replicate mode.
                if (!IsLoad)
                {
                    throw new InvalidOperationException();
                }

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

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

                    for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
                    {
                        EmitMemAddress();

                        EmitReadZxCall(Context, Op.Size);

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

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

                    Offset += 1 << Op.Size;
                }
            }
            else
            {
                for (int SElem = 0; SElem < Op.SElems; SElem++)
                {
                    int Rt = (Op.Rt + SElem) & 0x1f;

                    if (IsLoad)
                    {
                        EmitMemAddress();

                        EmitReadZxCall(Context, Op.Size);

                        EmitVectorInsert(Context, Rt, Op.Index, Op.Size);
                    }
                    else
                    {
                        EmitMemAddress();

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

                        EmitWriteCall(Context, Op.Size);
                    }

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

            if (Op.WBack)
            {
                EmitSimdMemWBack(Context, Offset);
            }
        }