예제 #1
0
        private static void EmitBranch(ILEmitterCtx context, Cond cond)
        {
            OpCodeBImm64 op = (OpCodeBImm64)context.CurrOp;

            if (context.CurrBlock.Next != null &&
                context.CurrBlock.Branch != null)
            {
                context.EmitCondBranch(context.GetLabel(op.Imm), cond);
            }
            else
            {
                context.EmitStoreState();

                ILLabel lblTaken = new ILLabel();

                context.EmitCondBranch(lblTaken, cond);

                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 EmitCall(ILEmitterCtx context, long imm)
        {
            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(context.CurrOp.Position + 4);

                ILLabel lblContinue = new ILLabel();

                context.Emit(OpCodes.Beq_S, lblContinue);
                context.Emit(OpCodes.Ret);

                context.MarkLabel(lblContinue);

                context.Emit(OpCodes.Pop);

                context.EmitLoadState();
            }
            else
            {
                context.EmitLdc_I8(imm);

                context.Emit(OpCodes.Ret);
            }
        }
예제 #3
0
        public static void Rev16_V(ILEmitterCtx context)
        {
            if (Optimizations.UseSsse3)
            {
                OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;

                Type[] typesSve = new Type[] { typeof(long), typeof(long) };
                Type[] typesSfl = new Type[] { typeof(Vector128 <sbyte>), typeof(Vector128 <sbyte>) };

                context.EmitLdvec(op.Rn);                                                                                        // value

                context.EmitLdc_I8(14L << 56 | 15L << 48 | 12L << 40 | 13L << 32 | 10L << 24 | 11L << 16 | 08L << 8 | 09L << 0); // maskE1
                context.EmitLdc_I8(06L << 56 | 07L << 48 | 04L << 40 | 05L << 32 | 02L << 24 | 03L << 16 | 00L << 8 | 01L << 0); // maskE0

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve));

                context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), typesSfl));

                context.EmitStvec(op.Rd);

                if (op.RegisterSize == RegisterSize.Simd64)
                {
                    EmitVectorZeroUpper(context, op.Rd);
                }
            }
            else
            {
                EmitRev_V(context, containerSize: 1);
            }
        }
예제 #4
0
        private static void EmitStore(ILEmitterCtx context, AccessType accType, bool pair)
        {
            OpCodeMemEx64 op = (OpCodeMemEx64)context.CurrOp;

            bool ordered   = (accType & AccessType.Ordered) != 0;
            bool exclusive = (accType & AccessType.Exclusive) != 0;

            if (ordered)
            {
                EmitBarrier(context);
            }

            ILLabel lblEx  = new ILLabel();
            ILLabel lblEnd = new ILLabel();

            if (exclusive)
            {
                EmitMemoryCall(context, nameof(MemoryManager.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(TranslatedSub.MemoryArgIdx);
            context.EmitLdint(op.Rn);
            context.EmitLdintzr(op.Rt);

            EmitWriteCall(context, op.Size);

            if (pair)
            {
                context.EmitLdarg(TranslatedSub.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(MemoryManager.ClearExclusiveForStore));
            }

            context.MarkLabel(lblEnd);
        }
예제 #5
0
        private static void EmitSimdMemMs(ILEmitterCtx context, bool isLoad)
        {
            OpCodeSimdMemMs64 op = (OpCodeSimdMemMs64)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(TranslatedSub.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 == RegisterSize.Simd64 && elem == op.Elems - 1)
                            {
                                EmitVectorZeroUpper(context, rtt);
                            }
                        }
                        else
                        {
                            context.EmitLdarg(TranslatedSub.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
        public static void Rshrn_V(ILEmitterCtx context)
        {
            if (Optimizations.UseSsse3)
            {
                OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp;

                Type[] typesAdd = new Type[] { VectorUIntTypesPerSizeLog2[op.Size + 1], VectorUIntTypesPerSizeLog2[op.Size + 1] };
                Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size + 1], typeof(byte) };
                Type[] typesSfl = new Type[] { typeof(Vector128 <sbyte>), typeof(Vector128 <sbyte>) };
                Type[] typesSav = new Type[] { UIntTypesPerSizeLog2[op.Size + 1] };
                Type[] typesSve = new Type[] { typeof(long), typeof(long) };

                string nameMov = op.RegisterSize == RegisterSize.Simd128
                    ? nameof(Sse.MoveLowToHigh)
                    : nameof(Sse.MoveHighToLow);

                int shift = GetImmShr(op);

                long roundConst = 1L << (shift - 1);

                context.EmitLdvec(op.Rd);
                VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero));

                context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveLowToHigh)));

                context.EmitLdvec(op.Rn);

                context.EmitLdc_I8(roundConst);
                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav));

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd));

                context.EmitLdc_I4(shift);
                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesSrl)); // value

                context.EmitLdc_I8(_masks_RshrnShrn[op.Size]);                                      // mask
                context.Emit(OpCodes.Dup);                                                          // mask

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve));

                context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), typesSfl));

                context.EmitCall(typeof(Sse).GetMethod(nameMov));

                context.EmitStvec(op.Rd);
            }
            else
            {
                EmitVectorShrImmNarrowOpZx(context, round: true);
            }
        }
