Beispiel #1
0
        private static void Remainder(Context context, MethodCompiler methodCompiler)
        {
            var result   = context.Result;
            var dividend = context.Operand1;
            var divisor  = context.Operand2;

            if (result.IsR8)
            {
                var xmm1 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R8);
                var xmm2 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R8);
                var xmm3 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R8);

                context.SetInstruction(X86.Divsd, xmm1, dividend, divisor);
                context.AppendInstruction(X86.Roundsd, xmm2, xmm1, methodCompiler.CreateConstant((byte)0x3));
                context.AppendInstruction(X86.Mulsd, xmm3, divisor, xmm2);
                context.AppendInstruction(X86.Subsd, result, dividend, xmm3);
            }
            else
            {
                var xmm1 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R4);
                var xmm2 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R4);
                var xmm3 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R4);

                context.SetInstruction(X86.Divss, xmm1, dividend, divisor);
                context.AppendInstruction(X86.Roundss, xmm2, xmm1, methodCompiler.CreateConstant((byte)0x3));
                context.AppendInstruction(X86.Mulss, xmm3, divisor, xmm2);
                context.AppendInstruction(X86.Subss, result, dividend, xmm3);
            }
        }
Beispiel #2
0
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler)
        {
            Operand v0 = context.Operand1;

            Operand esp = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ESP);

            context.SetInstruction(X86.Mov32, esp, v0);
            context.AppendInstruction(X86.Popad);
            context.AppendInstruction(X86.AddConst32, esp, esp, methodCompiler.CreateConstant(8));
            context.AppendInstruction(X86.Sti);
            context.AppendInstruction(X86.IRetd);

            // future - common code (refactor opportunity)
            context.GotoNext();

            // Remove all remaining instructions in block and clear next block list
            while (!context.IsBlockEndInstruction)
            {
                if (!context.IsEmpty)
                {
                    context.SetInstruction(X86.Nop);
                }
                context.GotoNext();
            }

            var nextBlocks = context.Block.NextBlocks;

            foreach (var next in nextBlocks)
            {
                next.PreviousBlocks.Remove(context.Block);
            }

            nextBlocks.Clear();
        }
Beispiel #3
0
        private static void InterruptReturn(Context context, MethodCompiler methodCompiler)
        {
            Operand v0 = context.Operand1;

            Operand esp = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I8, GeneralPurposeRegister.ESP);

            context.SetInstruction(X64.Mov64, esp, v0);
            context.AppendInstruction(X64.Popad);
            context.AppendInstruction(X64.Add64, esp, esp, methodCompiler.CreateConstant(8));
            context.AppendInstruction(X64.Sti);
            context.AppendInstruction(X64.IRetd);

            // future - common code (refactor opportunity)
            context.GotoNext();

            // Remove all remaining instructions in block and clear next block list
            while (!context.IsBlockEndInstruction)
            {
                if (!context.IsEmpty)
                {
                    context.Empty();
                }
                context.GotoNext();
            }

            var nextBlocks = context.Block.NextBlocks;

            foreach (var next in nextBlocks)
            {
                next.PreviousBlocks.Remove(context.Block);
            }

            nextBlocks.Clear();
        }
Beispiel #4
0
        private static void SizeOf(Context context, MethodCompiler methodCompiler)
        {
            //var size = type.IsPointer ? methodCompiler.Architecture.NativePointerSize : methodCompiler.TypeLayout.GetTypeSize(type);

            var type = context.InvokeMethod.GenericArguments[0];
            var size = methodCompiler.TypeLayout.GetTypeSize(type);
            var move = methodCompiler.Architecture.Is32BitPlatform ? (BaseInstruction)IRInstruction.Move32 : IRInstruction.Move64;

            context.SetInstruction(move, context.Result, methodCompiler.CreateConstant(size));
        }
Beispiel #5
0
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler)
        {
            var dest = context.Operand1;

            var v0       = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.Void, SSE2Register.XMM0);
            var offset16 = methodCompiler.CreateConstant(16);

            context.SetInstruction(X86.PXor, v0, v0, v0);
            context.AppendInstruction(X86.MovupsStore, dest, methodCompiler.ConstantZero, v0);
            context.AppendInstruction(X86.MovupsStore, dest, offset16, v0);
        }
