/// <summary>
        /// Creates the ISR methods.
        /// </summary>
        /// <param name="compiler">The compiler.</param>
        private void CreateISRMethods(AssemblyCompiler compiler)
        {
            // Create Interrupt Service Routines (ISR)
            RuntimeMethod InterruptMethod = compiler.Assembly.EntryPoint; // TODO: replace with another entry point

            SigType I1 = new SigType(CilElementType.I1);
            SigType I4 = new SigType(CilElementType.I4);
            RegisterOperand eax = new RegisterOperand(I4, GeneralPurposeRegister.EAX);

            for (int i = 0; i <= 256; i++) {
                InstructionSet set = new InstructionSet(100);
                Context ctx = new Context(set, -1);

                ctx.SetInstruction(CPUx86.Instruction.CliInstruction);
                if ((i != 8) && (i < 10 || i > 14)) // For IRQ 8, 10, 11, 12, 13, 14 the cpu automatically pushed the error code
                    ctx.AppendInstruction(CPUx86.Instruction.PushInstruction, null, new ConstantOperand(I4, 0x0));
                ctx.AppendInstruction(CPUx86.Instruction.PushadInstruction);
                ctx.AppendInstruction(CPUx86.Instruction.PushInstruction, null, new ConstantOperand(I4, i));
                // TODO: Set method parameters
                ctx.AppendInstruction(CPUx86.Instruction.CallInstruction, InterruptMethod);
                ctx.AppendInstruction(CPUx86.Instruction.PopInstruction, eax);
                ctx.AppendInstruction(CPUx86.Instruction.PopadInstruction);
                ctx.AppendInstruction(CPUx86.Instruction.PopInstruction, eax);
                ctx.AppendInstruction(CPUx86.Instruction.StiInstruction);
                //ctx.AppendInstruction(CPUx86.Instruction.IRetdInstruction);

                CompilerGeneratedMethod method = LinkTimeCodeGenerator.Compile(compiler, @"InterruptISR" + i.ToString(), set);
            }
        }
        /// <summary>
        /// Creates the ISR methods.
        /// </summary>
        /// <param name="compiler">The compiler.</param>
        private void CreateISRMethods(AssemblyCompiler compiler)
        {
            // Get RuntimeMethod for the Mosa.Kernel.X86.IDT.InterruptHandler
            RuntimeType rt = RuntimeBase.Instance.TypeLoader.GetType(@"Mosa.Kernel.X86.IDT");
            RuntimeMethod InterruptMethod = FindMethod(rt, "InterruptHandler");

            SigType I1 = new SigType(CilElementType.I1);
            SigType I2 = new SigType(CilElementType.I4);

            RegisterOperand ecx1 = new RegisterOperand(I1, GeneralPurposeRegister.ECX);
            RegisterOperand ecx2 = new RegisterOperand(I2, GeneralPurposeRegister.ECX);

            for (int i = 0; i <= 256; i++) {
                InstructionSet set = new InstructionSet(100);
                Context ctx = new Context(set, -1);

                ctx.AppendInstruction(CPUx86.Instruction.CliInstruction);
                ctx.AppendInstruction(CPUx86.Instruction.PushadInstruction);
                if ((i != 8) && (i < 10 || i > 14)) // For IRQ 8, 10, 11, 12, 13, 14 the cpu automatically pushed the error code
                    ctx.AppendInstruction(CPUx86.Instruction.PushInstruction, null, new ConstantOperand(I1, 0x0));
                ctx.AppendInstruction(CPUx86.Instruction.PushInstruction, null, new ConstantOperand(I2, i));
                ctx.AppendInstruction(CPUx86.Instruction.CallInstruction, InterruptMethod);
                // TODO: Replace next two instructions with add esp, 5 ;Stack clearing
                ctx.AppendInstruction(CPUx86.Instruction.PopInstruction, ecx2);
                ctx.AppendInstruction(CPUx86.Instruction.PopInstruction, ecx1);
                ctx.AppendInstruction(CPUx86.Instruction.PopadInstruction);
                ctx.AppendInstruction(CPUx86.Instruction.StiInstruction);
                ctx.AppendInstruction(CPUx86.Instruction.IRetdInstruction);

                CompilerGeneratedMethod method = LinkTimeCodeGenerator.Compile(compiler, @"InterruptISR" + i.ToString(), set);
            }
        }
        /// <summary>
        /// Replaces the instrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem)
        {
            Operand result = context.Result;

            RegisterOperand imm = new RegisterOperand(new SigType(CilElementType.U4), GeneralPurposeRegister.EAX);

            context.SetInstruction(IR.Instruction.MoveInstruction, imm, new RegisterOperand(new SigType(CilElementType.U4), _control));
            context.AppendInstruction(IR.Instruction.MoveInstruction, result, imm);
        }
Example #4
0
 /// <summary>
 /// Visitation function for <see cref="IR.IIRVisitor.AddressOfInstruction"/> instruction.
 /// </summary>
 /// <param name="ctx">The context.</param>
 void IR.IIRVisitor.AddressOfInstruction(Context ctx)
 {
     Operand opRes = ctx.Result;
     RegisterOperand eax = new RegisterOperand (opRes.Type, GeneralPurposeRegister.EAX);
     ctx.Result = eax;
     ctx.ReplaceInstructionOnly (CPUx86.Instruction.LeaInstruction);
     //            ctx.Ignore = true;
     ctx.AppendInstruction (CPUx86.Instruction.MovInstruction, opRes, eax);
 }
        /// <summary>
        /// Replaces the instrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        public void ReplaceIntrinsicCall(Context context)
        {
            Operand operand1 = context.Operand1;

            RegisterOperand imm = new RegisterOperand(new SigType(CilElementType.U4), GeneralPurposeRegister.EAX);

            context.SetInstruction(IR.Instruction.MoveInstruction, imm, operand1);
            context.AppendInstruction(IR.Instruction.MoveInstruction, new RegisterOperand(new SigType(CilElementType.U4), _control), imm);
        }
Example #6
0
        /// <summary>
        /// Replaces the instrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem)
        {
            Operand result = context.Result;

            RegisterOperand tmp = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Ptr), GeneralPurposeRegister.EDX);
            MemoryOperand operand = new MemoryOperand(context.Operand1.Type, GeneralPurposeRegister.EDX, new System.IntPtr(0));

            context.SetInstruction(CPUx86.Instruction.MovInstruction, tmp, context.Operand1);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, result, operand);
        }
Example #7
0
        /// <summary>
        /// Replaces the instrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem)
        {
            SigType I4 = new SigType(CilElementType.I4);
            RegisterOperand esp = new RegisterOperand(I4, GeneralPurposeRegister.ESP);

            context.SetInstruction(CPUx86.Instruction.MovInstruction, esp, context.Operand1);
            context.AppendInstruction(CPUx86.Instruction.PopadInstruction);
            context.AppendInstruction(CPUx86.Instruction.AddInstruction, esp, new ConstantOperand(I4, 0x08));
            context.AppendInstruction(CPUx86.Instruction.StiInstruction);
            context.AppendInstruction(CPUx86.Instruction.IRetdInstruction);
        }
        /// <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);
        }
Example #9
0
        /// <summary>
        /// Replaces the instrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        public void ReplaceIntrinsicCall(Context context)
        {
            Operand operand1 = context.Operand1;
            Operand operand2 = context.Operand2;

            RegisterOperand edx = new RegisterOperand (operand1.Type, GeneralPurposeRegister.EDX);
            RegisterOperand eax = new RegisterOperand (operand2.Type, GeneralPurposeRegister.EAX);

            context.SetInstruction (CPUx86.Instruction.MovInstruction, edx, operand1);
            context.AppendInstruction (CPUx86.Instruction.MovInstruction, eax, operand2);
            context.AppendInstruction (CPUx86.Instruction.OutInstruction, null, edx, eax);
        }
