Ejemplo n.º 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);
            }
        }
Ejemplo n.º 2
0
        private static void EmitLoadAddress(AILEmitterCtx Context)
        {
            switch (Context.CurrOp)
            {
            case AOpCodeMemImm Op:
                Context.EmitLdint(Op.Rn);

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

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

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

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

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

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

            Context.EmitSttmp();
        }
Ejemplo n.º 3
0
        private static void EmitStore(AILEmitterCtx Context, AccessType AccType, bool Pair)
        {
            AOpCodeMemEx Op = (AOpCodeMemEx)Context.CurrOp;

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

            if (Ordered)
            {
                EmitBarrier(Context);
            }

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

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

                Context.Emit(OpCodes.Brtrue_S, LblEx);

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

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

            Context.MarkLabel(LblEx);

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

            EmitWriteCall(Context, Op.Size);

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

                Context.Emit(OpCodes.Add);

                Context.EmitLdintzr(Op.Rt2);

                EmitWriteCall(Context, Op.Size);
            }

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

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

            Context.MarkLabel(LblEnd);
        }
Ejemplo n.º 4
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);
            }
        }
Ejemplo n.º 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);
            }
        }
Ejemplo n.º 6
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;
            }
            }
        }
Ejemplo n.º 7
0
        public static void Ret(AILEmitterCtx Context)
        {
            Context.EmitStoreState();
            Context.EmitLdint(AThreadState.LRIndex);

            Context.Emit(OpCodes.Ret);
        }
Ejemplo n.º 8
0
        private static void EmitSimdMemWBack(AILEmitterCtx Context, int Offset)
        {
            AOpCodeMemReg Op = (AOpCodeMemReg)Context.CurrOp;

            Context.EmitLdint(Op.Rn);

            if (Op.Rm != ARegisters.ZRIndex)
            {
                Context.EmitLdint(Op.Rm);
            }
            else
            {
                Context.EmitLdc_I8(Offset);
            }

            Context.Emit(OpCodes.Add);

            Context.EmitStint(Op.Rn);
        }
Ejemplo n.º 9
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);
        }
Ejemplo n.º 10
0
        public static void EmitDataLoadRn(AILEmitterCtx Context)
        {
            IAOpCodeAlu Op = (IAOpCodeAlu)Context.CurrOp;

            if (Op.DataOp == ADataOp.Logical || Op is IAOpCodeAluRs)
            {
                Context.EmitLdintzr(Op.Rn);
            }
            else
            {
                Context.EmitLdint(Op.Rn);
            }
        }
Ejemplo n.º 11
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);
        }
Ejemplo n.º 12
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);
            }
        }
Ejemplo n.º 13
0
        private static void EmitSimdMultLdSt(AILEmitterCtx Context, bool IsLoad)
        {
            AOpCodeSimdMemMult Op = (AOpCodeSimdMemMult)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.EmitLdvec(Rtt);
                            Context.EmitLdc_I4(Elem);
                            Context.EmitLdc_I4(Op.Size);
                            Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
                            Context.EmitLdint(Op.Rn);
                            Context.EmitLdc_I8(Offset);

                            Context.Emit(OpCodes.Add);

                            EmitReadZxCall(Context, Op.Size);

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

                            Context.EmitStvec(Rtt);

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

                            Context.EmitLdvec(Rtt);
                            Context.EmitLdc_I4(Elem);
                            Context.EmitLdc_I4(Op.Size);

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

                            EmitWriteCall(Context, Op.Size);
                        }

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

            if (Op.WBack)
            {
                Context.EmitLdint(Op.Rn);

                if (Op.Rm != ARegisters.ZRIndex)
                {
                    Context.EmitLdint(Op.Rm);
                }
                else
                {
                    Context.EmitLdc_I8(Offset);
                }

                Context.Emit(OpCodes.Add);

                Context.EmitStint(Op.Rn);
            }
        }