Beispiel #6
0
        private static void Memclr256(Context context, MethodCompiler methodCompiler)
        {
            var dest = context.Operand1;

            var v0       = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.Void, SSE2Register.XMM0);
            var offset16 = methodCompiler.CreateConstant(16);

            context.SetInstruction(X86.PXor, v0, v0, v0);
            context.AppendInstruction(X86.MovupsStore, dest, methodCompiler.ConstantZero32, v0);
            context.AppendInstruction(X86.MovupsStore, dest, offset16, v0);
        }
Beispiel #7
0
        /// <summary>
        /// Create platform compound move.
        /// </summary>
        /// <param name="methodCompiler">The compiler.</param>
        /// <param name="context">The context.</param>
        /// <param name="destinationBase">The destination base.</param>
        /// <param name="destination">The destination.</param>
        /// <param name="sourceBase">The source base.</param>
        /// <param name="source">The source.</param>
        /// <param name="size">The size.</param>
        public override void InsertCompoundCopy(MethodCompiler methodCompiler, Context context, Operand destinationBase, Operand destination, Operand sourceBase, Operand source, int size)
        {
            const int LargeAlignment       = 16;
            int       alignedSize          = size - (size % NativeAlignment);
            int       largeAlignedTypeSize = size - (size % LargeAlignment);

            Debug.Assert(size > 0);

            var srcReg = methodCompiler.CreateVirtualRegister(destinationBase.Type.TypeSystem.BuiltIn.I4);
            var dstReg = methodCompiler.CreateVirtualRegister(destinationBase.Type.TypeSystem.BuiltIn.I4);

            context.AppendInstruction(IRInstruction.UnstableObjectTracking);

            context.AppendInstruction(X86.Lea32, srcReg, sourceBase, source);
            context.AppendInstruction(X86.Lea32, dstReg, destinationBase, destination);

            var tmp      = methodCompiler.CreateVirtualRegister(destinationBase.Type.TypeSystem.BuiltIn.I4);
            var tmpLarge = methodCompiler.CreateVirtualRegister(destinationBase.Type.TypeSystem.BuiltIn.R8);

            for (int i = 0; i < largeAlignedTypeSize; i += LargeAlignment)
            {
                // Large aligned moves allow 128bits to be copied at a time
                var index = methodCompiler.CreateConstant((int)i);
                context.AppendInstruction(X86.MovupsLoad, tmpLarge, srcReg, index);
                context.AppendInstruction(X86.MovupsStore, null, dstReg, index, tmpLarge);
            }
            for (int i = largeAlignedTypeSize; i < alignedSize; i += 4)
            {
                var index = methodCompiler.CreateConstant(i);
                context.AppendInstruction(X86.MovLoad32, tmp, srcReg, index);
                context.AppendInstruction(X86.MovStore32, null, dstReg, index, tmp);
            }
            for (int i = alignedSize; i < size; i++)
            {
                var index = methodCompiler.CreateConstant(i);
                context.AppendInstruction(X86.MovLoad8, tmp, srcReg, index);
                context.AppendInstruction(X86.MovStore8, null, dstReg, index, tmp);
            }

            context.AppendInstruction(IRInstruction.StableObjectTracking);
        }
Beispiel #8
0
        private static void Memcpy256(Context context, MethodCompiler methodCompiler)
        {
            var dest = context.Operand1;
            var src  = context.Operand2;

            var v0       = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.Void);
            var v1       = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.Void);
            var offset16 = methodCompiler.CreateConstant(16);

            context.SetInstruction(X86.MovupsLoad, v0, dest, methodCompiler.ConstantZero);
            context.AppendInstruction(X86.MovupsLoad, v1, dest, offset16);
            context.AppendInstruction(X86.MovupsStore, null, dest, methodCompiler.ConstantZero, v0);
            context.AppendInstruction(X86.MovupsStore, null, dest, offset16, v1);
        }
Beispiel #9
0
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler)
        {
            var dest = context.Operand1;
            var src  = context.Operand2;

            var v0       = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.Void);
            var v1       = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.Void);
            var offset16 = methodCompiler.CreateConstant(16);

            context.SetInstruction(X86.MovupsLoad, v0, dest, methodCompiler.ConstantZero);
            context.AppendInstruction(X86.MovupsLoad, v1, dest, offset16);
            context.AppendInstruction(X86.MovupsStore, null, dest, methodCompiler.ConstantZero, v0);
            context.AppendInstruction(X86.MovupsStore, null, dest, offset16, v1);
        }
