예제 #1
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);
        }
예제 #2
0
        public static void Bfm(ILEmitterCtx context)
        {
            OpCodeBfm64 op = (OpCodeBfm64)context.CurrOp;

            if (op.Pos < op.Shift)
            {
                //BFI.
                context.EmitLdintzr(op.Rn);

                int shift = op.GetBitsCount() - op.Shift;

                int width = op.Pos + 1;

                long mask = (long)(ulong.MaxValue >> (64 - width));

                context.EmitLdc_I(mask);

                context.Emit(OpCodes.And);

                context.EmitLsl(shift);

                context.EmitLdintzr(op.Rd);

                context.EmitLdc_I(~(mask << shift));

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

                context.EmitStintzr(op.Rd);
            }
            else
            {
                //BFXIL.
                context.EmitLdintzr(op.Rn);

                context.EmitLsr(op.Shift);

                int width = op.Pos - op.Shift + 1;

                long mask = (long)(ulong.MaxValue >> (64 - width));

                context.EmitLdc_I(mask);

                context.Emit(OpCodes.And);

                context.EmitLdintzr(op.Rd);

                context.EmitLdc_I(~mask);

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

                context.EmitStintzr(op.Rd);
            }
        }
예제 #3
0
        private static void EmitCsel(ILEmitterCtx context, CselOperation cselOp)
        {
            OpCodeCsel64 op = (OpCodeCsel64)context.CurrOp;

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

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

            context.EmitLdc_I((op.Position & ~0xfffL) + (op.Imm << 12));
            context.EmitStintzr(op.Rd);
        }
예제 #5
0
        private static void EmitLdr(ILEmitterCtx context, bool signed)
        {
            OpCodeMem64 op = (OpCodeMem64)context.CurrOp;

            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 IOpCodeSimd64)
            {
                context.EmitStvec(op.Rt);
            }
            else
            {
                context.EmitStintzr(op.Rt);
            }

            EmitWBackIfNeeded(context);
        }
예제 #6
0
        public static void Ubfm(ILEmitterCtx context)
        {
            OpCodeBfm64 op = (OpCodeBfm64)context.CurrOp;

            if (op.Pos + 1 == op.GetBitsCount())
            {
                EmitUbfmShift(context);
            }
            else if (op.Pos < op.Shift)
            {
                EmitUbfiz(context);
            }
            else if (op.Pos + 1 == op.Shift)
            {
                EmitBfmLsl(context);
            }
            else if (op.Pos == 7 && op.Shift == 0)
            {
                EmitUbfmCast(context, OpCodes.Conv_U1);
            }
            else if (op.Pos == 15 && op.Shift == 0)
            {
                EmitUbfmCast(context, OpCodes.Conv_U2);
            }
            else
            {
                EmitBfmLoadRn(context);

                context.EmitStintzr(op.Rd);
            }
        }
예제 #7
0
        public static void Adr(ILEmitterCtx context)
        {
            OpCodeAdr64 op = (OpCodeAdr64)context.CurrOp;

            context.EmitLdc_I(op.Position + op.Imm);
            context.EmitStintzr(op.Rd);
        }
예제 #8
0
        public static void Movz(ILEmitterCtx context)
        {
            OpCodeMov64 op = (OpCodeMov64)context.CurrOp;

            context.EmitLdc_I(op.Imm);
            context.EmitStintzr(op.Rd);
        }
예제 #9
0
        public static void Fmov_Ftoi1(ILEmitterCtx context)
        {
            OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;

            EmitVectorExtractZx(context, op.Rn, 1, 3);

            context.EmitStintzr(op.Rd);
        }
예제 #10
0
        public static void Umov_S(ILEmitterCtx context)
        {
            OpCodeSimdIns64 op = (OpCodeSimdIns64)context.CurrOp;

            EmitVectorExtractZx(context, op.Rn, op.DstIndex, op.Size);

            context.EmitStintzr(op.Rd);
        }
예제 #11
0
        public static void Smov_S(ILEmitterCtx context)
        {
            OpCodeSimdIns64 op = (OpCodeSimdIns64)context.CurrOp;

            EmitVectorExtractSx(context, op.Rn, op.DstIndex, op.Size);

            EmitIntZeroUpperIfNeeded(context);

            context.EmitStintzr(op.Rd);
        }
예제 #12
0
        public static void Rev64(ILEmitterCtx context)
        {
            OpCodeAlu64 op = (OpCodeAlu64)context.CurrOp;

            context.EmitLdintzr(op.Rn);

            SoftFallback.EmitCall(context, nameof(SoftFallback.ReverseBytes64));

            context.EmitStintzr(op.Rd);
        }