예제 #7
0
        public static void Stp(ILEmitterCtx context)
        {
            OpCodeMemPair64 op = (OpCodeMemPair64)context.CurrOp;

            EmitLoadAddress(context);

            if (op is IOpCodeSimd64)
            {
                context.EmitLdvec(op.Rt);
            }
            else
            {
                context.EmitLdintzr(op.Rt);
            }

            EmitWriteCall(context, op.Size);

            context.EmitLdtmp();
            context.EmitLdc_I8(1 << op.Size);

            context.Emit(OpCodes.Add);

            if (op is IOpCodeSimd64)
            {
                context.EmitLdvec(op.Rt2);
            }
            else
            {
                context.EmitLdintzr(op.Rt2);
            }

            EmitWriteCall(context, op.Size);

            EmitWBackIfNeeded(context);
        }
예제 #8
0
        public static void Orn_V(ILEmitterCtx context)
        {
            if (Optimizations.UseSse2)
            {
                OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;

                Type[] typesSav   = new Type[] { typeof(long) };
                Type[] typesAntOr = new Type[] { typeof(Vector128 <long>), typeof(Vector128 <long>) };

                context.EmitLdvec(op.Rn);
                context.EmitLdvec(op.Rm);

                context.EmitLdc_I8(-1L);
                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav));

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAntOr));
                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Or), typesAntOr));

                context.EmitStvec(op.Rd);

                if (op.RegisterSize == RegisterSize.Simd64)
                {
                    EmitVectorZeroUpper(context, op.Rd);
                }
            }
            else
            {
                EmitVectorBinaryOpZx(context, () =>
                {
                    context.Emit(OpCodes.Not);
                    context.Emit(OpCodes.Or);
                });
            }
        }
예제 #9
0
        public static void Sli_V(ILEmitterCtx context)
        {
            OpCodeSimdShImm64 op = (OpCodeSimdShImm64)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 == RegisterSize.Simd64)
            {
                EmitVectorZeroUpper(context, op.Rd);
            }
        }
예제 #10
0
        private static void EmitMoviMvni(ILEmitterCtx context, bool not)
        {
            OpCodeSimdImm64 op = (OpCodeSimdImm64)context.CurrOp;

            Type[] typesSav = new Type[] { UIntTypesPerSizeLog2[op.Size] };

            long imm = op.Imm;

            if (not)
            {
                imm = ~imm;
            }

            if (op.Size < 3)
            {
                context.EmitLdc_I4((int)imm);
            }
            else
            {
                context.EmitLdc_I8(imm);
            }

            context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav));

            context.EmitStvec(op.Rd);

            if (op.RegisterSize == RegisterSize.Simd64)
            {
                EmitVectorZeroUpper(context, op.Rd);
            }
        }
예제 #11
0
        public static void Ldr_Literal(ILEmitterCtx context)
        {
            IOpCodeLit64 op = (IOpCodeLit64)context.CurrOp;

            if (op.Prefetch)
            {
                return;
            }

            context.EmitLdc_I8(op.Imm);

            if (op.Signed)
            {
                EmitReadSx64Call(context, op.Size);
            }
            else
            {
                EmitReadZxCall(context, op.Size);
            }

            if (op is IOpCodeSimd64)
            {
                context.EmitStvec(op.Rt);
            }
            else
            {
                context.EmitStint(op.Rt);
            }
        }
