Esempio n. 1
0
        /// <summary>
        /// Creates the temporary moves.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="block">The block.</param>
        /// <param name="stack">The stack.</param>
        private void CreateTemporaryMoves(Context ctx, BasicBlock block, Stack <Operand> stack)
        {
            Context context = ctx.InsertBefore();

            context.SetInstruction(IR.Instruction.NopInstruction);

            BasicBlock nextBlock;

            if (NextBlockHasInitialStack(block, out nextBlock))
            {
                LinkTemporaryMoves(context, block, nextBlock, stack);
            }
            else
            {
                CreateNewTemporaryMoves(context, block, stack);
            }
        }
        private void HandleMemoryToMemoryOperation(Context ctx, Operand register, bool useStack)
        {
            Operand destination = ctx.Result;
            Operand source = ctx.Operand1;

            Debug.Assert(destination is MemoryOperand && source is MemoryOperand);

            if (register == null)
                register = new RegisterOperand(destination.Type, GeneralPurposeRegister.EDX);

            ctx.Operand1 = register;

            Context before = ctx.InsertBefore();

            if (useStack) {
                before.SetInstruction(CPUx86.Instruction.PushInstruction, null, register);
                before.AppendInstruction(CPUx86.Instruction.MovInstruction, register, source);
            }
            else
                before.SetInstruction(CPUx86.Instruction.MovInstruction, register, source);

            if (useStack)
                ctx.AppendInstruction(CPUx86.Instruction.PopInstruction, register);
        }
        /// <summary>
        /// Visitation function for <see cref="CPUx86.IX86Visitor.UDiv"/> instructions.
        /// </summary>
        /// <param name="context">The context.</param>
        void CPUx86.IX86Visitor.UDiv(Context context)
        {
            RegisterOperand edx = new RegisterOperand(new SigType(CilElementType.I), GeneralPurposeRegister.EDX);
            Context before = context.InsertBefore();
            before.SetInstruction(CPUx86.Instruction.XorInstruction, edx, edx);

            if (context.Operand1 is ConstantOperand) {
                RegisterOperand ecx = new RegisterOperand(context.Operand1.Type, GeneralPurposeRegister.ECX);
                before.AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, context.Operand1);
                context.Operand1 = ecx;
            }
        }
 /// <summary>
 /// Visitation function for <see cref="CPUx86.IX86Visitor.Shr"/> instructions.
 /// </summary>
 /// <param name="context">The context.</param>
 void CPUx86.IX86Visitor.Shr(Context context)
 {
     if (context.Operand1 is ConstantOperand)
         return;
     RegisterOperand ecx = new RegisterOperand(new SigType(CilElementType.I), GeneralPurposeRegister.ECX);
     Context before = context.InsertBefore();
     before.SetInstruction(CPUx86.Instruction.MovInstruction, ecx, context.Operand1);
     context.Operand1 = context.Result;
 }
        /// <summary>
        /// Visitation function for <see cref="CPUx86.IX86Visitor.Mul"/> instructions.
        /// </summary>
        /// <param name="ctx">The context.</param>
        void CPUx86.IX86Visitor.Mul(Context ctx)
        {
            if (ctx.Operand1 is ConstantOperand) {
                RegisterOperand ecx = new RegisterOperand(ctx.Operand1.Type, GeneralPurposeRegister.ECX);
                Context before = ctx.InsertBefore();
                before.SetInstruction(CPUx86.Instruction.PushInstruction, null, ecx);
                before.AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, ctx.Operand1);

                ctx.Operand1 = ecx;
                ctx.AppendInstruction(CPUx86.Instruction.PopInstruction, ecx);
            }

            if (ctx.Operand1 == null || ctx.Result == null)
                return;
        }
        /// <summary>
        /// Visitation function for <see cref="CPUx86.IX86Visitor.Div"/> instructions.
        /// </summary>
        /// <param name="context">The context.</param>
        void CPUx86.IX86Visitor.Div(Context context)
        {
            Context before = context.InsertBefore();
            before.SetInstruction(CPUx86.Instruction.CdqInstruction);

            if (context.Operand1 is ConstantOperand) {
                RegisterOperand ecx = new RegisterOperand(context.Operand1.Type, GeneralPurposeRegister.ECX);
                before.AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, context.Operand1);
                context.Operand1 = ecx;
            }
        }
        /// <summary>
        /// Visitation function for RemFInstruction.
        /// </summary>
        /// <param name="context">The context.</param>
        void IR.IIRVisitor.RemFInstruction(Context context)
        {
            HandleNonCommutativeOperation(context, CPUx86.Instruction.SseDivInstruction);
            ExtendToR8(context);

            Operand destination = context.Result;
            Operand source = context.Operand1;

            Context[] newBlocks = CreateEmptyBlockContexts(context.Label, 3);
            Context nextBlock = SplitContext(context, false);

            RegisterOperand xmm5 = new RegisterOperand(new SigType(CilElementType.R8), SSE2Register.XMM5);
            RegisterOperand xmm6 = new RegisterOperand(new SigType(CilElementType.R8), SSE2Register.XMM6);
            RegisterOperand eax = new RegisterOperand(new SigType(CilElementType.I4), GeneralPurposeRegister.EAX);
            RegisterOperand edx = new RegisterOperand(new SigType(CilElementType.I4), GeneralPurposeRegister.EDX);
            RegisterOperand uedx = new RegisterOperand(new SigType(CilElementType.U4), GeneralPurposeRegister.EDX);
            Context before = context.InsertBefore();

            context.SetInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[0].BasicBlock);
            LinkBlocks(context, newBlocks[0]);

            newBlocks[0].SetInstruction(CPUx86.Instruction.MovsdInstruction, xmm5, source);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.MovsdInstruction, xmm6, destination);

            newBlocks[0].AppendInstruction(CPUx86.Instruction.SseDivInstruction, destination, source);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.Cvttsd2siInstruction, edx, destination);

            newBlocks[0].AppendInstruction(CPUx86.Instruction.CmpInstruction, edx, new ConstantOperand(new SigType(CilElementType.I4), 0));
            newBlocks[0].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.Equal, newBlocks[2].BasicBlock);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[1].BasicBlock);
            LinkBlocks(newBlocks[0], newBlocks[1], newBlocks[2]);

            newBlocks[1].AppendInstruction(CPUx86.Instruction.Cvtsi2sdInstruction, destination, edx);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.SseMulInstruction, destination, xmm5);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.SseSubInstruction, xmm6, destination);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.MovsdInstruction, destination, xmm6);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.JmpInstruction, nextBlock.BasicBlock);
            LinkBlocks(newBlocks[1], nextBlock);

            newBlocks[2].SetInstruction(CPUx86.Instruction.MovsdInstruction, destination, xmm6);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.JmpInstruction, nextBlock.BasicBlock);
            LinkBlocks(newBlocks[2], nextBlock);
        }
 /// <summary>
 /// Visitation function for SubSInstruction.
 /// </summary>
 /// <param name="context">The context.</param>
 void IR.IIRVisitor.SubSInstruction(Context context)
 {
     if (IsInt64(context.Operand1))
     {
         ExpandSub(context);
     }
     else
     {
         if (context.Operand2 is ConstantOperand && context.Operand1.Type.Type == CilElementType.Char)
         {
             RegisterOperand ecx = new RegisterOperand(context.Operand1.Type, GeneralPurposeRegister.ECX);
             context.InsertBefore().SetInstruction(CPUx86.Instruction.MovInstruction, ecx, context.Operand2);
             context.Operand2 = ecx;
         }
     }
 }