예제 #13
0
        public static void Fmov_Ftoi1(ILEmitterCtx context)
        {
            OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;

            EmitVectorExtractZx(context, op.Rn, 1, 3);

            EmitIntZeroUpperIfNeeded(context);

            context.EmitStintzr(op.Rd);
        }
예제 #14
0
        private static void EmitBfmLsl(ILEmitterCtx context)
        {
            OpCodeBfm64 op = (OpCodeBfm64)context.CurrOp;

            context.EmitLdintzr(op.Rn);

            context.EmitLsl(op.GetBitsCount() - op.Shift);

            context.EmitStintzr(op.Rd);
        }
예제 #15
0
        private static void EmitSse42Crc32(ILEmitterCtx context, Type tCrc, Type tData)
        {
            OpCodeAluRs64 op = (OpCodeAluRs64)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);
        }
예제 #16
0
        public static void Umulh(ILEmitterCtx context)
        {
            OpCodeMul64 op = (OpCodeMul64)context.CurrOp;

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

            SoftFallback.EmitCall(context, nameof(SoftFallback.UMulHi128));

            context.EmitStintzr(op.Rd);
        }
예제 #17
0
        public static void Cls(ILEmitterCtx context)
        {
            OpCodeAlu64 op = (OpCodeAlu64)context.CurrOp;

            context.EmitLdintzr(op.Rn);

            context.EmitLdc_I4(op.RegisterSize == RegisterSize.Int32 ? 32 : 64);

            SoftFallback.EmitCall(context, nameof(SoftFallback.CountLeadingSigns));

            context.EmitStintzr(op.Rd);
        }
예제 #18
0
        private static void EmitLoad(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);
            }

            if (exclusive)
            {
                EmitMemoryCall(context, nameof(MemoryManager.SetExclusive), op.Rn);
            }

            context.EmitLdint(op.Rn);
            context.EmitSttmp();

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

            EmitReadZxCall(context, op.Size);

            context.EmitStintzr(op.Rt);

            if (pair)
            {
                context.EmitLdarg(TranslatedSub.MemoryArgIdx);
                context.EmitLdtmp();
                context.EmitLdc_I8(1 << op.Size);

                context.Emit(OpCodes.Add);

                EmitReadZxCall(context, op.Size);

                context.EmitStintzr(op.Rt2);
            }
        }
예제 #19
0
        private static void EmitBfmShift(ILEmitterCtx context, bool signed)
        {
            OpCodeBfm64 op = (OpCodeBfm64)context.CurrOp;

            context.EmitLdintzr(op.Rn);
            context.EmitLdc_I4(op.Shift);

            context.Emit(signed
                ? OpCodes.Shr
                : OpCodes.Shr_Un);

            context.EmitStintzr(op.Rd);
        }
예제 #20
0
        public static void EmitAluStore(ILEmitterCtx context, bool setFlags)
        {
            IOpCodeAlu64 op = (IOpCodeAlu64)context.CurrOp;

            if (setFlags || op is IOpCodeAluRs64)
            {
                context.EmitStintzr(op.Rd);
            }
            else
            {
                context.EmitStint(op.Rd);
            }
        }
예제 #21
0
        private static void EmitMul(ILEmitterCtx context, OpCode ilOp)
        {
            OpCodeMul64 op = (OpCodeMul64)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);
        }
예제 #22
0
        public static void Smov_S(ILEmitterCtx context)
        {
            OpCodeSimdIns64 op = (OpCodeSimdIns64)context.CurrOp;

            EmitVectorExtractSx(context, op.Rn, op.DstIndex, op.Size);

            if (op.RegisterSize == RegisterSize.Simd64)
            {
                context.Emit(OpCodes.Conv_U4);
                context.Emit(OpCodes.Conv_U8);
            }

            context.EmitStintzr(op.Rd);
        }
예제 #23
0
        public static void Movk(ILEmitterCtx context)
        {
            OpCodeMov64 op = (OpCodeMov64)context.CurrOp;

            context.EmitLdintzr(op.Rd);
            context.EmitLdc_I(~(0xffffL << op.Pos));

            context.Emit(OpCodes.And);

            context.EmitLdc_I(op.Imm);

            context.Emit(OpCodes.Or);

            context.EmitStintzr(op.Rd);
        }