Example #10
0
 /// <summary>
 /// Replaces the instrinsic call site
 /// </summary>
 /// <param name="context">The context.</param>
 public void ReplaceIntrinsicCall(Context context)
 {
     Operand result = context.Result;
     Operand operand = context.Operand1;
     RegisterOperand eax = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I4), GeneralPurposeRegister.EAX);
     RegisterOperand ecx = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I4), GeneralPurposeRegister.ECX);
     RegisterOperand reg = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I4), GeneralPurposeRegister.EBX);
     context.SetInstruction(CPUx86.Instruction.MovInstruction, eax, operand);
     context.AppendInstruction(CPUx86.Instruction.XorInstruction, ecx, ecx);
     context.AppendInstruction(CPUx86.Instruction.CpuIdEbxInstruction);
     context.AppendInstruction(CPUx86.Instruction.MovInstruction, result, reg);
 }
Example #11
0
        /// <summary>
        /// Replaces the instrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem)
        {
            Operand result = context.Result;
            Operand operand1 = context.Operand1;

            RegisterOperand edx = new RegisterOperand(operand1.Type, GeneralPurposeRegister.EDX);
            RegisterOperand eax = new RegisterOperand(result.Type, GeneralPurposeRegister.EAX);

            context.SetInstruction(CPUx86.Instruction.MovInstruction, edx, operand1);
            context.AppendInstruction(CPUx86.Instruction.InInstruction, eax, edx);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, result, eax);
        }
Example #12
0
        /// <summary>
        /// Replaces the instrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem)
        {
            Operand result = context.Result;
            SigType u4 = new SigType(CilElementType.U4);
            RegisterOperand eax = new RegisterOperand(u4, GeneralPurposeRegister.EAX);

            context.SetInstruction(CPUx86.Instruction.PopInstruction, eax);
            context.AppendInstruction(CPUx86.Instruction.AddInstruction, eax, new RegisterOperand(u4, GeneralPurposeRegister.ESP));
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, eax, new MemoryOperand(u4, GeneralPurposeRegister.EAX, new IntPtr(0)));
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, result, eax);
            context.AppendInstruction(CPUx86.Instruction.PushInstruction, null, eax);
        }
Example #13
0
        /// <summary>
        /// Replaces the instrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem)
        {
            Operand dest = context.Operand1;
            Operand value = context.Operand2;

            RegisterOperand edx = new RegisterOperand(dest.Type, GeneralPurposeRegister.EDX);
            RegisterOperand eax = new RegisterOperand(value.Type, GeneralPurposeRegister.EAX);
            MemoryOperand memory = new MemoryOperand(new SigType(context.InvokeTarget.Signature.Parameters[1].Type), GeneralPurposeRegister.EDX, new IntPtr(0));

            context.SetInstruction(CPUx86.Instruction.MovInstruction, edx, dest);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, eax, value);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, memory, eax);
        }
Example #14
0
        /// <summary>
        /// Replaces the instrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem)
        {
            SigType u4 = new SigType(Runtime.Metadata.CilElementType.U4);

            RegisterOperand ebp = new RegisterOperand(u4, GeneralPurposeRegister.EBP);
            RegisterOperand esp = new RegisterOperand(u4, GeneralPurposeRegister.ESP);
            RegisterOperand eax = new RegisterOperand(u4, GeneralPurposeRegister.EAX);
            RegisterOperand ebx = new RegisterOperand(u4, GeneralPurposeRegister.EBX);
            RegisterOperand ecx = new RegisterOperand(u4, GeneralPurposeRegister.ECX);
            RegisterOperand edx = new RegisterOperand(u4, GeneralPurposeRegister.EDX);
            RegisterOperand esi = new RegisterOperand(u4, GeneralPurposeRegister.ESI);
            RegisterOperand edi = new RegisterOperand(u4, GeneralPurposeRegister.EDI);

            context.SetInstruction(CPUx86.Instruction.PushInstruction, null, ebp);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, ebp, esp);
            context.AppendInstruction(CPUx86.Instruction.PushInstruction, null, ebx);
            context.AppendInstruction(CPUx86.Instruction.PushInstruction, null, esi);
            context.AppendInstruction(CPUx86.Instruction.PushInstruction, null, edi);

            // Load register context
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, eax, new MemoryOperand(u4, GeneralPurposeRegister.ESP, new IntPtr(28)));
            // Load exception handler
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, new MemoryOperand(u4, GeneralPurposeRegister.ESP, new IntPtr(32)));
            // Save EBP
            context.AppendInstruction(CPUx86.Instruction.PushInstruction, null, ebp);

            // Restore register values
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, ebp, new MemoryOperand(u4, GeneralPurposeRegister.EAX, new IntPtr(24)));
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, ebx, new MemoryOperand(u4, GeneralPurposeRegister.EAX, new IntPtr(4)));
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, esi, new MemoryOperand(u4, GeneralPurposeRegister.EAX, new IntPtr(16)));
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, edi, new MemoryOperand(u4, GeneralPurposeRegister.EAX, new IntPtr(20)));

            // Align ESP
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, edx, esp);
            context.AppendInstruction(CPUx86.Instruction.AndInstruction, esp, new ConstantOperand(u4, 0xFFFFFFF0u));
            context.AppendInstruction(CPUx86.Instruction.SubInstruction, esp, new ConstantOperand(u4, 0x8u));

            // Save original ESP
            context.AppendInstruction(CPUx86.Instruction.PushInstruction, null, edx);
            // Call catch handler
            context.AppendInstruction(CPUx86.Instruction.CallInstruction, ecx);

            // Restore registers
            context.AppendInstruction(CPUx86.Instruction.PopInstruction, esp);
            context.AppendInstruction(CPUx86.Instruction.PopInstruction, ebp);
            context.AppendInstruction(CPUx86.Instruction.PopInstruction, esi);
            context.AppendInstruction(CPUx86.Instruction.PopInstruction, edi);
            context.AppendInstruction(CPUx86.Instruction.PopInstruction, ebx);
            context.AppendInstruction(CPUx86.Instruction.LeaveInstruction);
            context.AppendInstruction(CPUx86.Instruction.RetInstruction);
        }
        /// <summary>
        /// Replaces the instrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        public void ReplaceIntrinsicCall(Context context)
        {
            if (!(context.Operand1 is ConstantOperand))
                throw new InvalidOperationException();

            Operand result = context.Result;

            ControlRegister control;

            switch ((int)(context.Operand1 as ConstantOperand).Value) {
                case 0: control = ControlRegister.CR0; break;
                case 2: control = ControlRegister.CR2; break;
                case 3: control = ControlRegister.CR3; break;
                case 4: control = ControlRegister.CR4; break;
                default: throw new InvalidOperationException();
            }

            RegisterOperand imm = new RegisterOperand(new SigType(CilElementType.U4), GeneralPurposeRegister.EAX);

            context.SetInstruction(IR.Instruction.MoveInstruction, imm, new RegisterOperand(new SigType(CilElementType.U4), control));
            context.AppendInstruction(IR.Instruction.MoveInstruction, result, imm);
        }