Beispiel #10
0
        public static void OrderOperands(Context context, MethodCompiler methodCompiler)
        {
            if (context.Operand1.IsResolvedConstant && context.Operand2.IsResolvedConstant)
            {
                context.Operand1 = methodCompiler.CreateConstant(context.Operand1.ConstantUnsigned64 + context.Operand2.ConstantUnsigned64);
                context.Operand2 = methodCompiler.ConstantZero;
            }

            if (context.Operand1.IsConstant && !context.Operand2.IsConstant)
            {
                var operand1 = context.Operand1;
                var operand2 = context.Operand2;

                context.Operand2 = operand1;
                context.Operand1 = operand2;
            }
        }
Beispiel #11
0
        public static void OrderLoadOperands(InstructionNode node, MethodCompiler methodCompiler)
        {
            if (node.Operand1.IsResolvedConstant && node.Operand2.IsResolvedConstant)
            {
                node.Operand1 = methodCompiler.CreateConstant(node.Operand1.ConstantUnsignedLongInteger + node.Operand2.ConstantUnsignedLongInteger);
                node.Operand2 = methodCompiler.ConstantZero;
            }

            if (node.Operand1.IsConstant && !node.Operand2.IsConstant)
            {
                var operand1 = node.Operand1;
                var operand2 = node.Operand2;

                node.Operand2 = operand1;
                node.Operand1 = operand2;
            }
        }
Beispiel #12
0
        public static void Unsafe_SizeOf(Context context, MethodCompiler methodCompiler)
        {
            var type     = methodCompiler.Method.GenericArguments[0];
            var size     = methodCompiler.TypeLayout.GetTypeSize(type);
            var opReturn = methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType);

            // Move constant into return operand
            var move = methodCompiler.Is32BitPlatform ? (BaseInstruction)IRInstruction.Move32 : IRInstruction.Move64;

            context.AppendInstruction(move, opReturn, methodCompiler.CreateConstant(size));

            // Set return
            var setReturn = BaseMethodCompilerStage.GetSetReturnInstruction(opReturn.Type, methodCompiler.Is32BitPlatform);

            context.AppendInstruction(setReturn, null, opReturn);

            context.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock);
        }
Beispiel #13
0
        public static void RuntimeHelpers_IsReferenceOrContainsReferences(Context context, MethodCompiler methodCompiler)
        {
            var type     = methodCompiler.Method.GenericArguments[0];
            var opReturn = methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType);

            // FIXME: we're only checking if the current type is a reference type, we aren't checking if it contains references
            var isReferenceOrContainsReferences = type.IsReferenceType;

            // Move constant into return operand
            var move = methodCompiler.Is32BitPlatform ? (BaseInstruction)IRInstruction.Move32 : IRInstruction.Move64;

            context.AppendInstruction(move, opReturn, methodCompiler.CreateConstant(isReferenceOrContainsReferences ? 1 : 0));

            // Set return
            var setReturn = BaseMethodCompilerStage.GetSetReturnInstruction(opReturn.Type, methodCompiler.Is32BitPlatform);

            context.AppendInstruction(setReturn, null, opReturn);

            context.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock);
        }
Beispiel #14
0
        private static void FrameCallRetR8(Context context, MethodCompiler methodCompiler)
        {
            var result        = context.Result;
            var methodAddress = context.Operand1;

            var eax  = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I8, GeneralPurposeRegister.EAX);
            var edx  = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I8, GeneralPurposeRegister.EDX);
            var xmm0 = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I8, SSE2Register.XMM0);

            methodCompiler.SplitLongOperand(result, out Operand op0L, out Operand op0H);

            context.SetInstruction(X64.Call, null, methodAddress);
            context.AppendInstruction(IRInstruction.Gen, xmm0);

            //context.AppendInstruction(X64.Movdi64ss, eax, xmm0);        // FIXME: X64
            context.AppendInstruction(X64.Pextrd64, edx, xmm0, methodCompiler.CreateConstant((byte)1));

            context.AppendInstruction(X64.Mov64, op0L, eax);
            context.AppendInstruction(X64.Mov64, op0H, edx);
        }
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler)
        {
            var result        = context.Result;
            var methodAddress = context.Operand1;
            var newESP        = context.Operand2;

            var eax  = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX);
            var edx  = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EDX);
            var mmx1 = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, SSE2Register.XMM0);

            methodCompiler.SplitLongOperand(result, out Operand op0L, out Operand op0H);

            context.SetInstruction(X86.CallReg, null, methodAddress);
            context.AppendInstruction(IRInstruction.Gen, mmx1);

            context.AppendInstruction(X86.Movd, eax, mmx1);
            context.AppendInstruction(X86.Pextrd, edx, mmx1, methodCompiler.CreateConstant((byte)1));

            context.AppendInstruction(X86.Mov32, op0L, eax);
            context.AppendInstruction(X86.Mov32, op0H, edx);
        }