예제 #24
0
        private static void EmitFallback32_64(ILEmitterCtx context, string name32, string name64)
        {
            OpCodeAlu64 op = (OpCodeAlu64)context.CurrOp;

            context.EmitLdintzr(op.Rn);

            if (op.RegisterSize == RegisterSize.Int32)
            {
                SoftFallback.EmitCall(context, name32);
            }
            else
            {
                SoftFallback.EmitCall(context, name64);
            }

            context.EmitStintzr(op.Rd);
        }
예제 #25
0
        private static void EmitBfmCast(ILEmitterCtx context, OpCode ilOp, bool signed)
        {
            OpCodeBfm64 op = (OpCodeBfm64)context.CurrOp;

            context.EmitLdintzr(op.Rn);

            context.Emit(ilOp);

            if (op.RegisterSize != RegisterSize.Int32)
            {
                context.Emit(signed
                    ? OpCodes.Conv_I8
                    : OpCodes.Conv_U8);
            }

            context.EmitStintzr(op.Rd);
        }
예제 #26
0
        public static void Sbfm(ILEmitterCtx context)
        {
            OpCodeBfm64 op = (OpCodeBfm64)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
            {
                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);
            }
        }
예제 #27
0
        public static void Bfm(ILEmitterCtx context)
        {
            OpCodeBfm64 op = (OpCodeBfm64)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);
        }
예제 #28
0
        public static void Mrs(ILEmitterCtx context)
        {
            OpCodeSystem64 op = (OpCodeSystem64)context.CurrOp;

            context.EmitLdarg(TranslatedSub.StateArgIdx);

            string propName;

            switch (GetPackedId(op))
            {
            case 0b11_011_0000_0000_001: propName = nameof(CpuThreadState.CtrEl0);    break;

            case 0b11_011_0000_0000_111: propName = nameof(CpuThreadState.DczidEl0);  break;

            case 0b11_011_0100_0100_000: propName = nameof(CpuThreadState.Fpcr);      break;

            case 0b11_011_0100_0100_001: propName = nameof(CpuThreadState.Fpsr);      break;

            case 0b11_011_1101_0000_010: propName = nameof(CpuThreadState.TpidrEl0);  break;

            case 0b11_011_1101_0000_011: propName = nameof(CpuThreadState.Tpidr);     break;

            case 0b11_011_1110_0000_000: propName = nameof(CpuThreadState.CntfrqEl0); break;

            case 0b11_011_1110_0000_001: propName = nameof(CpuThreadState.CntpctEl0); break;

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

            context.EmitCallPropGet(typeof(CpuThreadState), propName);

            PropertyInfo propInfo = typeof(CpuThreadState).GetProperty(propName);

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

            context.EmitStintzr(op.Rt);
        }
예제 #29
0
        public static void Ldp(ILEmitterCtx context)
        {
            OpCodeMemPair64 op = (OpCodeMemPair64)context.CurrOp;

            void EmitReadAndStore(int rt)
            {
                if (op.Extend64)
                {
                    EmitReadSx64Call(context, op.Size);
                }
                else
                {
                    EmitReadZxCall(context, op.Size);
                }

                if (op is IOpCodeSimd64)
                {
                    context.EmitStvec(rt);
                }
                else
                {
                    context.EmitStintzr(rt);
                }
            }

            context.EmitLdarg(TranslatedSub.MemoryArgIdx);

            EmitLoadAddress(context);

            EmitReadAndStore(op.Rt);

            context.EmitLdarg(TranslatedSub.MemoryArgIdx);
            context.EmitLdtmp();
            context.EmitLdc_I8(1 << op.Size);

            context.Emit(OpCodes.Add);

            EmitReadAndStore(op.Rt2);

            EmitWBackIfNeeded(context);
        }
예제 #30
0
        public static void Clz(ILEmitterCtx context)
        {
            OpCodeAlu64 op = (OpCodeAlu64)context.CurrOp;

            context.EmitLdintzr(op.Rn);

            if (Lzcnt.IsSupported)
            {
                Type tValue = op.RegisterSize == RegisterSize.Int32 ? typeof(uint) : typeof(ulong);

                context.EmitCall(typeof(Lzcnt).GetMethod(nameof(Lzcnt.LeadingZeroCount), new Type[] { tValue }));
            }
            else
            {
                context.EmitLdc_I4(op.RegisterSize == RegisterSize.Int32 ? 32 : 64);

                SoftFallback.EmitCall(context, nameof(SoftFallback.CountLeadingZeros));
            }

            context.EmitStintzr(op.Rd);
        }