Beispiel #1
0
        private void LoadParameterInteger(InstructionNode node)
        {
            Debug.Assert(!node.Result.IsR4);
            Debug.Assert(!node.Result.IsR8);

            // TODO: Managed 64bit pointers

            if (!node.Result.Is64BitInteger)
            {
                return;
            }

            var result   = node.Result;
            var operand1 = node.Operand1;

            MethodCompiler.SplitLongOperand(operand1, out Operand op0Low, out Operand op0High);

            var resultLow  = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
            var resultHigh = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);

            var context = new Context(node);

            context.SetInstruction(IRInstruction.LoadParameterInteger, InstructionSize.Size32, resultLow, op0Low);
            context.AppendInstruction(IRInstruction.LoadParameterInteger, InstructionSize.Size32, resultHigh, op0High);
            context.AppendInstruction(IRInstruction.To64, result, resultLow, resultHigh);
        }
        private void Add64v2(Context context)
        {
            Debug.Assert(context.Result.Is64BitInteger);

            var result   = context.Result;
            var operand1 = context.Operand1;
            var operand2 = context.Operand2;

            var resultLow   = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
            var resultHigh  = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
            var resultCarry = AllocateVirtualRegister(TypeSystem.BuiltIn.Boolean);

            var v1 = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
            var v2 = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
            var v3 = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
            var v4 = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);

            MethodCompiler.SplitLongOperand(operand1, out Operand op1Low, out Operand op1High);
            MethodCompiler.SplitLongOperand(operand2, out Operand op2Low, out Operand op2High);

            context.SetInstruction(IRInstruction.GetLow64, v1, op1Low);
            context.AppendInstruction(IRInstruction.GetLow64, v2, op2Low);
            context.AppendInstruction2(IRInstruction.AddCarryOut32, resultLow, resultCarry, v1, v2);
            context.AppendInstruction(IRInstruction.GetHigh64, v3, op1High);
            context.AppendInstruction(IRInstruction.GetHigh64, v4, op2High);
            context.AppendInstruction(IRInstruction.AddCarryIn32, resultHigh, v3, v4, resultCarry);
            context.AppendInstruction(IRInstruction.To64, result, resultLow, resultHigh);
        }
Beispiel #3
0
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler)
        {
            Operand n       = context.Operand1;
            Operand d       = context.Operand2;
            Operand result  = context.Result;
            Operand result2 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.U4);

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

            context.SetInstruction2(X86.Div32, result2, result, op0H, op0L, d);
        }
Beispiel #4
0
        private static void Div(Context context, MethodCompiler methodCompiler)
        {
            Operand n       = context.Operand1;
            Operand d       = context.Operand2;
            Operand result  = context.Result;
            Operand result2 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.U4);

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

            context.SetInstruction2(X86.Div32, result2, result, op0H, op0L, d);
        }
Beispiel #5
0
        private static void RdMSR(Context context, MethodCompiler methodCompiler)
        {
            var result   = context.Result;
            var operand1 = context.Operand1;

            methodCompiler.SplitLongOperand(result, out Operand resultLow, out Operand resultHigh);

            var EAX = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I8, GeneralPurposeRegister.EAX);
            var EDX = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I8, GeneralPurposeRegister.EDX);
            var ECX = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I8, GeneralPurposeRegister.ECX);

            context.SetInstruction(X64.Mov64, ECX, operand1);
            context.AppendInstruction2(X64.RdMSR, EAX, EDX, ECX);
            context.AppendInstruction(X64.Mov64, resultLow, EAX);
            context.AppendInstruction(X64.Mov64, resultHigh, EDX);
        }
Beispiel #6
0
        private static void FrameCallRetU8(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);

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

            context.SetInstruction(X64.Call, null, methodAddress);
            context.AppendInstruction(IRInstruction.Gen, eax);
            context.AppendInstruction(IRInstruction.Gen, edx);
            context.AppendInstruction(X64.Mov64, op0L, eax);
            context.AppendInstruction(X64.Mov64, op0H, edx);
        }
        private void LoadParamZeroExtend8x64(Context context)
        {
            Debug.Assert(!context.Result.IsR4);
            Debug.Assert(!context.Result.IsR8);
            Debug.Assert(context.Result.Is64BitInteger);

            var result   = context.Result;
            var operand1 = context.Operand1;

            MethodCompiler.SplitLongOperand(operand1, out Operand op0Low, out Operand _);

            var resultLow = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);

            context.SetInstruction(IRInstruction.LoadParamZeroExtend8x32, resultLow, op0Low);
            context.AppendInstruction(IRInstruction.To64, result, resultLow, ConstantZero);
        }
        private void StoreParam64(Context context)
        {
            var operand1 = context.Operand1;
            var operand2 = context.Operand2;

            var op0Low  = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
            var op0High = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);

            MethodCompiler.SplitLongOperand(operand1, out Operand op1Low, out Operand op1High);
            MethodCompiler.SplitLongOperand(operand2, out Operand _, out Operand _);

            SetGetLow64(context, op0Low, operand2);
            AppendGetHigh64(context, op0High, operand2);
            context.AppendInstruction(IRInstruction.StoreParam32, null, op1Low, op0Low);
            context.AppendInstruction(IRInstruction.StoreParam32, null, op1High, op0High);
        }
        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);

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

            context.SetInstruction(X86.CallReg, null, methodAddress);
            context.AppendInstruction(IRInstruction.Gen, eax);
            context.AppendInstruction(IRInstruction.Gen, edx);
            context.AppendInstruction(X86.Mov32, op0L, eax);
            context.AppendInstruction(X86.Mov32, op0H, edx);
        }