Beispiel #16
0
        private static void FrameCallRetR8(Context context, MethodCompiler methodCompiler)
        {
            var result        = context.Result;
            var methodAddress = context.Operand1;
            var newESP        = context.Operand2;

            var eax  = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX);
            var edx  = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EDX);
            var mmx1 = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, SSE2Register.XMM0);

            methodCompiler.SplitLongOperand(result, out Operand op0L, out Operand op0H);

            context.SetInstruction(X86.Call, null, methodAddress);
            context.AppendInstruction(IRInstruction.Gen, mmx1);

            context.AppendInstruction(X86.Movdi32ss, eax, mmx1);                // CHECK
            context.AppendInstruction(X86.Pextrd32, edx, mmx1, methodCompiler.CreateConstant((byte)1));

            context.AppendInstruction(X86.Mov32, op0L, eax);
            context.AppendInstruction(X86.Mov32, op0H, edx);
        }
Beispiel #17
0
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler)
        {
            //Helper.FoldOperand1ToConstant(context);

            var constantx10 = methodCompiler.CreateConstant(0x10);

            Operand eax = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX);
            Operand ds  = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.DS);
            Operand es  = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.ES);
            Operand fs  = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.FS);
            Operand gs  = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.GS);
            Operand ss  = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.SS);

            context.SetInstruction(X86.Lgdt, null, context.Operand1);
            context.AppendInstruction(X86.MovConst32, eax, constantx10);
            context.AppendInstruction(X86.MovStoreSeg32, ds, eax);
            context.AppendInstruction(X86.MovStoreSeg32, es, eax);
            context.AppendInstruction(X86.MovStoreSeg32, fs, eax);
            context.AppendInstruction(X86.MovStoreSeg32, gs, eax);
            context.AppendInstruction(X86.MovStoreSeg32, ss, eax);
            context.AppendInstruction(X86.JmpFar);
        }
Beispiel #18
0
        private static void Lgdt(Context context, MethodCompiler methodCompiler)
        {
            //Helper.FoldOperand1ToConstant(context);

            var constantx10 = methodCompiler.CreateConstant(0x10);

            var eax = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX);

            var ds = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.DS);
            var es = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.ES);
            var fs = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.FS);
            var gs = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.GS);
            var ss = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.SS);

            context.SetInstruction(X86.Lgdt, null, context.Operand1);
            context.AppendInstruction(X86.Mov32, eax, constantx10);
            context.AppendInstruction(X86.MovStoreSeg32, ds, eax);
            context.AppendInstruction(X86.MovStoreSeg32, es, eax);
            context.AppendInstruction(X86.MovStoreSeg32, fs, eax);
            context.AppendInstruction(X86.MovStoreSeg32, gs, eax);
            context.AppendInstruction(X86.MovStoreSeg32, ss, eax);
            context.AppendInstruction(X86.JmpFar);
        }
Beispiel #19
0
 private static void Roundsd2Positive(Context context, MethodCompiler methodCompiler)
 {
     context.SetInstruction(X86.Roundsd, context.Result, context.Operand1, methodCompiler.CreateConstant((byte)2));
 }
Beispiel #20
0
        private static void GetDelegateTargetAddress(Context context, MethodCompiler methodCompiler)
        {
            var load = methodCompiler.Architecture.Is32BitPlatform ? (BaseInstruction)IRInstruction.LoadInt32 : IRInstruction.LoadInt64;

            context.SetInstruction(load, context.Result, context.Operand1, methodCompiler.CreateConstant(3 * methodCompiler.Architecture.NativePointerSize));
        }
 private static void Roundss2Negative(Context context, MethodCompiler methodCompiler)
 {
     context.SetInstruction(X64.Roundss, context.Result, context.Operand1, methodCompiler.CreateConstant((byte)1));
 }
Beispiel #22
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The method compiler.</param>
        void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler)
        {
            var load = methodCompiler.Architecture.Is32BitPlatform ? (BaseInstruction)IRInstruction.LoadInt32 : IRInstruction.LoadInt64;

            context.SetInstruction(load, context.Result, context.Operand1, methodCompiler.CreateConstant(2 * methodCompiler.Architecture.NativePointerSize));
        }