Esempio n. 9
0
        /// <summary>
        /// Eliminates the common subexpressions.
        /// </summary>
        /// <param name="ctx">The context.</param>
        private static void EliminateCommonSubexpressions(Context ctx)
        {
            List<AEBinExp> AEB = new List<AEBinExp>();
            List<AEBinExp> tmp;

            AEBinExp aeb;

            for (; !ctx.EndOfInstruction; ctx.GotoNext()) {
                IInstruction instruction = ctx.Instruction; // block.Instructions[i];
                RegisterOperand temp = null;
                bool found = false;

                if ((instruction is CIL.ArithmeticInstruction) && (instruction is CIL.BinaryInstruction)) {
                    tmp = new List<AEBinExp>(AEB);

                    while (tmp.Count > 0) {
                        aeb = tmp[0];
                        tmp.RemoveAt(0);

                        // Match current instruction's expression against those
                        // in AEB, including commutativity
                        if (IsCommutative(instruction)) {
                            //int position = aeb.Position;
                            found = true;

                            // If no variable in tuple, create a new temporary and
                            // insert an instruction evaluating the expression
                            // and assigning it to the temporary
                            if (aeb.Var == null) {
                                // new_tmp()
                                AEB.Remove(aeb);
                                AEB.Add(new AEBinExp(aeb.Position, aeb.Operand1, aeb.Operator, aeb.Operand2, temp));

                                // Insert new assignment to instruction stream in block
                                Context inserted = ctx.InsertBefore();

                                switch (aeb.Operator) {
                                    case Operation.Add:
                                        inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Add), temp, aeb.Operand1, aeb.Operand2);
                                        break;
                                    case Operation.Mul:
                                        inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Mul), temp, aeb.Operand1, aeb.Operand2);
                                        break;
                                    case Operation.Or:
                                        inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Or), temp, aeb.Operand1, aeb.Operand2);
                                        break;
                                    case Operation.Xor:
                                        inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Xor), temp, aeb.Operand1, aeb.Operand2);
                                        break;
                                    default:
                                        break;
                                }

                                //block.Instructions.Insert(position, inst);

                                //++position;
                                //++i;

                                // Replace current instruction by one that copies
                                // the temporary instruction
                                // FIXME PG:
                                // block.Instructions[position] = new IR.MoveInstruction(block.Instructions[position].Results[0], temp);
                                // ctx.SetInstruction(IR.MoveInstruction); // FIXME PG
                                // ctx.Result = block.Instructions[position].Results[0]; // FIXME PG
                                ctx.Operand1 = temp;
                            }
                            else {
                                temp = (RegisterOperand)aeb.Var;
                            }

                            // FIXME PG
                            // block.Instructions[i] = new IR.MoveInstruction(instruction.Results[0], temp);
                        }
                    }

                    if (!found) {
                        Operation opr = Operation.None;

                        if (instruction is CIL.AddInstruction)
                            opr = Operation.Add;
                        else if (instruction is CIL.MulInstruction)
                            opr = Operation.Mul;
                        else if (instruction is IR.LogicalAndInstruction)
                            opr = Operation.And;
                        // Insert new tuple
                        AEB.Add(new AEBinExp(ctx.Index, ctx.Operand1, opr, ctx.Operand2, null));
                    }

                    // Remove all tuples that use the variable assigned to by
                    // the current instruction
                    tmp = new List<AEBinExp>(AEB);

                    while (tmp.Count > 0) {
                        aeb = tmp[0];
                        tmp.RemoveAt(0);

                        if (ctx.Operand1 == aeb.Operand1 || ctx.Operand2 == aeb.Operand2)
                            AEB.Remove(aeb);
                    }
                }
            }
        }
        /// <summary>
        /// Converts the given instruction from three address format to a two address format.
        /// </summary>
        /// <param name="ctx">The conversion context.</param>
        private static void ThreeTwoAddressConversion(Context ctx)
        {
            Operand result = ctx.Result;
            Operand op1 = ctx.Operand1;
            Operand op2 = ctx.Operand2;

            if (ctx.Instruction is IR.FloatingPointCompareInstruction)
                return;

            if (ctx.Instruction is CIL.MulInstruction /*|| ctx.Instruction is CIL.DivInstruction*/)
                if (!(op1 is ConstantOperand) && (op2 is ConstantOperand))
                {
                    Operand temp = op1;
                    op1 = op2;
                    op2 = temp;
                }

            // Create registers for different data types
            RegisterOperand eax = new RegisterOperand(op1.Type, op1.StackType == StackTypeCode.F ? (Register)SSE2Register.XMM0 : GeneralPurposeRegister.EAX);
            RegisterOperand storeOperand = new RegisterOperand(result.Type, result.StackType == StackTypeCode.F ? (Register)SSE2Register.XMM0 : GeneralPurposeRegister.EAX);
            //    RegisterOperand eaxL = new RegisterOperand(op1.Type, GeneralPurposeRegister.EAX);

            ctx.Result = storeOperand;
            ctx.Operand1 = op2;
            ctx.Operand2 = null;
            ctx.OperandCount = 1;

            if (op1.StackType != StackTypeCode.F)
            {
                if (IsSigned(op1) && !(op1 is ConstantOperand))
                    ctx.InsertBefore().SetInstruction(IR.Instruction.SignExtendedMoveInstruction, eax, op1);
                else if (IsUnsigned(op1) && !(op1 is ConstantOperand))
                    ctx.InsertBefore().SetInstruction(IR.Instruction.ZeroExtendedMoveInstruction, eax, op1);
                else
                    ctx.InsertBefore().SetInstruction(CPUx86.Instruction.MovInstruction, eax, op1);
            }
            else
            {
                if (op1.Type.Type == CilElementType.R4)
                {
                    if (op1 is ConstantOperand)
                    {
                        Context before = ctx.InsertBefore();
                        before.SetInstruction(CPUx86.Instruction.MovInstruction, eax, op1);
                        before.AppendInstruction(CPUx86.Instruction.Cvtss2sdInstruction, eax, eax);
                    }
                    else
                        ctx.InsertBefore().SetInstruction(CPUx86.Instruction.Cvtss2sdInstruction, eax, op1);
                }
                else
                    ctx.InsertBefore().SetInstruction(CPUx86.Instruction.MovInstruction, eax, op1);
            }
            ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, result, eax);
        }
