Esempio n. 1
0
        /// <summary>
        /// Requests the calling convention to create an appropriate move instruction to populate the return
        /// value of a method.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="operand">The operand, that's holding the return value.</param>
        void ICallingConvention.MoveReturnValue(Context ctx, Operand operand)
        {
            int size, alignment;

            _architecture.GetTypeRequirements(operand.Type, out size, out alignment);

            // FIXME: Do not issue a move, if the operand is already the destination register
            if (4 == size || 2 == size || 1 == size)
            {
                ctx.SetInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(operand.Type, GeneralPurposeRegister.EAX), operand);
                return;
            }
            if (8 == size && (operand.Type.Type == CilElementType.R4 || operand.Type.Type == CilElementType.R8))
            {
                ctx.SetInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(operand.Type, SSE2Register.XMM0), operand);
                return;
            }
            if (8 == size && (operand.Type.Type == CilElementType.I8 || operand.Type.Type == CilElementType.U8))
            {
                SigType I4 = new SigType(CilElementType.I4);
                SigType U4 = new SigType(CilElementType.U4);

                Operand opL, opH;
                LongOperandTransformationStage.SplitLongOperand(operand, out opL, out opH);

                // Like Win32: EDX:EAX
                ctx.SetInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(U4, GeneralPurposeRegister.EAX), opL);
                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(I4, GeneralPurposeRegister.EDX), opH);

                return;
            }
            throw new NotSupportedException();
        }
Esempio n. 2
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            Operand n       = context.Operand1;
            Operand d       = context.Operand2;
            Operand result  = context.Result;
            Operand result2 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.U4);

            Operand op0L, op0H;

            LongOperandTransformationStage.SplitLongOperand(methodCompiler, n, out op0L, out op0H, null);

            context.SetInstruction2(X86.Div, result2, result, op0H, op0L, d);
        }
Esempio n. 3
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The method compiler.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            Operand result        = context.Result;
            Operand methodAddress = context.Operand1;
            Operand newESP        = context.Operand2;

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

            Operand op0L, op0H;

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

            context.SetInstruction(X86.Call, null, methodAddress);
            context.AppendInstruction(IRInstruction.Gen, eax);
            context.AppendInstruction(IRInstruction.Gen, edx);
            context.AppendInstruction(X86.Mov, op0L, eax);
            context.AppendInstruction(X86.Mov, op0H, edx);
        }
Esempio n. 4
0
        /// <summary>
        /// Requests the calling convention to create an appropriate move instruction to populate the return
        /// value of a method.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="operand">The operand, that's holding the return value.</param>
        void ICallingConvention.MoveReturnValue(Context ctx, Operand operand)
        {
            int size, alignment;

            architecture.GetTypeRequirements(operand.Type, out size, out alignment);

            // FIXME: Do not issue a move, if the operand is already the destination register
            if (4 == size || 2 == size || 1 == size)
            {
                ctx.SetInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(operand.Type, GeneralPurposeRegister.EAX), operand);
                return;
            }
            else if (8 == size && (operand.Type.Type == CilElementType.R4 || operand.Type.Type == CilElementType.R8))
            {
                if (!(operand is MemoryOperand))
                {
                    // Move the operand to memory by prepending an instruction
                }

                // BUG: Return values are in FP0, not XMM#0
                ctx.SetInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(operand.Type, SSE2Register.XMM0), operand);
                return;
            }
            else if (8 == size && (operand.Type.Type == CilElementType.I8 || operand.Type.Type == CilElementType.U8))
            {
                SigType HighType = (operand.Type.Type == CilElementType.I8) ? new SigType(CilElementType.I4) : new SigType(CilElementType.U4);
                SigType U4       = new SigType(CilElementType.U4);

                Operand opL, opH;
                LongOperandTransformationStage.SplitLongOperand(operand, out opL, out opH);

                // Like Win32: EDX:EAX
                ctx.SetInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(U4, GeneralPurposeRegister.EAX), opL);
                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(HighType, GeneralPurposeRegister.EDX), opH);

                return;
            }
            else
            {
                throw new NotSupportedException();
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Moves the return value to 64 bit.
        /// </summary>
        /// <param name="resultOperand">The result operand.</param>
        /// <param name="ctx">The context.</param>
        private static void MoveReturnValueTo64Bit(Operand resultOperand, Context ctx)
        {
            SigType       I4            = new SigType(CilElementType.I4);
            SigType       U4            = new SigType(CilElementType.U4);
            MemoryOperand memoryOperand = resultOperand as MemoryOperand;

            if (memoryOperand == null)
            {
                return;
            }
            Operand opL, opH;

            LongOperandTransformationStage.SplitLongOperand(memoryOperand, out opL, out opH);
            //MemoryOperand opL = new MemoryOperand(U4, memoryOperand.Base, memoryOperand.Offset);
            //MemoryOperand opH = new MemoryOperand(I4, memoryOperand.Base, new IntPtr(memoryOperand.Offset.ToInt64() + 4));
            RegisterOperand eax = new RegisterOperand(U4, GeneralPurposeRegister.EAX);
            RegisterOperand edx = new RegisterOperand(I4, GeneralPurposeRegister.EDX);

            ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, opL, eax);
            ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, opH, edx);
        }