예제 #12
0
        private static void EmitContinueOrReturnCheck(ILEmitterCtx context)
        {
            // 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.
            if (context.CurrBlock.Next != null)
            {
                context.Emit(OpCodes.Dup);

                context.EmitLdc_I8(context.CurrOp.Position + 4);

                ILLabel lblContinue = new ILLabel();

                context.Emit(OpCodes.Beq_S, lblContinue);
                context.Emit(OpCodes.Ret);

                context.MarkLabel(lblContinue);

                context.Emit(OpCodes.Pop);

                context.EmitLoadContext();
            }
            else
            {
                context.Emit(OpCodes.Ret);
            }
        }
예제 #13
0
        public static void Sys(ILEmitterCtx 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.
            OpCodeSystem64 op = (OpCodeSystem64)context.CurrOp;

            switch (GetPackedId(op))
            {
            case 0b11_011_0111_0100_001:
            {
                //DC ZVA
                for (int offs = 0; offs < (4 << CpuThreadState.DczSizeLog2); offs += 8)
                {
                    context.EmitLdarg(TranslatedSub.MemoryArgIdx);
                    context.EmitLdintzr(op.Rt);
                    context.EmitLdc_I(offs);

                    context.Emit(OpCodes.Add);

                    context.EmitLdc_I8(0);

                    InstEmitMemoryHelper.EmitWriteCall(context, 3);
                }

                break;
            }

            //No-op
            case 0b11_011_0111_1110_001:     //DC CIVAC
                break;
            }
        }
예제 #14
0
        public static void EmitVectorImmOp(ILEmitterCtx context, Action emit, bool binary)
        {
            OpCodeSimdImm64 op = (OpCodeSimdImm64)context.CurrOp;

            int bytes = op.GetBitsCount() >> 3;
            int elems = bytes >> op.Size;

            for (int index = 0; index < elems; index++)
            {
                if (binary)
                {
                    EmitVectorExtractZx(context, op.Rd, index, op.Size);
                }

                context.EmitLdc_I8(op.Imm);

                emit();

                EmitVectorInsert(context, op.Rd, index, op.Size);
            }

            if (op.RegisterSize == RegisterSize.Simd64)
            {
                EmitVectorZeroUpper(context, op.Rd);
            }
        }
예제 #15
0
        public static void Cmle_V(ILEmitterCtx context)
        {
            if (Optimizations.UseSse42)
            {
                OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;

                Type[] typesCmp = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] };
                Type[] typesAnt = new Type[] { typeof(Vector128 <long>), typeof(Vector128 <long>) };
                Type[] typesSav = new Type[] { typeof(long) };

                Type typeSse = op.Size != 3 ? typeof(Sse2) : typeof(Sse42);

                context.EmitLdvec(op.Rn);
                VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero));

                context.EmitCall(typeSse.GetMethod(nameof(Sse2.CompareGreaterThan), typesCmp));

                context.EmitLdc_I8(-1L);
                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav));

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAnt));

                context.EmitStvec(op.Rd);

                if (op.RegisterSize == RegisterSize.Simd64)
                {
                    EmitVectorZeroUpper(context, op.Rd);
                }
            }
            else
            {
                EmitCmpOp(context, OpCodes.Ble_S, scalar: false);
            }
        }
예제 #16
0
        public static void Fmov_Si(ILEmitterCtx context)
        {
            OpCodeSimdFmov64 op = (OpCodeSimdFmov64)context.CurrOp;

            context.EmitLdc_I8(op.Imm);

            EmitScalarSet(context, op.Rd, op.Size + 2);
        }