Esempio n. 11
0
        /// <summary>
        /// Eliminates the common subexpressions.
        /// </summary>
        /// <param name="ctx">The context.</param>
        private static void EliminateCommonSubexpressions(Context ctx)
        {
            List <AEBinExp> AEB = new List <AEBinExp> ();
            List <AEBinExp> tmp;

            AEBinExp aeb;

            for (; !ctx.EndOfInstruction; ctx.GotoNext())
            {
                IInstruction instruction = ctx.Instruction;
                // block.Instructions[i];
                RegisterOperand temp  = null;
                bool            found = false;

                if ((instruction is CIL.ArithmeticInstruction) && (instruction is CIL.BinaryInstruction))
                {
                    tmp = new List <AEBinExp> (AEB);

                    while (tmp.Count > 0)
                    {
                        aeb = tmp[0];
                        tmp.RemoveAt(0);

                        // Match current instruction's expression against those
                        // in AEB, including commutativity
                        if (IsCommutative(instruction))
                        {
                            //int position = aeb.Position;
                            found = true;

                            // If no variable in tuple, create a new temporary and
                            // insert an instruction evaluating the expression
                            // and assigning it to the temporary
                            if (aeb.Var == null)
                            {
                                // new_tmp()
                                AEB.Remove(aeb);
                                AEB.Add(new AEBinExp(aeb.Position, aeb.Operand1, aeb.Operator, aeb.Operand2, temp));

                                // Insert new assignment to instruction stream in block
                                Context inserted = ctx.InsertBefore();

                                switch (aeb.Operator)
                                {
                                case Operation.Add:
                                    inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Add), temp, aeb.Operand1, aeb.Operand2);
                                    break;

                                case Operation.Mul:
                                    inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Mul), temp, aeb.Operand1, aeb.Operand2);
                                    break;

                                case Operation.Or:
                                    inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Or), temp, aeb.Operand1, aeb.Operand2);
                                    break;

                                case Operation.Xor:
                                    inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Xor), temp, aeb.Operand1, aeb.Operand2);
                                    break;

                                default:
                                    break;
                                }

                                //block.Instructions.Insert(position, inst);

                                //++position;
                                //++i;

                                // Replace current instruction by one that copies
                                // the temporary instruction
                                // FIXME PG:
                                // block.Instructions[position] = new IR.MoveInstruction(block.Instructions[position].Results[0], temp);
                                // ctx.SetInstruction(IR.MoveInstruction); // FIXME PG
                                // ctx.Result = block.Instructions[position].Results[0]; // FIXME PG
                                ctx.Operand1 = temp;
                            }
                            else
                            {
                                temp = (RegisterOperand)aeb.Var;
                            }

                            // FIXME PG
                            // block.Instructions[i] = new IR.MoveInstruction(instruction.Results[0], temp);
                        }
                    }

                    if (!found)
                    {
                        Operation opr = Operation.None;

                        if (instruction is CIL.AddInstruction)
                        {
                            opr = Operation.Add;
                        }
                        else if (instruction is CIL.MulInstruction)
                        {
                            opr = Operation.Mul;
                        }
                        else if (instruction is IR.LogicalAndInstruction)
                        {
                            opr = Operation.And;
                        }
                        // Insert new tuple
                        AEB.Add(new AEBinExp(ctx.Index, ctx.Operand1, opr, ctx.Operand2, null));
                    }

                    // Remove all tuples that use the variable assigned to by
                    // the current instruction
                    tmp = new List <AEBinExp> (AEB);

                    while (tmp.Count > 0)
                    {
                        aeb = tmp[0];
                        tmp.RemoveAt(0);

                        if (ctx.Operand1 == aeb.Operand1 || ctx.Operand2 == aeb.Operand2)
                        {
                            AEB.Remove(aeb);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Visitation function for <see cref="ICILVisitor.Newobj"/>.
        /// </summary>
        /// <param name="ctx">The context.</param>
        public void Newobj(Context ctx)
        {
            Operand thisReference = ctx.Result;
            Debug.Assert(thisReference != null, @"Newobj didn't specify class signature?");

            ClassSigType classSigType = (ClassSigType)thisReference.Type;
            RuntimeType classType = RuntimeBase.Instance.TypeLoader.GetType(this.MethodCompiler.Method, this.MethodCompiler.Assembly, classSigType.Token);

            List<Operand> ctorOperands = new List<Operand>(ctx.Operands);

            Context before = ctx.InsertBefore();
            before.SetInstruction(Instruction.NopInstruction);

            ReplaceWithInternalCall(before, VmCall.AllocateObject);

            SymbolOperand methodTableSymbol = this.GetMethodTableSymbol(classType);

            before.SetOperand(1, methodTableSymbol);
            before.SetOperand(2, new ConstantOperand(BuiltInSigType.Int32, classType.Size));
            before.OperandCount = 2;
            before.Result = thisReference;

            // Result is the this pointer, now invoke the real constructor
            RuntimeMethod ctorMethod = this.FindConstructor(classType, ctorOperands);
            SymbolOperand symbolOperand = SymbolOperand.FromMethod(ctorMethod);

            ctorOperands.Insert(0, thisReference);
            this.ProcessInvokeInstruction(ctx, symbolOperand, null, ctorOperands);
        }
        /// <summary>
        /// Visitation function for <see cref="CIL.ICILVisitor.Rem"/>.
        /// </summary>
        /// <param name="ctx">The context.</param>
        void CIL.ICILVisitor.Rem(Context ctx)
        {
            Operand result = ctx.Result;
            Operand operand = ctx.Operand1;

            if (ctx.Operand1.StackType != StackTypeCode.F)
            {
                RegisterOperand eax = new RegisterOperand(new SigType(CilElementType.I4), GeneralPurposeRegister.EAX);
                RegisterOperand ecx = new RegisterOperand(new SigType(CilElementType.I4), GeneralPurposeRegister.ECX);
                RegisterOperand eaxSource = new RegisterOperand(result.Type, GeneralPurposeRegister.EAX);
                RegisterOperand ecxSource = new RegisterOperand(operand.Type, GeneralPurposeRegister.ECX);

                ctx.SetInstruction(CPUx86.Instruction.MovInstruction, eaxSource, result);
                if (IsUnsigned(result))
                    ctx.AppendInstruction(IR.Instruction.ZeroExtendedMoveInstruction, eax, eaxSource);
                else
                    ctx.AppendInstruction(IR.Instruction.SignExtendedMoveInstruction, eax, eaxSource);

                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, ecxSource, operand);
                if (IsUnsigned(operand))
                    ctx.AppendInstruction(IR.Instruction.ZeroExtendedMoveInstruction, ecx, ecxSource);
                else
                    ctx.AppendInstruction(IR.Instruction.SignExtendedMoveInstruction, ecx, ecxSource);

                if (IsUnsigned(result) && IsUnsigned(operand))
                    ctx.AppendInstruction(CPUx86.Instruction.UDivInstruction, eax, ecx);
                else
                    ctx.AppendInstruction(CPUx86.Instruction.DivInstruction, eax, ecx);

                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, result, new RegisterOperand(new SigType(CilElementType.I4), GeneralPurposeRegister.EDX));
            }
            else
            {
                HandleNonCommutativeOperation(ctx, CPUx86.Instruction.SseDivInstruction);
                ExtendToR8(ctx);

                Operand destination = ctx.Result;
                Operand source = ctx.Operand1;

                RegisterOperand xmm5 = new RegisterOperand(new SigType(CilElementType.R8), SSE2Register.XMM5);
                Context before = ctx.InsertBefore();
                before.SetInstruction(CPUx86.Instruction.MovInstruction, xmm5, destination);

                // Round towards zero
                ctx.AppendInstruction(CPUx86.Instruction.SseRoundInstruction, destination, destination, new ConstantOperand(BuiltInSigType.Byte, 0x03));

                ctx.AppendInstruction(CPUx86.Instruction.SseMulInstruction, destination, source);
                ctx.AppendInstruction(CPUx86.Instruction.SseSubInstruction, xmm5, destination);
                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, destination, xmm5);
            }
        }
        /// <summary>
        /// Visitation function for Newobj instruction.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Newobj(Context context)
        {
            Operand thisReference = context.Result;
            Debug.Assert(thisReference != null, @"Newobj didn't specify class signature?");

            ClassSigType classSigType = (ClassSigType)thisReference.Type;
            RuntimeType classType = typeModule.GetType(classSigType.Token);

            List<Operand> ctorOperands = new List<Operand>(context.Operands);
            RuntimeMethod ctorMethod = context.InvokeTarget;

            if (!ReplaceWithInternalCall(context, ctorMethod))
            {
                Context before = context.InsertBefore();
                before.SetInstruction(Instruction.NopInstruction);

                ReplaceWithVmCall(before, VmCall.AllocateObject);

                SymbolOperand methodTableSymbol = GetMethodTableSymbol(classType);

                before.SetOperand(1, methodTableSymbol);
                before.SetOperand(2, new ConstantOperand(BuiltInSigType.Int32, typeLayout.GetTypeSize(classType)));
                before.OperandCount = 2;
                before.Result = thisReference;

                // Result is the this pointer, now invoke the real constructor
                SymbolOperand symbolOperand = SymbolOperand.FromMethod(ctorMethod);

                ctorOperands.Insert(0, thisReference);
                ProcessInvokeInstruction(context, symbolOperand, null, ctorOperands);
            }
        }
        /// <summary>
        /// Extends to r8.
        /// </summary>
        /// <param name="ctx">The context.</param>
        private static void ExtendToR8(Context ctx)
        {
            RegisterOperand xmm5 = new RegisterOperand(new SigType(CilElementType.R8), SSE2Register.XMM5);
            RegisterOperand xmm6 = new RegisterOperand(new SigType(CilElementType.R8), SSE2Register.XMM6);
            Context before = ctx.InsertBefore();

            if (ctx.Result.Type.Type == CilElementType.R4) {
                before.SetInstruction(CPUx86.Instruction.Cvtss2sdInstruction, xmm5, ctx.Result);
                ctx.Result = xmm5;
            }

            if (ctx.Operand1.Type.Type == CilElementType.R4) {
                before.SetInstruction(CPUx86.Instruction.Cvtss2sdInstruction, xmm6, ctx.Operand1);
                ctx.Operand1 = xmm6;
            }
        }
 /// <summary>
 /// Visitation function for <see cref="CIL.ICILVisitor.Sub"/>.
 /// </summary>
 /// <param name="ctx">The context.</param>
 void CIL.ICILVisitor.Sub(Context ctx)
 {
     if (ctx.Operand1.StackType == StackTypeCode.Int64)
         ExpandSub(ctx);
     else
     {
         if (ctx.Operand2 is ConstantOperand && ctx.Operand1.Type.Type == CilElementType.Char)
         {
             RegisterOperand ecx = new RegisterOperand(ctx.Operand1.Type, GeneralPurposeRegister.ECX);
             ctx.InsertBefore().SetInstruction(CPUx86.Instruction.MovInstruction, ecx, ctx.Operand2);
             ctx.Operand2 = ecx;
         }
     }
 }
        private void HandleMemoryToMemoryOperation(Context ctx)
        {
            Operand destination = ctx.Result;
            Operand source = ctx.Operand1;

            Debug.Assert(destination is MemoryOperand && source is MemoryOperand);

            SigType destinationSigType = destination.Type;

            if (this.RequiresSseOperation(destinationSigType))
            {
                IInstruction moveInstruction = this.GetMoveInstruction(destinationSigType);
                RegisterOperand destinationRegister = this.AllocateRegister(destinationSigType);

                ctx.Result = destinationRegister;
                ctx.AppendInstruction(moveInstruction, destination, destinationRegister);
            }
            else
            {
                SigType sourceSigType = ctx.Operand1.Type;
                IInstruction moveInstruction = this.GetMoveInstruction(sourceSigType);
                RegisterOperand sourceRegister = this.AllocateRegister(sourceSigType);

                ctx.Operand1 = sourceRegister;

                ctx.InsertBefore().SetInstruction(moveInstruction, sourceRegister, source);
            }
        }
        /// <summary>
        /// Visitation function for <see cref="CPUx86.IX86Visitor.Call"/> instructions.
        /// </summary>
        /// <param name="context">The context.</param>
        void CPUx86.IX86Visitor.Call(Context context)
        {
            Operand destinationOperand = context.Operand1;

            if (destinationOperand == null)
            {
                return;
            }

            if (destinationOperand is SymbolOperand)
            {
                return;
            }

            if (!(destinationOperand is RegisterOperand))
            {
                Context before = context.InsertBefore();
                RegisterOperand eax = new RegisterOperand(BuiltInSigType.IntPtr, GeneralPurposeRegister.EAX);

                before.SetInstruction(CPUx86.Instruction.MovInstruction, eax, destinationOperand);
                context.Operand1 = eax;
            }
        }
        private Operand InsertLoadBeforeInstruction(Context context, string symbolName, SigType type)
        {
            Context before = context.InsertBefore();
            Operand result = this.MethodCompiler.CreateTemporary(type);
            Operand op = new SymbolOperand(type, symbolName);

            before.SetInstruction(Instruction.Get(OpCode.Ldc_i4), result, op);

            return result;
        }
        /// <summary>
        /// Visitation function for <see cref="CPUx86.IX86Visitor.Cmp"/> instructions.
        /// </summary>
        /// <param name="ctx">The context.</param>
        void CPUx86.IX86Visitor.Cmp(Context ctx)
        {
            Operand left = ctx.Result;
            Operand right = ctx.Operand1;

            if (left is ConstantOperand)
            {
                RegisterOperand ecx = new RegisterOperand(left.Type, GeneralPurposeRegister.ECX);
                Context before = ctx.InsertBefore();
                before.SetInstruction(CPUx86.Instruction.PushInstruction, null, ecx);
                before.AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, left);
                ctx.Result = ecx;
                ctx.AppendInstruction(CPUx86.Instruction.PopInstruction, ecx);
            }
            if (right is ConstantOperand && !Is32Bit(left))
            {
                RegisterOperand edx = new RegisterOperand(new SigType(CilElementType.I4), GeneralPurposeRegister.EBX);
                Context before = ctx.InsertBefore();
                before.SetInstruction(CPUx86.Instruction.PushInstruction, null, edx);
                if (IsSigned(left))
                    before.AppendInstruction(CPUx86.Instruction.MovsxInstruction, edx, left);
                else
                    before.AppendInstruction(CPUx86.Instruction.MovzxInstruction, edx, left);
                ctx.Result = edx;
                ctx.AppendInstruction(CPUx86.Instruction.PopInstruction, edx);
            }
        }
        /// <summary>
        /// Creates the temporary moves.
        /// </summary>
        /// <param name="ctx">The CTX.</param>
        /// <param name="block">The block.</param>
        /// <param name="stack">The stack.</param>
        private void CreateTemporaryMoves(Context ctx, BasicBlock block, Stack<Operand> stack)
        {
            Context context = ctx.InsertBefore();

            context.SetInstruction(IR.Instruction.NopInstruction);

            BasicBlock nextBlock;

            if (NextBlockHasInitialStack(block, out nextBlock))
                LinkTemporaryMoves(context, block, nextBlock, stack);
            else
                CreateNewTemporaryMoves(context, block, stack);
        }
        public void RemFInstruction(Context context)
        {
            HandleNonCommutativeOperation(context, CPUx86.Instruction.SseDivInstruction);
            ExtendToR8(context);

            Operand destination = context.Result;
            Operand source = context.Operand1;

            RegisterOperand xmm5 = new RegisterOperand(new SigType(CilElementType.R8), SSE2Register.XMM5);
            Context before = context.InsertBefore();
            before.SetInstruction(CPUx86.Instruction.MovInstruction, xmm5, destination);

            // Round towards zero
            context.AppendInstruction(CPUx86.Instruction.SseRoundInstruction, destination, destination, new ConstantOperand(BuiltInSigType.Byte, 0x03));

            context.AppendInstruction(CPUx86.Instruction.SseMulInstruction, destination, source);
            context.AppendInstruction(CPUx86.Instruction.SseSubInstruction, xmm5, destination);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, destination, xmm5);
        }