Beispiel #10
0
        private void StoreParamInt64(Context context)
        {
            var result   = context.Result;
            var operand1 = context.Operand1;
            var operand2 = context.Operand2;

            var op0Low  = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
            var op0High = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);

            MethodCompiler.SplitLongOperand(context.Operand1, out Operand op1Low, out Operand op1High);
            MethodCompiler.SplitLongOperand(context.Operand2, out Operand op2Low, out Operand op2High);

            context.SetInstruction(IRInstruction.GetLow64, op0Low, operand2);
            context.AppendInstruction(IRInstruction.GetHigh64, op0High, operand2);
            context.AppendInstruction(IRInstruction.StoreParamInt32, null, op1Low, op0Low);
            context.AppendInstruction(IRInstruction.StoreParamInt32, null, op1High, op0High);
        }
        private void LoadParamSignExtend32x64(Context context)
        {
            Debug.Assert(!context.Result.IsR4);
            Debug.Assert(!context.Result.IsR8);
            Debug.Assert(context.Result.Is64BitInteger);

            var result   = context.Result;
            var operand1 = context.Operand1;

            MethodCompiler.SplitLongOperand(operand1, out Operand op0Low, out Operand _);

            var resultLow  = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
            var resultHigh = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);

            context.SetInstruction(IRInstruction.LoadParam32, resultLow, op0Low);
            context.AppendInstruction(IRInstruction.ArithShiftRight32, resultHigh, resultLow, CreateConstant((byte)31));
            context.AppendInstruction(IRInstruction.To64, result, resultLow, resultHigh);
        }
Beispiel #12
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);
        }
Beispiel #13
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 #14
0
        private Operand Map(Operand operand, Dictionary <Operand, Operand> map, InstructionNode callSiteNode)
        {
            if (operand == null)
            {
                return(null);
            }

            if (map.TryGetValue(operand, out Operand mappedOperand))
            {
                return(mappedOperand);
            }

            if (operand.IsSymbol)
            {
                if (operand.IsString)
                {
                    // FUTURE: explore operand re-use
                    mappedOperand = Operand.CreateStringSymbol(operand.Name, operand.StringData, operand.Type.TypeSystem);
                }
                else if (operand.Method != null)
                {
                    // FUTURE: explore operand re-use
                    mappedOperand = Operand.CreateSymbolFromMethod(operand.Method, operand.Type.TypeSystem);
                }
                else if (operand.Name != null)
                {
                    // FUTURE: explore operand re-use
                    mappedOperand = Operand.CreateSymbol(operand.Type, operand.Name);
                }
            }
            else if (operand.IsParameter)
            {
                mappedOperand = callSiteNode.GetOperand(operand.Index + 1);
            }
            else if (operand.IsStackLocal)
            {
                mappedOperand = MethodCompiler.AddStackLocal(operand.Type, operand.IsPinned);
            }
            else if (operand.IsVirtualRegister)
            {
                mappedOperand = AllocateVirtualRegister(operand.Type);
            }
            else if (operand.IsStaticField)
            {
                // FUTURE: explore operand re-use
                mappedOperand = Operand.CreateStaticField(operand.Field, TypeSystem);
            }
            else if (operand.IsCPURegister)
            {
                mappedOperand = operand;
            }
            else if (operand.IsConstant)
            {
                mappedOperand = operand;
            }

            Debug.Assert(mappedOperand != null);

            if (operand.HasLongParent)
            {
                MethodCompiler.SplitLongOperand(mappedOperand);

                if (operand.IsLow)
                {
                    mappedOperand = mappedOperand.Low;
                }
                else if (operand.IsHigh)
                {
                    mappedOperand = mappedOperand.High;
                }
            }

            map.Add(operand, mappedOperand);

            return(mappedOperand);
        }
Beispiel #15
0
 public void SplitLongOperand(Operand operand, out Operand operandLow, out Operand operandHigh)
 {
     MethodCompiler.SplitLongOperand(operand, out operandLow, out operandHigh);
 }
Beispiel #16
0
        private static void WrMSR(Context context, MethodCompiler methodCompiler)
        {
            methodCompiler.SplitLongOperand(context.Operand2, out Operand resultLow, out Operand resultHigh);

            context.SetInstruction(X86.WrMSR, null, context.Operand1, resultLow, resultHigh);
        }