예제 #17
0
        public static void Xtn_V(ILEmitterCtx context)
        {
            OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;

            if (Optimizations.UseSsse3)
            {
                Type[] typesSve = new Type[] { typeof(long), typeof(long) };

                string nameMov = op.RegisterSize == RegisterSize.Simd128
                    ? nameof(Sse.MoveLowToHigh)
                    : nameof(Sse.MoveHighToLow);

                context.EmitLdvec(op.Rd);
                VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero));

                context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveLowToHigh)));

                context.EmitLdvec(op.Rn);                        // value

                context.EmitLdc_I8(_masksE0_TrnUzpXtn[op.Size]); // mask
                context.Emit(OpCodes.Dup);                       // mask

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve));

                context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), GetTypesSflUpk(0)));

                context.EmitCall(typeof(Sse).GetMethod(nameMov));

                context.EmitStvec(op.Rd);
            }
            else
            {
                int elems = 8 >> op.Size;

                int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0;

                if (part != 0)
                {
                    context.EmitLdvec(op.Rd);
                    context.EmitStvectmp();
                }

                for (int index = 0; index < elems; index++)
                {
                    EmitVectorExtractZx(context, op.Rn, index, op.Size + 1);

                    EmitVectorInsertTmp(context, part + index, op.Size);
                }

                context.EmitLdvectmp();
                context.EmitStvec(op.Rd);

                if (part == 0)
                {
                    EmitVectorZeroUpper(context, op.Rd);
                }
            }
        }
예제 #18
0
        // dst64 = (Int(src64, signed) + roundConst) >> shift;
        private static void EmitShrImm64(ILEmitterCtx context, bool signed, long roundConst, int shift)
        {
            context.EmitLdc_I8(roundConst);
            context.EmitLdc_I4(shift);

            SoftFallback.EmitCall(context, signed
                ? nameof(SoftFallback.SignedShrImm64)
                : nameof(SoftFallback.UnsignedShrImm64));
        }
예제 #19
0
        private static void EmitShrImmOp(ILEmitterCtx context, ShrImmFlags flags)
        {
            OpCodeSimdShImm64 op = (OpCodeSimdShImm64)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) */
                {
                    EmitShrImm64(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 == RegisterSize.Simd64) || scalar)
            {
                EmitVectorZeroUpper(context, op.Rd);
            }
        }
예제 #20
0
        public static void EmitCall(ILEmitterCtx context, long imm)
        {
            if (context.Tier == TranslationTier.Tier0)
            {
                context.EmitStoreContext();

                context.TranslateAhead(imm);

                context.EmitLdc_I8(imm);

                context.Emit(OpCodes.Ret);

                return;
            }

            if (!context.TryOptEmitSubroutineCall())
            {
                context.HasSlowCall = true;

                context.EmitStoreContext();

                context.TranslateAhead(imm);

                context.EmitLdarg(TranslatedSub.StateArgIdx);

                context.EmitLdfld(typeof(CpuThreadState).GetField(nameof(CpuThreadState.CurrentTranslator),
                                                                  BindingFlags.Instance |
                                                                  BindingFlags.NonPublic));

                context.EmitLdarg(TranslatedSub.StateArgIdx);
                context.EmitLdc_I8(imm);
                context.EmitLdc_I4((int)CallType.Call);

                context.EmitPrivateCall(typeof(Translator), nameof(Translator.GetOrTranslateSubroutine));

                context.EmitLdarg(TranslatedSub.StateArgIdx);
                context.EmitLdarg(TranslatedSub.MemoryArgIdx);

                context.EmitCall(typeof(TranslatedSub), nameof(TranslatedSub.Execute));
            }

            EmitContinueOrReturnCheck(context);
        }
예제 #21
0
        private static void EmitExceptionCall(ILEmitterCtx context, string mthdName)
        {
            OpCodeException64 op = (OpCodeException64)context.CurrOp;

            context.EmitStoreState();

            context.EmitLdarg(TranslatedSub.StateArgIdx);

            context.EmitLdc_I8(op.Position);
            context.EmitLdc_I4(op.Id);

            context.EmitPrivateCall(typeof(CpuThreadState), mthdName);

            //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(TranslatedSub.StateArgIdx);

            context.EmitCallPropGet(typeof(CpuThreadState), nameof(CpuThreadState.Running));

            ILLabel lblEnd = new ILLabel();

            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);
            }
        }
예제 #22
0
        public static void EmitVectorInsertTmp(ILEmitterCtx context, int index, int size, long value)
        {
            ThrowIfInvalid(index, size);

            context.EmitLdc_I8(value);
            context.EmitLdvectmp();
            context.EmitLdc_I4(index);
            context.EmitLdc_I4(size);

            VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInsertInt));

            context.EmitStvectmp();
        }