Example #16
0
        /// <summary>
        /// Replaces the instrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem)
        {
            MemoryOperand operand = new MemoryOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Ptr), GeneralPurposeRegister.EAX, new System.IntPtr(0));
            context.SetInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Ptr), GeneralPurposeRegister.EAX), context.Operand1);
            context.AppendInstruction(CPUx86.Instruction.LgdtInstruction, null, operand);

            RegisterOperand ax = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), GeneralPurposeRegister.EAX);
            RegisterOperand ds = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), SegmentRegister.DS);
            RegisterOperand es = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), SegmentRegister.ES);
            RegisterOperand fs = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), SegmentRegister.FS);
            RegisterOperand gs = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), SegmentRegister.GS);
            RegisterOperand ss = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), SegmentRegister.SS);

            context.AppendInstruction(CPUx86.Instruction.MovInstruction, ax, new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I4), (int)0x00000010));
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, ds, ax);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, es, ax);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, fs, ax);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, gs, ax);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, ss, ax);
            context.AppendInstruction(CPUx86.Instruction.FarJmpInstruction);
            context.AppendInstruction(CPUx86.Instruction.NopInstruction);
            context.Previous.SetBranch(context.Offset);
        }
        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>
 /// Spills the given register to its source operand.
 /// </summary>
 /// <param name="ctx">The context.</param>
 /// <param name="op">The operand to spill to.</param>
 /// <param name="rop">The register operand to spill.</param>
 private void SpillRegister(Context ctx, Operand op, RegisterOperand rop)
 {
     // Set the operand in the active operands list
     int regIdx = rop.Register.Index;
     Debug.Assert(_activeOperands[regIdx].Equals(op), @"Register assigned to another operand?");
     InsertMove(ctx, op, rop);
     _activeOperands[regIdx] = null;
     _activeOpLastUse[regIdx] = null;
 }
        /// <summary>
        /// Spills a register from the given register set.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="type">The signature type of the resulting operand.</param>
        /// <param name="regs">The instruction compatible subset of the register set.</param>
        /// <returns>A register From the given set.</returns>
        private RegisterOperand SpillRegister(Context ctx, SigType type, Register[] regs)
        {
            // FIXME: Find the oldest reg from the set. Always use the oldest one.

            KeyValuePair<Register, Context>[] lastUses = new KeyValuePair<Register, Context>[regs.Length];

            int i = 0;
            foreach (Register reg in regs)
                lastUses[i++] = new KeyValuePair<Register, Context>(reg, _activeOpLastUse[reg.Index]);

            // Sort the last uses from oldest -> newest
            Array.Sort<KeyValuePair<Register, Context>>(lastUses, delegate(KeyValuePair<Register, Context> a, KeyValuePair<Register, Context> b)
            {
                return b.Value.Offset - a.Value.Offset;
            });

            // Spill the oldest entry (first index)
            KeyValuePair<Register, Context> lastUse = lastUses[0];
            Operand dest = _activeOperands[lastUse.Key.Index];
            RegisterOperand src = new RegisterOperand(dest.Type, lastUse.Key);
            SpillRegister(lastUse.Value, dest, src);

            return new RegisterOperand(type, lastUse.Key);
        }
 /// <summary>
 /// Assigns the operand to the register.
 /// </summary>
 /// <param name="rop">The register operand containing the register to assign.</param>
 /// <param name="op">The operand assigned to the register.</param>
 /// <param name="ctx">The context.</param>
 private void AssignRegister(RegisterOperand rop, Operand op, Context ctx)
 {
     // Set the operand in the active operands list
     int regIdx = rop.Register.Index;
     Debug.Assert(_activeOperands[regIdx] == null, @"Register not free.");
     _activeOperands[regIdx] = op;
     _activeOpLastUse[regIdx] = ctx;
 }
        /// <summary>
        /// Expands the urem instruction.
        /// </summary>
        /// <param name="context">The context.</param>
        private void ExpandURem(Context context)
        {
            SigType U4 = new SigType(CilElementType.U4);
            SigType U1 = new SigType(CilElementType.U1);

            Operand op0H, op1H, op2H, op0L, op1L, op2L;
            SplitLongOperand(context.Result, out op0L, out op0H);
            SplitLongOperand(context.Operand1, out op1L, out op1H);
            SplitLongOperand(context.Operand2, out op2L, out op2H);
            RegisterOperand eax = new RegisterOperand(U4, GeneralPurposeRegister.EAX);
            RegisterOperand ebx = new RegisterOperand(U4, GeneralPurposeRegister.EBX);
            RegisterOperand edx = new RegisterOperand(U4, GeneralPurposeRegister.EDX);
            RegisterOperand ecx = new RegisterOperand(U4, GeneralPurposeRegister.ECX);
            RegisterOperand edi = new RegisterOperand(U4, GeneralPurposeRegister.EDI);
            RegisterOperand esi = new RegisterOperand(U4, GeneralPurposeRegister.ESI);

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

            // Determine sign of the result (edi = 0 if result is positive, non-zero
            // otherwise) and make operands positive.
            //    xor     edi,edi         ; result sign assumed positive
            //mov     eax,HIWORD(DVND) ; hi word of a
            //or      eax,eax         ; test to see if signed
            //jge     short L1        ; skip rest if a is already positive
            //inc     edi             ; complement result sign flag bit
            //mov     edx,LOWORD(DVND) ; lo word of a
            //neg     eax             ; make a positive
            //neg     edx
            //sbb     eax,0
            //mov     HIWORD(DVND),eax ; save positive value
            //mov     LOWORD(DVND),edx
            context.SetInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[0].BasicBlock);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.PushInstruction, null, edi);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.PushInstruction, null, esi);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.PushInstruction, null, ebx);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op2H);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.OrInstruction, eax, eax);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.NotEqual, newBlocks[2].BasicBlock);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[1].BasicBlock);
            LinkBlocks(newBlocks[0], newBlocks[2], newBlocks[1]);

            newBlocks[1].AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, op2L);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op1H);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.XorInstruction, edx, edx);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.DirectDivisionInstruction, eax, ecx);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op1L);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.DirectDivisionInstruction, eax, ecx);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, edx);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.XorInstruction, edx, edx);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[10].BasicBlock);
            LinkBlocks(newBlocks[1], newBlocks[10]);

            // L1:
            newBlocks[2].AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, eax);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.MovInstruction, ebx, op2L);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.MovInstruction, edx, op1H);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op1L);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[3].BasicBlock);
            LinkBlocks(newBlocks[2], newBlocks[3]);

            // L3:
            newBlocks[3].AppendInstruction(CPUx86.Instruction.ShrInstruction, ecx, new ConstantOperand(U1, 1));
            newBlocks[3].AppendInstruction(CPUx86.Instruction.RcrInstruction, ebx, new ConstantOperand(U1, 1)); // RCR
            newBlocks[3].AppendInstruction(CPUx86.Instruction.ShrInstruction, edx, new ConstantOperand(U1, 1));
            newBlocks[3].AppendInstruction(CPUx86.Instruction.RcrInstruction, eax, new ConstantOperand(U1, 1));
            newBlocks[3].AppendInstruction(CPUx86.Instruction.OrInstruction, ecx, ecx);
            newBlocks[3].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.NotEqual, newBlocks[3].BasicBlock);
            newBlocks[3].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[4].BasicBlock);
            LinkBlocks(newBlocks[3], newBlocks[3], newBlocks[4]);

            newBlocks[4].AppendInstruction(CPUx86.Instruction.DirectDivisionInstruction, eax, ebx);
            newBlocks[4].AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, eax);
            newBlocks[4].AppendInstruction(CPUx86.Instruction.MulInstruction, null, op2H);
            newBlocks[4].AppendInstruction(CPUx86.Instruction.XchgInstruction, ecx, eax);
            newBlocks[4].AppendInstruction(CPUx86.Instruction.MulInstruction, null, op2L);
            newBlocks[4].AppendInstruction(CPUx86.Instruction.AddInstruction, edx, ecx);
            newBlocks[4].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.UnsignedLessThan, newBlocks[8].BasicBlock);
            newBlocks[4].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[5].BasicBlock);
            LinkBlocks(newBlocks[4], newBlocks[8], newBlocks[5]);

            newBlocks[5].AppendInstruction(CPUx86.Instruction.DirectCompareInstruction, edx, op1H);
            newBlocks[5].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.UnsignedGreaterThan, newBlocks[8].BasicBlock);
            newBlocks[5].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[6].BasicBlock);
            LinkBlocks(newBlocks[5], newBlocks[8], newBlocks[6]);

            newBlocks[6].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.UnsignedLessThan, newBlocks[9].BasicBlock);
            newBlocks[6].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[7].BasicBlock);
            LinkBlocks(newBlocks[6], newBlocks[6], newBlocks[7]);

            newBlocks[7].AppendInstruction(CPUx86.Instruction.DirectCompareInstruction, eax, op1L);
            newBlocks[7].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.UnsignedLessOrEqual, newBlocks[9].BasicBlock);
            newBlocks[7].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[3].BasicBlock);
            LinkBlocks(newBlocks[7], newBlocks[9], newBlocks[3]);

            // L4:
            newBlocks[8].AppendInstruction(CPUx86.Instruction.SubInstruction, eax, op2L);
            newBlocks[8].AppendInstruction(CPUx86.Instruction.SbbInstruction, edx, op2H);
            newBlocks[8].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[9].BasicBlock);
            LinkBlocks(newBlocks[8], newBlocks[9]);

            // L5:
            newBlocks[9].AppendInstruction(CPUx86.Instruction.SubInstruction, eax, op1L);
            newBlocks[9].AppendInstruction(CPUx86.Instruction.SbbInstruction, edx, op1H);
            newBlocks[9].AppendInstruction(CPUx86.Instruction.NegInstruction, edx);
            newBlocks[9].AppendInstruction(CPUx86.Instruction.NegInstruction, eax);
            newBlocks[9].AppendInstruction(CPUx86.Instruction.SbbInstruction, edx, new ConstantOperand(U4, (int)0));
            newBlocks[9].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[10].BasicBlock);
            LinkBlocks(newBlocks[9], newBlocks[10]);

            newBlocks[10].SetInstruction(CPUx86.Instruction.MovInstruction, op0L, eax);
            newBlocks[10].AppendInstruction(CPUx86.Instruction.MovInstruction, op0H, edx);
            newBlocks[10].AppendInstruction(CPUx86.Instruction.PopInstruction, ebx);
            newBlocks[10].AppendInstruction(CPUx86.Instruction.PopInstruction, esi);
            newBlocks[10].AppendInstruction(CPUx86.Instruction.PopInstruction, edi);
            newBlocks[10].AppendInstruction(CPUx86.Instruction.JmpInstruction, nextBlock.BasicBlock);
            LinkBlocks(newBlocks[10], nextBlock);
        }
        /// <summary>
        /// Expands the unsigned move instruction for 64-bits.
        /// </summary>
        /// <param name="context">The context.</param>
        private void ExpandUnsignedMove(Context context)
        {
            MemoryOperand op0 = context.Result as MemoryOperand;
            Operand op1 = context.Operand1;
            Debug.Assert(op0 != null, @"I8 not in a memory operand!");

            SigType U4 = new SigType(CilElementType.U4);
            Operand op0L, op0H, op1L, op1H;
            SplitLongOperand(op0, out op0L, out op0H);
            SplitLongOperand(op1, out op1L, out op1H);
            RegisterOperand eax = new RegisterOperand(U4, GeneralPurposeRegister.EAX);
            RegisterOperand edx = new RegisterOperand(U4, GeneralPurposeRegister.EDX);

            switch (op1.Type.Type)
            {
                case CilElementType.Boolean:
                    context.SetInstruction(IR.Instruction.ZeroExtendedMoveInstruction, op0L, op1L);
                    context.AppendInstruction(IR.Instruction.LogicalXorInstruction, op0H, op0H, op0H);
                    break;

                case CilElementType.U1:
                    context.SetInstruction(IR.Instruction.ZeroExtendedMoveInstruction, eax, op1L);
                    context.AppendInstruction(CPUx86.Instruction.CdqInstruction);
                    context.AppendInstruction(CPUx86.Instruction.MovInstruction, op0L, eax);
                    context.AppendInstruction(IR.Instruction.LogicalXorInstruction, op0H, op0H, op0H);
                    break;

                case CilElementType.U2: goto case CilElementType.U1;

                case CilElementType.I4:
                    context.SetInstruction(IR.Instruction.ZeroExtendedMoveInstruction, eax, op1L);
                    context.AppendInstruction(CPUx86.Instruction.XorInstruction, edx, edx);
                    context.AppendInstruction(CPUx86.Instruction.MovInstruction, op0L, eax);
                    context.AppendInstruction(CPUx86.Instruction.MovInstruction, op0H, edx);
                    break;
                case CilElementType.U4:
                    context.SetInstruction(IR.Instruction.ZeroExtendedMoveInstruction, eax, op1L);
                    context.AppendInstruction(CPUx86.Instruction.CdqInstruction);
                    context.AppendInstruction(CPUx86.Instruction.MovInstruction, op0L, eax);
                    context.AppendInstruction(CPUx86.Instruction.MovInstruction, op0H, edx);
                    break;

                case CilElementType.U8:
                    context.SetInstruction(IR.Instruction.ZeroExtendedMoveInstruction, op0L, op1L);
                    context.SetInstruction(IR.Instruction.ZeroExtendedMoveInstruction, op0H, op1H);
                    break;

                case CilElementType.R4:
                    throw new NotSupportedException();

                case CilElementType.R8:
                    throw new NotSupportedException();

                default:
                    throw new NotSupportedException();
            }
        }
        /// <summary>
        /// Expands the udiv instruction.
        /// </summary>
        /// <param name="context">The context.</param>
        private void ExpandUDiv(Context context)
        {
            SigType U4 = new SigType(CilElementType.U4);
            SigType U1 = new SigType(CilElementType.U1);

            Operand op0H, op1H, op2H, op0L, op1L, op2L;
            SplitLongOperand(context.Result, out op0L, out op0H);
            SplitLongOperand(context.Operand1, out op1L, out op1H);
            SplitLongOperand(context.Operand2, out op2L, out op2H);
            RegisterOperand eax = new RegisterOperand(U4, GeneralPurposeRegister.EAX);
            RegisterOperand ebx = new RegisterOperand(U4, GeneralPurposeRegister.EBX);
            RegisterOperand edx = new RegisterOperand(U4, GeneralPurposeRegister.EDX);
            RegisterOperand ecx = new RegisterOperand(U4, GeneralPurposeRegister.ECX);
            RegisterOperand edi = new RegisterOperand(U4, GeneralPurposeRegister.EDI);
            RegisterOperand esi = new RegisterOperand(U4, GeneralPurposeRegister.ESI);

            Context[] newBlocks = CreateEmptyBlockContexts(context.Label, 12);
            Context nextBlock = SplitContext(context, false);
            context.SetInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[0].BasicBlock);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.PushInstruction, null, edi);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.PushInstruction, null, esi);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.PushInstruction, null, ebx);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op2H);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.OrInstruction, eax, eax);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.NotEqual, newBlocks[2].BasicBlock); // JNZ
            newBlocks[0].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[1].BasicBlock);
            LinkBlocks(newBlocks[0], newBlocks[2], newBlocks[1]);

            newBlocks[1].AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, op2L);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op1H);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.XorInstruction, edx, edx);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.DirectDivisionInstruction, eax, ecx);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.MovInstruction, ebx, eax);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op1L);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.DirectDivisionInstruction, eax, ecx);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.MovInstruction, edx, ebx);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[10].BasicBlock);
            LinkBlocks(newBlocks[0], newBlocks[10]);

            // L1
            newBlocks[2].AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, eax);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.MovInstruction, ebx, op2L);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.MovInstruction, edx, op1H);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op1L);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[3].BasicBlock);
            LinkBlocks(newBlocks[2], newBlocks[3]);

            // L3
            newBlocks[3].AppendInstruction(CPUx86.Instruction.ShrInstruction, ecx, new ConstantOperand(U1, 1));
            newBlocks[3].AppendInstruction(CPUx86.Instruction.RcrInstruction, ebx, new ConstantOperand(U1, 1)); // RCR
            newBlocks[3].AppendInstruction(CPUx86.Instruction.ShrInstruction, edx, new ConstantOperand(U1, 1));
            newBlocks[3].AppendInstruction(CPUx86.Instruction.RcrInstruction, eax, new ConstantOperand(U1, 1));
            newBlocks[3].AppendInstruction(CPUx86.Instruction.OrInstruction, ecx, ecx);
            newBlocks[3].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.NotEqual, newBlocks[3].BasicBlock); // JNZ
            newBlocks[3].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[4].BasicBlock);
            LinkBlocks(newBlocks[3], newBlocks[3], newBlocks[4]);

            newBlocks[4].AppendInstruction(CPUx86.Instruction.DirectDivisionInstruction, eax, ebx);
            newBlocks[4].AppendInstruction(CPUx86.Instruction.MovInstruction, esi, eax);
            newBlocks[4].AppendInstruction(CPUx86.Instruction.MulInstruction, null, op2H);
            newBlocks[4].AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, eax);
            newBlocks[4].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op2L);
            newBlocks[4].AppendInstruction(CPUx86.Instruction.MulInstruction, null, esi);
            newBlocks[4].AppendInstruction(CPUx86.Instruction.AddInstruction, edx, ecx);
            newBlocks[4].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.UnsignedLessThan, newBlocks[8].BasicBlock);
            newBlocks[4].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[5].BasicBlock);
            LinkBlocks(newBlocks[4], newBlocks[8], newBlocks[5]);

            newBlocks[5].AppendInstruction(CPUx86.Instruction.DirectCompareInstruction, edx, op1H);
            newBlocks[5].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.UnsignedGreaterThan, newBlocks[8].BasicBlock);
            newBlocks[5].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[6].BasicBlock);
            LinkBlocks(newBlocks[5], newBlocks[8], newBlocks[6]);

            newBlocks[6].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.UnsignedLessThan, newBlocks[9].BasicBlock);
            newBlocks[6].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[7].BasicBlock);
            LinkBlocks(newBlocks[6], newBlocks[9], newBlocks[7]);

            newBlocks[7].AppendInstruction(CPUx86.Instruction.DirectCompareInstruction, eax, op1L);
            newBlocks[7].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.UnsignedLessOrEqual, newBlocks[9].BasicBlock);
            newBlocks[7].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[8].BasicBlock);
            LinkBlocks(newBlocks[7], newBlocks[9], newBlocks[8]);

            // L4:
            newBlocks[8].AppendInstruction(CPUx86.Instruction.DecInstruction, esi);
            newBlocks[8].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[9].BasicBlock);
            LinkBlocks(newBlocks[8], newBlocks[9]);

            // L5
            newBlocks[9].AppendInstruction(CPUx86.Instruction.XorInstruction, edx, edx);
            newBlocks[9].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, esi);
            newBlocks[9].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[10].BasicBlock);
            LinkBlocks(newBlocks[9], newBlocks[10]);

            // L2
            newBlocks[10].SetInstruction(CPUx86.Instruction.MovInstruction, op0L, eax);
            newBlocks[10].AppendInstruction(CPUx86.Instruction.MovInstruction, op0H, edx);
            newBlocks[10].AppendInstruction(CPUx86.Instruction.PopInstruction, ebx);
            newBlocks[10].AppendInstruction(CPUx86.Instruction.PopInstruction, esi);
            newBlocks[10].AppendInstruction(CPUx86.Instruction.PopInstruction, edi);
            newBlocks[10].AppendInstruction(CPUx86.Instruction.JmpInstruction, nextBlock.BasicBlock);
            LinkBlocks(newBlocks[10], nextBlock);
        }
        /// <summary>
        /// Expands the store instruction for 64-bits.
        /// </summary>
        /// <param name="context">The context.</param>
        private void ExpandStore(Context context)
        {
            MemoryOperand op0 = context.Result as MemoryOperand;
            Operand offsetOperand = context.Operand1;
            MemoryOperand op2 = context.Operand2 as MemoryOperand;
            Debug.Assert(op0 != null && op2 != null, @"Operands to I8 LoadInstruction are not MemoryOperand.");

            SigType I4 = new SigType(CilElementType.I4);
            SigType U4 = new SigType(CilElementType.U4);
            Operand op1L, op1H;
            SplitLongOperand(op2, out op1L, out op1H);
            RegisterOperand eax = new RegisterOperand(I4, GeneralPurposeRegister.EAX);
            RegisterOperand edx = new RegisterOperand(I4, GeneralPurposeRegister.EDX);

            context.SetInstruction(CPUx86.Instruction.MovInstruction, edx, op0);

            // Fortunately in 32-bit mode, we can't have 64-bit offsets, so this plain add should suffice.
            context.AppendInstruction(CPUx86.Instruction.AddInstruction, edx, offsetOperand);

            context.AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op1L);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, new MemoryOperand(U4, GeneralPurposeRegister.EDX, IntPtr.Zero), eax);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op1H);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, new MemoryOperand(I4, GeneralPurposeRegister.EDX, new IntPtr(4)), eax);
        }
        /// <summary>
        /// Expands the shift right instruction for 64-bits.
        /// </summary>
        /// <param name="context">The context.</param>
        private void ExpandShiftRight(Context context)
        {
            SigType I4 = new SigType(CilElementType.I4);
            SigType I1 = new SigType(CilElementType.I1);
            SigType U1 = new SigType(CilElementType.U1);
            Operand count = context.Operand2;

            Operand op0H, op1H, op0L, op1L;
            SplitLongOperand(context.Operand1, out op0L, out op0H);
            SplitLongOperand(context.Operand2, out op1L, out op1H);
            RegisterOperand eax = new RegisterOperand(I4, GeneralPurposeRegister.EAX);
            RegisterOperand edx = new RegisterOperand(I4, GeneralPurposeRegister.EDX);
            RegisterOperand ecx = new RegisterOperand(U1, GeneralPurposeRegister.ECX);

            //UNUSED:
            //RegisterOperand cl = new RegisterOperand(new SigType(CilElementType.U1), GeneralPurposeRegister.ECX);

            Context[] newBlocks = CreateEmptyBlockContexts(context.Label, 6);
            Context nextBlock = SplitContext(context, true);

            // Handle shifts of 64 bits or more (if shifting 64 bits or more, the result
            // depends only on the high order bit of edx).
            context.SetInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[0].BasicBlock);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.PushInstruction, null, ecx);
            newBlocks[0].AppendInstruction(IR.Instruction.LogicalAndInstruction, count, count, new ConstantOperand(I4, 0x3F));
            newBlocks[0].AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, count);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.MovInstruction, edx, op1H);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op1L);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.CmpInstruction, ecx, new ConstantOperand(I4, 64));
            newBlocks[0].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.UnsignedGreaterOrEqual, newBlocks[4].BasicBlock);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[1].BasicBlock);
            LinkBlocks(newBlocks[0], newBlocks[4], newBlocks[1]);

            newBlocks[1].AppendInstruction(CPUx86.Instruction.CmpInstruction, ecx, new ConstantOperand(I4, 32));
            newBlocks[1].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.UnsignedGreaterOrEqual, newBlocks[3].BasicBlock);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[2].BasicBlock);
            LinkBlocks(newBlocks[3], newBlocks[2], newBlocks[1]);

            newBlocks[2].AppendInstruction(CPUx86.Instruction.ShrdInstruction, eax, edx, ecx);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.SarInstruction, edx, ecx);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[5].BasicBlock);
            LinkBlocks(newBlocks[2], newBlocks[5]);

            // Handle shifts of between 32 and 63 bits
            // MORE32:
            newBlocks[3].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, edx);
            newBlocks[3].AppendInstruction(CPUx86.Instruction.PushInstruction, null, ecx);
            newBlocks[3].AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, new ConstantOperand(I1, (sbyte)0x1F));
            newBlocks[3].AppendInstruction(CPUx86.Instruction.SarInstruction, edx, ecx);
            newBlocks[3].AppendInstruction(CPUx86.Instruction.PopInstruction, ecx);
            newBlocks[3].AppendInstruction(CPUx86.Instruction.AndInstruction, ecx, new ConstantOperand(I4, 0x1F));
            newBlocks[3].AppendInstruction(CPUx86.Instruction.PushInstruction, null, ecx);
            newBlocks[3].AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, new ConstantOperand(I1, (sbyte)0x1F));
            newBlocks[3].AppendInstruction(CPUx86.Instruction.SarInstruction, eax, ecx);
            newBlocks[3].AppendInstruction(CPUx86.Instruction.PopInstruction, ecx);
            newBlocks[3].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[5].BasicBlock);
            LinkBlocks(newBlocks[3], newBlocks[5]);

            // Return double precision 0 or -1, depending on the sign of edx
            // RETSIGN:
            newBlocks[4].AppendInstruction(CPUx86.Instruction.SarInstruction, edx, new ConstantOperand(I1, (sbyte)0x1F));
            newBlocks[4].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, edx);
            newBlocks[4].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[5].BasicBlock);
            LinkBlocks(newBlocks[4], newBlocks[5]);

            // done:
            // ; remaining code from current basic block
            newBlocks[5].SetInstruction(CPUx86.Instruction.MovInstruction, op0H, edx);
            newBlocks[5].AppendInstruction(CPUx86.Instruction.MovInstruction, op0L, eax);
            newBlocks[5].AppendInstruction(CPUx86.Instruction.PopInstruction, ecx);
            newBlocks[5].AppendInstruction(CPUx86.Instruction.JmpInstruction, nextBlock.BasicBlock);
            LinkBlocks(newBlocks[5], nextBlock);
        }
        /// <summary>
        /// Expands the rem.
        /// </summary>
        /// <param name="context">The context.</param>
        private void ExpandRem(Context context)
        {
            SigType I4 = new SigType(CilElementType.I4);
            SigType U1 = new SigType(CilElementType.U1);

            Operand op0H, op1H, op2H, op0L, op1L, op2L;
            SplitLongOperand(context.Result, out op0L, out op0H);
            SplitLongOperand(context.Operand1, out op1L, out op1H);
            SplitLongOperand(context.Operand2, out op2L, out op2H);
            RegisterOperand eax = new RegisterOperand(I4, GeneralPurposeRegister.EAX);
            RegisterOperand ebx = new RegisterOperand(I4, GeneralPurposeRegister.EBX);
            RegisterOperand edx = new RegisterOperand(I4, GeneralPurposeRegister.EDX);
            RegisterOperand ecx = new RegisterOperand(I4, GeneralPurposeRegister.ECX);
            RegisterOperand edi = new RegisterOperand(I4, GeneralPurposeRegister.EDI);
            RegisterOperand esi = new RegisterOperand(I4, GeneralPurposeRegister.ESI);

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

            // Determine sign of the result (edi = 0 if result is positive, non-zero
            // otherwise) and make operands positive.
            //    xor     edi,edi         ; result sign assumed positive
            //mov     eax,HIWORD(DVND) ; hi word of a
            //or      eax,eax         ; test to see if signed
            //jge     short L1        ; skip rest if a is already positive
            //inc     edi             ; complement result sign flag bit
            //mov     edx,LOWORD(DVND) ; lo word of a
            //neg     eax             ; make a positive
            //neg     edx
            //sbb     eax,0
            //mov     HIWORD(DVND),eax ; save positive value
            //mov     LOWORD(DVND),edx
            context.SetInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[0].BasicBlock);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.PushInstruction, null, edi);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.PushInstruction, null, esi);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.PushInstruction, null, ebx);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.XorInstruction, edi, edi);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op1H);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.OrInstruction, eax, eax);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.GreaterOrEqual, newBlocks[2].BasicBlock);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[1].BasicBlock);
            LinkBlocks(newBlocks[0], newBlocks[2], newBlocks[1]);

            newBlocks[1].AppendInstruction(CPUx86.Instruction.IncInstruction, edi);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.MovInstruction, edx, op1L);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.NegInstruction, eax);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.NegInstruction, edx);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.SbbInstruction, eax, new ConstantOperand(I4, 0));
            newBlocks[1].AppendInstruction(CPUx86.Instruction.MovInstruction, op1H, eax);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.MovInstruction, op1L, edx);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[2].BasicBlock);
            LinkBlocks(newBlocks[1], newBlocks[2]);

            // L1:
            //
            // mov     eax,HIWORD(DVSR) ; hi word of b
            // or      eax,eax         ; test to see if signed
            // jge     short L2        ; skip rest if b is already positive
            // mov     edx,LOWORD(DVSR) ; lo word of b
            // neg     eax             ; make b positive
            // neg     edx
            // sbb     eax,0
            // mov     HIWORD(DVSR),eax ; save positive value
            // mov     LOWORD(DVSR),edx
            newBlocks[2].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op2H);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.OrInstruction, eax, eax);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.GreaterOrEqual, newBlocks[4].BasicBlock);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[3].BasicBlock);
            LinkBlocks(newBlocks[2], newBlocks[4], newBlocks[3]);

            newBlocks[3].AppendInstruction(CPUx86.Instruction.MovInstruction, edx, op2L);
            newBlocks[3].AppendInstruction(CPUx86.Instruction.NegInstruction, eax);
            newBlocks[3].AppendInstruction(CPUx86.Instruction.NegInstruction, edx);
            newBlocks[3].AppendInstruction(CPUx86.Instruction.SbbInstruction, eax, new ConstantOperand(I4, 0));
            newBlocks[3].AppendInstruction(CPUx86.Instruction.MovInstruction, op2H, eax);
            newBlocks[3].AppendInstruction(CPUx86.Instruction.MovInstruction, op2L, edx);
            newBlocks[3].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[4].BasicBlock);
            LinkBlocks(newBlocks[3], newBlocks[4]);

            // L2:
            //
            //
            // Now do the divide.  First look to see if the divisor is less than 4194304K.
            // If so, then we can use a simple algorithm with word divides, otherwise
            // things get a little more complex.
            //
            // NOTE - eax currently contains the high order word of DVSR
            //
            //
            // or      eax,eax         ; check to see if divisor < 4194304K
            // jnz     short L3        ; nope, gotta do this the hard way
            // mov     ecx,LOWORD(DVSR) ; load divisor
            // mov     eax,HIWORD(DVND) ; load high word of dividend
            // xor     edx,edx
            // div     ecx             ; eax <- high order bits of quotient
            // mov     eax,LOWORD(DVND) ; edx:eax <- remainder:lo word of dividend
            // div     ecx             ; eax <- low order bits of quotient
            // mov     edx,ebx         ; edx:eax <- quotient
            // jmp     short L4        ; set sign, restore stack and return
            newBlocks[4].AppendInstruction(CPUx86.Instruction.OrInstruction, eax, eax);
            newBlocks[4].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.NotEqual, newBlocks[6].BasicBlock);
            newBlocks[4].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[5].BasicBlock);
            LinkBlocks(newBlocks[4], newBlocks[6], newBlocks[5]);

            newBlocks[5].AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, op2L);
            newBlocks[5].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op1H);
            newBlocks[5].AppendInstruction(CPUx86.Instruction.XorInstruction, edx, edx);
            newBlocks[5].AppendInstruction(CPUx86.Instruction.DirectDivisionInstruction, eax, ecx);
            newBlocks[5].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op1L);
            newBlocks[5].AppendInstruction(CPUx86.Instruction.DirectDivisionInstruction, eax, ecx);
            newBlocks[5].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, edx);
            newBlocks[5].AppendInstruction(CPUx86.Instruction.XorInstruction, edx, edx);
            newBlocks[5].AppendInstruction(CPUx86.Instruction.DecInstruction, edi);
            newBlocks[5].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.NotSigned, newBlocks[14].BasicBlock);
            newBlocks[5].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[15].BasicBlock);
            LinkBlocks(newBlocks[5], newBlocks[14], newBlocks[15]);

            // Here we do it the hard way.  Remember, eax contains the high word of DVSR
            //
            // L3:
            //        mov     ebx,eax         ; ebx:ecx <- divisor
            //        mov     ecx,LOWORD(DVSR)
            //        mov     edx,HIWORD(DVND) ; edx:eax <- dividend
            //        mov     eax,LOWORD(DVND)
            newBlocks[6].AppendInstruction(CPUx86.Instruction.MovInstruction, ebx, eax);
            newBlocks[6].AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, op2L);
            newBlocks[6].AppendInstruction(CPUx86.Instruction.MovInstruction, edx, op1H);
            newBlocks[6].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op1L);
            newBlocks[6].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[7].BasicBlock);
            LinkBlocks(newBlocks[6], newBlocks[7]);

            // L5:
            //
            //  shr     ebx,1           ; shift divisor right one bit
            //  rcr     ecx,1
            //  shr     edx,1           ; shift dividend right one bit
            //  rcr     eax,1
            //  or      ebx,ebx
            //  jnz     short L5        ; loop until divisor < 4194304K
            //  div     ecx             ; now divide, ignore remainder

            //
            // We may be off by one, so to check, we will multiply the quotient
            // by the divisor and check the result against the orignal dividend
            // Note that we must also check for overflow, which can occur if the
            // dividend is close to 2**64 and the quotient is off by 1.
            //

            //  mov     ecx,eax         ; save a copy of quotient in ECX
            //  mul     dword ptr HIWORD(DVSR)
            //  xchg    ecx,eax         ; save product, get quotient in EAX
            //  mul     dword ptr LOWORD(DVSR)
            //  add     edx,ecx         ; EDX:EAX = QUOT * DVSR
            //  jc      short L6        ; carry means Quotient is off by 1

            //
            // do long compare here between original dividend and the result of the
            // multiply in edx:eax.  If original is larger or equal, we are ok, otherwise
            // subtract the original divisor from the result.
            //

            //  cmp     edx,HIWORD(DVND) ; compare hi words of result and original
            //  ja      short L6        ; if result > original, do subtract
            //  jb      short L7        ; if result < original, we are ok
            //  cmp     eax,LOWORD(DVND) ; hi words are equal, compare lo words
            //  jbe     short L7        ; if less or equal we are ok, else subtract

            newBlocks[7].AppendInstruction(CPUx86.Instruction.ShrInstruction, ebx, new ConstantOperand(U1, 1));
            newBlocks[7].AppendInstruction(CPUx86.Instruction.RcrInstruction, ecx, new ConstantOperand(U1, 1)); // RCR
            newBlocks[7].AppendInstruction(CPUx86.Instruction.ShrInstruction, edx, new ConstantOperand(U1, 1));
            newBlocks[7].AppendInstruction(CPUx86.Instruction.RcrInstruction, eax, new ConstantOperand(U1, 1));
            newBlocks[7].AppendInstruction(CPUx86.Instruction.OrInstruction, ebx, ebx);
            newBlocks[7].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.NotEqual, newBlocks[7].BasicBlock);
            newBlocks[7].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[8].BasicBlock);
            LinkBlocks(newBlocks[7], newBlocks[7], newBlocks[8]);

            newBlocks[8].AppendInstruction(CPUx86.Instruction.DirectDivisionInstruction, eax, ecx);
            newBlocks[8].AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, eax);
            newBlocks[8].AppendInstruction(CPUx86.Instruction.MulInstruction, null, op2H);
            newBlocks[8].AppendInstruction(CPUx86.Instruction.XchgInstruction, ecx, eax);
            newBlocks[8].AppendInstruction(CPUx86.Instruction.MulInstruction, null, op2L);
            newBlocks[8].AppendInstruction(CPUx86.Instruction.AddInstruction, edx, ecx);
            newBlocks[8].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.UnsignedLessThan, newBlocks[12].BasicBlock);
            newBlocks[8].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[9].BasicBlock);
            LinkBlocks(newBlocks[8], newBlocks[12], newBlocks[9]);

            newBlocks[9].AppendInstruction(CPUx86.Instruction.DirectCompareInstruction, edx, op1H);
            newBlocks[9].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.UnsignedGreaterThan, newBlocks[12].BasicBlock);
            newBlocks[9].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[10].BasicBlock);
            LinkBlocks(newBlocks[9], newBlocks[12], newBlocks[10]);

            newBlocks[10].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.UnsignedLessThan, newBlocks[13].BasicBlock);
            newBlocks[10].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[11].BasicBlock);
            LinkBlocks(newBlocks[10], newBlocks[13], newBlocks[11]);

            newBlocks[11].AppendInstruction(CPUx86.Instruction.DirectCompareInstruction, eax, op1L);
            newBlocks[11].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.UnsignedLessOrEqual, newBlocks[13].BasicBlock);
            newBlocks[11].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[12].BasicBlock);
            LinkBlocks(newBlocks[11], newBlocks[13], newBlocks[12]);

            // L6:
            newBlocks[12].AppendInstruction(CPUx86.Instruction.SubInstruction, eax, op2L);
            newBlocks[12].AppendInstruction(CPUx86.Instruction.SbbInstruction, edx, op2H);
            newBlocks[12].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[13].BasicBlock);
            LinkBlocks(newBlocks[13], newBlocks[13]);

            // L7:
            //
            // Calculate remainder by subtracting the result from the original dividend.
            // Since the result is already in a register, we will do the subtract in the
            // opposite direction and negate the result if necessary.
            //
            newBlocks[13].AppendInstruction(CPUx86.Instruction.SubInstruction, eax, op1L);
            newBlocks[13].AppendInstruction(CPUx86.Instruction.SbbInstruction, edx, op1H);
            newBlocks[13].AppendInstruction(CPUx86.Instruction.DecInstruction, edi);
            newBlocks[13].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.NotSigned, newBlocks[15].BasicBlock);
            newBlocks[13].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[14].BasicBlock);
            LinkBlocks(newBlocks[13], newBlocks[14], newBlocks[15]);

            // L4:
            //        neg     edx             ; otherwise, negate the result
            //        neg     eax
            //        sbb     edx,0
            newBlocks[14].AppendInstruction(CPUx86.Instruction.NegInstruction, edx);
            newBlocks[14].AppendInstruction(CPUx86.Instruction.NegInstruction, eax);
            newBlocks[14].AppendInstruction(CPUx86.Instruction.SbbInstruction, edx, new ConstantOperand(I4, 0));
            newBlocks[14].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[15].BasicBlock);
            LinkBlocks(newBlocks[14], newBlocks[15]);

            newBlocks[15].SetInstruction(CPUx86.Instruction.MovInstruction, op0L, eax);
            newBlocks[15].AppendInstruction(CPUx86.Instruction.MovInstruction, op0H, edx);
            newBlocks[15].AppendInstruction(CPUx86.Instruction.PopInstruction, ebx);
            newBlocks[15].AppendInstruction(CPUx86.Instruction.PopInstruction, esi);
            newBlocks[15].AppendInstruction(CPUx86.Instruction.PopInstruction, edi);
            newBlocks[15].AppendInstruction(CPUx86.Instruction.JmpInstruction, nextBlock.BasicBlock);
            LinkBlocks(newBlocks[15], nextBlock);
        }
        /// <summary>
        /// Expands the mul instruction for 64-bit operands.
        /// </summary>
        /// <param name="context">The context.</param>
        private void ExpandMul(Context context)
        {
            Operand op0 = context.Result;
            Operand op1 = context.Operand1;
            Operand op2 = context.Operand2;
            Debug.Assert(op0 != null && op1 != null && op2 != null, @"Operands to 64 bit multiplication are not MemoryOperands.");

            SigType I4 = new SigType(CilElementType.I4);
            Operand op0H, op1H, op2H, op0L, op1L, op2L;
            SplitLongOperand(context.Result, out op0L, out op0H);
            SplitLongOperand(context.Operand1, out op1L, out op1H);
            SplitLongOperand(context.Operand2, out op2L, out op2H);

            RegisterOperand eax = new RegisterOperand(I4, GeneralPurposeRegister.EAX);
            RegisterOperand ebx = new RegisterOperand(I4, GeneralPurposeRegister.EBX);
            RegisterOperand ecx = new RegisterOperand(I4, GeneralPurposeRegister.ECX);
            RegisterOperand edx = new RegisterOperand(I4, GeneralPurposeRegister.EDX);

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

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

            newBlocks[0].SetInstruction(CPUx86.Instruction.MovInstruction, eax, op1H);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, op2H);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.OrInstruction, ecx, eax);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, op2L);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.NotEqual, newBlocks[2].BasicBlock);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[1].BasicBlock);
            LinkBlocks(newBlocks[0], newBlocks[1], newBlocks[2]);

            newBlocks[1].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op1L);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.MulInstruction, null, ecx);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[3].BasicBlock);
            LinkBlocks(newBlocks[1], newBlocks[3]);

            newBlocks[2].AppendInstruction(CPUx86.Instruction.PushInstruction, null, ebx);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.MulInstruction, null, ecx);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.MovInstruction, ebx, eax);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op1L);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.MulInstruction, null, op2H);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.AddInstruction, ebx, eax);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op1L);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.MulInstruction, null, ecx);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.AddInstruction, edx, ebx);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.PopInstruction, ebx);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[3].BasicBlock);
            LinkBlocks(newBlocks[2], newBlocks[3]);

            newBlocks[3].AppendInstruction(CPUx86.Instruction.MovInstruction, op0L, eax);
            newBlocks[3].AppendInstruction(CPUx86.Instruction.MovInstruction, op0H, edx);
            newBlocks[3].AppendInstruction(CPUx86.Instruction.JmpInstruction, nextBlock.BasicBlock);
            LinkBlocks(newBlocks[2], nextBlock);
        }