Esempio n. 6
0
        /// <summary>
        /// Pushes the specified instructions.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="op">The op.</param>
        /// <param name="stackSize">Size of the stack.</param>
        private void Push(Context ctx, Operand op, int stackSize)
        {
            if (op is MemoryOperand)
            {
                RegisterOperand rop;
                switch (op.StackType)
                {
                case StackTypeCode.O:
                    goto case StackTypeCode.N;

                case StackTypeCode.Ptr:
                    goto case StackTypeCode.N;

                case StackTypeCode.Int32:
                    goto case StackTypeCode.N;

                case StackTypeCode.N:
                    rop = new RegisterOperand(op.Type, GeneralPurposeRegister.EAX);
                    break;

                case StackTypeCode.F:
                    rop = new RegisterOperand(op.Type, SSE2Register.XMM0);
                    break;

                case StackTypeCode.Int64:
                {
                    SigType       I4  = new SigType(CilElementType.I4);
                    MemoryOperand mop = op as MemoryOperand;
                    Debug.Assert(null != mop, "I8/U8 arg is not in a memory operand.");
                    RegisterOperand eax = new RegisterOperand(I4, GeneralPurposeRegister.EAX);
                    Operand         opL, opH;
                    LongOperandTransformationStage.SplitLongOperand(mop, out opL, out opH);
                    //MemoryOperand opL = new MemoryOperand(I4, mop.Base, mop.Offset);
                    //MemoryOperand opH = new MemoryOperand(I4, mop.Base, new IntPtr(mop.Offset.ToInt64() + 4));

                    ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, eax, opL);
                    ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, new MemoryOperand(op.Type, GeneralPurposeRegister.EDX, new IntPtr(stackSize)), eax);
                    ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, eax, opH);
                    ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, new MemoryOperand(op.Type, GeneralPurposeRegister.EDX, new IntPtr(stackSize + 4)), eax);
                }
                    return;

                default:

                    throw new NotSupportedException();
                }

                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, rop, op);
                op = rop;
            }
            else if (op is ConstantOperand && op.StackType == StackTypeCode.Int64)
            {
                Operand         opL, opH;
                SigType         I4  = new SigType(CilElementType.I4);
                RegisterOperand eax = new RegisterOperand(I4, GeneralPurposeRegister.EAX);
                LongOperandTransformationStage.SplitLongOperand(op, out opL, out opH);

                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, eax, opL);
                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, new MemoryOperand(I4, GeneralPurposeRegister.EDX, new IntPtr(stackSize)), eax);
                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, eax, opH);
                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, new MemoryOperand(I4, GeneralPurposeRegister.EDX, new IntPtr(stackSize + 4)), eax);

                return;
            }

            ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, new MemoryOperand(op.Type, GeneralPurposeRegister.EDX, new IntPtr(stackSize)), op);
        }