예제 #23
0
        public static void Bl(ILEmitterCtx context)
        {
            OpCodeBImmAl64 op = (OpCodeBImmAl64)context.CurrOp;

            context.EmitLdc_I(op.Position + 4);
            context.EmitStint(CpuThreadState.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);

                ILLabel lblContinue = new ILLabel();

                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);
            }
        }
예제 #24
0
        public static void Und(ILEmitterCtx context)
        {
            OpCode64 op = context.CurrOp;

            context.EmitStoreState();

            context.EmitLdarg(TranslatedSub.StateArgIdx);

            context.EmitLdc_I8(op.Position);
            context.EmitLdc_I4(op.RawOpCode);

            context.EmitPrivateCall(typeof(CpuThreadState), nameof(CpuThreadState.OnUndefined));

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

                context.Emit(OpCodes.Ret);
            }
        }
예제 #25
0
        public static void B(ILEmitterCtx context)
        {
            OpCodeBImmAl64 op = (OpCodeBImmAl64)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);
            }
        }
예제 #26
0
        public static void B(ILEmitterCtx context)
        {
            IOpCode32BImm op = (IOpCode32BImm)context.CurrOp;

            if (context.CurrBlock.Branch != null)
            {
                context.Emit(OpCodes.Br, context.GetLabel(op.Imm));
            }
            else
            {
                context.EmitStoreContext();
                context.EmitLdc_I8(op.Imm);

                context.Emit(OpCodes.Ret);
            }
        }
예제 #27
0
        public static void Fmov_V(ILEmitterCtx context)
        {
            OpCodeSimdImm64 op = (OpCodeSimdImm64)context.CurrOp;

            int elems = op.RegisterSize == RegisterSize.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 == RegisterSize.Simd64)
            {
                EmitVectorZeroUpper(context, op.Rd);
            }
        }
예제 #28
0
        private static void EmitVectorShrImmNarrowOpZx(ILEmitterCtx context, bool round)
        {
            OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp;

            int shift = GetImmShr(op);

            long roundConst = 1L << (shift - 1);

            int elems = 8 >> op.Size;

            int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0;

            if (part != 0)
            {
                context.EmitLdvec(op.Rd);
                context.EmitStvectmp();
            }

            for (int index = 0; index < elems; index++)
            {
                EmitVectorExtractZx(context, op.Rn, index, op.Size + 1);

                if (round)
                {
                    context.EmitLdc_I8(roundConst);

                    context.Emit(OpCodes.Add);
                }

                context.EmitLdc_I4(shift);

                context.Emit(OpCodes.Shr_Un);

                EmitVectorInsertTmp(context, part + index, op.Size);
            }

            context.EmitLdvectmp();
            context.EmitStvec(op.Rd);

            if (part == 0)
            {
                EmitVectorZeroUpper(context, op.Rd);
            }
        }
예제 #29
0
        private static void EmitSimdMemWBack(ILEmitterCtx context, int offset)
        {
            OpCodeMemReg64 op = (OpCodeMemReg64)context.CurrOp;

            context.EmitLdint(op.Rn);

            if (op.Rm != RegisterAlias.Zr)
            {
                context.EmitLdint(op.Rm);
            }
            else
            {
                context.EmitLdc_I8(offset);
            }

            context.Emit(OpCodes.Add);

            context.EmitStint(op.Rn);
        }
예제 #30
0
        private static void EmitCmpOp(ILEmitterCtx context, OpCode ilOp, bool scalar)
        {
            OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;

            int bytes = op.GetBitsCount() >> 3;
            int elems = !scalar ? bytes >> op.Size : 1;

            ulong szMask = ulong.MaxValue >> (64 - (8 << op.Size));

            for (int index = 0; index < elems; index++)
            {
                EmitVectorExtractSx(context, op.Rn, index, op.Size);

                if (op is OpCodeSimdReg64 binOp)
                {
                    EmitVectorExtractSx(context, binOp.Rm, index, op.Size);
                }
                else
                {
                    context.EmitLdc_I8(0L);
                }

                ILLabel lblTrue = new ILLabel();
                ILLabel lblEnd  = new ILLabel();

                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 == RegisterSize.Simd64) || scalar)
            {
                EmitVectorZeroUpper(context, op.Rd);
            }
        }