Example #28
0
        /// <summary>
        /// Compares with the given operand for equality.
        /// </summary>
        /// <param name="other">The other operand to compare with.</param>
        /// <returns>The return value is true if the operands are equal; false if not.</returns>
        public override bool Equals(Operand other)
        {
            RegisterOperand rop = other as RegisterOperand;

            return(null != rop && ReferenceEquals(rop.Register, Register));
        }
 /// <summary>
 /// Spills the given register operand, if its register is in use.
 /// </summary>
 /// <param name="ctx">The context.</param>
 /// <param name="rop">The register operand to spill.</param>
 private void SpillRegisterIfInUse(Context ctx, RegisterOperand rop)
 {
     int regIdx = rop.Register.Index;
     Operand op = _activeOperands[regIdx];
     if (op != null) {
         InsertMove(ctx, op, rop);
         _activeOperands[regIdx] = null;
         _activeOpLastUse[regIdx] = null;
     }
 }
        /// <summary>
        /// Expands the load instruction for 64-bits.
        /// </summary>
        /// <param name="context">The context.</param>
        private void ExpandLoad(Context context)
        {
            Operand op0 = context.Result;
            Operand op1 = context.Operand1;
            Operand offsetOperand = context.Operand2;
            Debug.Assert(op0 != null && op1 != null, @"Operands to I8 LoadInstruction are not MemoryOperand.");

            SigType I4 = new SigType(CilElementType.I4);
            Operand op0L, op0H;
            SplitLongOperand(op0, out op0L, out op0H);

            RegisterOperand eax = new RegisterOperand(I4, GeneralPurposeRegister.EAX);
            RegisterOperand edx = new RegisterOperand(I4, GeneralPurposeRegister.EDX);

            context.SetInstruction(CPUx86.Instruction.MovInstruction, eax, op1);
            context.AppendInstruction(CPUx86.Instruction.AddInstruction, eax, offsetOperand);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, edx, new MemoryOperand(op0L.Type, GeneralPurposeRegister.EAX, IntPtr.Zero));
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, op0L, edx);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, edx, new MemoryOperand(op0H.Type, GeneralPurposeRegister.EAX, new IntPtr(4)));
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, op0H, edx);
        }
        /// <summary>
        /// Expands the sub instruction for 64-bit operands.
        /// </summary>
        /// <param name="context">The context.</param>
        private void ExpandSub(Context context)
        {
            /* This function transforms the SUB into the following sequence of x86 instructions:
             *
             * mov eax, [op1]       ; Move lower 32-bits of the first operand into eax
             * sub eax, [op2]       ; Sub lower 32-bits of second operand to eax
             * mov [result], eax    ; Save the result into the lower 32-bits of the result operand
             * mov eax, [op1+4]     ; Move upper 32-bits of the first operand into eax
             * sbb eax, [op2+4]     ; Sub with borrow upper 32-bits of the second operand to eax
             * mov [result+4], eax  ; Save the result into the upper 32-bits of the result operand
             *
             */

            // This only works for memory operands (can't store I8/U8 in a register.)
            // This fails for constant operands right now, which need to be extracted into memory
            // with a literal/literal operand first - TODO
            RegisterOperand eaxH = new RegisterOperand(new SigType(CilElementType.I4), GeneralPurposeRegister.EAX);
            RegisterOperand eaxL = new RegisterOperand(new SigType(CilElementType.U4), GeneralPurposeRegister.EAX);

            Operand op1L, op1H, op2L, op2H, resL, resH;
            SplitLongOperand(context.Operand1, out op1L, out op1H);
            SplitLongOperand(context.Operand2, out op2L, out op2H);
            SplitLongOperand(context.Result, out resL, out resH);

            context.SetInstruction(CPUx86.Instruction.MovInstruction, eaxL, op1L);
            context.AppendInstruction(CPUx86.Instruction.SubInstruction, eaxL, op2L);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, resL, eaxL);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, eaxH, op1H);
            context.AppendInstruction(CPUx86.Instruction.SbbInstruction, eaxH, op2H);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, resH, eaxH);
        }