AppendInstruction2() public méthode

Appends the instruction.
public AppendInstruction2 ( BaseInstruction instruction, Operand result, Operand result2 ) : void
instruction BaseInstruction The instruction.
result Operand The result.
result2 Operand The result2.
Résultat void
        /// <summary>
        /// Visitation function for <see cref="IX86Visitor.Div"/> instructions.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Div(Context context)
        {
            if (context.Result.IsCPURegister && context.Result2.IsCPURegister && context.Operand1.IsCPURegister)
                if (context.Result.Register == GeneralPurposeRegister.EDX &&
                    context.Result2.Register == GeneralPurposeRegister.EAX &&
                    context.Operand1.Register == GeneralPurposeRegister.EDX &&
                    context.Operand2.Register == GeneralPurposeRegister.EAX)
                    return;

            Operand operand1 = context.Operand1;
            Operand operand2 = context.Operand2;
            Operand operand3 = context.Operand3;
            Operand result = context.Result;
            Operand result2 = context.Result2;

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

            context.SetInstruction(X86.Mov, EDX, operand1);
            context.AppendInstruction(X86.Mov, EAX, operand2);

            if (operand3.IsCPURegister)
            {
                context.AppendInstruction2(X86.Div, EDX, EAX, EDX, EAX, operand3);
            }
            else
            {
                Operand v3 = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
                context.AppendInstruction(X86.Mov, v3, operand3);
                context.AppendInstruction2(X86.Div, EDX, EAX, EDX, EAX, v3);
            }

            context.AppendInstruction(X86.Mov, result2, EAX);
            context.AppendInstruction(X86.Mov, result, EDX);
        }
        /// <summary>
        /// Visitation function for <see cref="IX86Visitor.Cdq"/> instructions.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Cdq(Context context)
        {
            if (context.Result.IsCPURegister && context.Result2.IsCPURegister && context.Operand1.IsCPURegister)
                return;

            Operand operand1 = context.Operand1;
            Operand result = context.Result;
            Operand result2 = context.Result2;

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

            context.SetInstruction(X86.Mov, EAX, operand1);
            context.AppendInstruction2(X86.Cdq, EDX, EAX, EAX);
            context.AppendInstruction(X86.Mov, result, EDX);
            context.AppendInstruction(X86.Mov, result2, EAX);
        }
        /// <summary>
        /// Visitation function for <see cref="IX86Visitor.Mul"/> instructions.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Mul(Context context)
        {
            if (context.Result.IsCPURegister && context.Result2.IsCPURegister && context.Operand1.IsCPURegister && !context.Operand2.IsConstant &&
                context.Result.Register == GeneralPurposeRegister.EDX && context.Result2.Register == GeneralPurposeRegister.EAX && context.Operand1.Register == GeneralPurposeRegister.EAX)
                return;

            Operand operand1 = context.Operand1;
            Operand operand2 = context.Operand2;
            Operand result = context.Result;
            Operand result2 = context.Result2;

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

            context.SetInstruction(X86.Mov, EAX, operand1);

            if (operand2.IsConstant)
            {
                Operand v3 = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
                context.AppendInstruction(X86.Mov, v3, operand2);
                operand2 = v3;
            }

            Debug.Assert(operand2.IsCPURegister || operand2.IsVirtualRegister);

            context.AppendInstruction2(X86.Mul, EDX, EAX, EAX, operand2);
            context.AppendInstruction(X86.Mov, result, EDX);
            context.AppendInstruction(X86.Mov, result2, EAX);
        }
        /// <summary>
        /// Visitation function for <see cref="IX86Visitor.Mul"/> instructions.
        /// </summary>
        /// <param name="context">The context.</param>
        void IX86Visitor.Mul(Context context)
        {
            if (context.Result.IsCPURegister && context.Result2.IsCPURegister && context.Operand1.IsCPURegister && context.Operand2.IsRegister)
                if (context.Result.Register == GeneralPurposeRegister.EDX &&
                    context.Result2.Register == GeneralPurposeRegister.EAX &&
                    context.Operand1.Register == GeneralPurposeRegister.EAX)
                    return;

            Operand operand1 = context.Operand1;
            Operand operand2 = context.Operand2;
            Operand result = context.Result;
            Operand result2 = context.Result2;

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

            context.SetInstruction(X86.Mov, eax, operand1);

            if (operand2.IsRegister)
            {
                context.AppendInstruction2(X86.Mul, edx, eax, eax, operand2);
            }
            else
            {
                Operand v3 = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
                context.AppendInstruction(X86.Mov, v3, operand2);
                context.AppendInstruction2(X86.Mul, edx, eax, eax, v3);
            }

            context.AppendInstruction(X86.Mov, result, edx);
            context.AppendInstruction(X86.Mov, result2, eax);
        }
        /// <summary>
        /// Visitation function for <see cref="IX86Visitor.Setcc"/> instructions.
        /// </summary>
        /// <param name="context">The context.</param>
        void IX86Visitor.Setcc(Context context)
        {
            Debug.Assert(context.Result.IsCPURegister);

            // SETcc can not use ESI or EDI registers
            if (context.Result.IsCPURegister && (context.Result.Register == GeneralPurposeRegister.ESI || context.Result.Register == GeneralPurposeRegister.EDI))
            {
                Operand result = context.Result;
                var condition = context.ConditionCode;

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

                context.SetInstruction2(X86.Xchg, EAX, result, result, EAX);
                context.AppendInstruction(X86.Setcc, condition, EAX);
                context.AppendInstruction2(X86.Xchg, result, EAX, EAX, result);
            }
        }
        /// <summary>
        /// Visitation function for <see cref="IX86Visitor.Mov"/> instructions.
        /// </summary>
        /// <param name="context">The context.</param>
        void IX86Visitor.Mov(Context context)
        {
            // Mov can not use ESI or EDI registers with 8 or 16 bit memory or register
            if (context.Operand1.IsCPURegister && (context.Result.IsMemoryAddress || context.Result.IsCPURegister)
                && (context.Result.IsByte || context.Result.IsShort || context.Result.IsChar || context.Result.IsBoolean)
                && (context.Operand1.Register == GeneralPurposeRegister.ESI || context.Operand1.Register == GeneralPurposeRegister.EDI))
            {
                Operand source = context.Operand1;
                Operand dest = context.Result;

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

                context.SetInstruction2(X86.Xchg, EAX, source, source, EAX);
                context.AppendInstruction(X86.Mov, dest, EAX);
                context.AppendInstruction2(X86.Xchg, source, EAX, EAX, source);
            }
        }
        /// <summary>
        /// Visitation function for RemUnsigned.
        /// </summary>
        /// <param name="context">The context.</param>
        void IIRVisitor.RemUnsigned(Context context)
        {
            EmitFloatingPointConstants(context);

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

            Operand v1 = AllocateVirtualRegister(TypeSystem.BuiltIn.U4);
            Operand v2 = AllocateVirtualRegister(TypeSystem.BuiltIn.U4);

            context.SetInstruction(X86.Mov, v1, Operand.CreateConstantUnsignedInt(TypeSystem, (uint)0x0));
            context.AppendInstruction2(X86.Div, v1, v2, v1, operand1, operand2);
            context.AppendInstruction(X86.Mov, result, v2);
        }
        public void Setcc(Context context)
        {
            Debug.Assert(context.Result.IsCPURegister);

            Operand result = context.Result;

            Debug.Assert(result.IsCPURegister);

            // SETcc can not use with ESI or EDI registers
            if (result.Register == GeneralPurposeRegister.ESI || result.Register == GeneralPurposeRegister.EDI)
            {
                var condition = context.ConditionCode;

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

                context.SetInstruction2(X86.Xchg, eax, result, result, eax);
                context.AppendInstruction(X86.Setcc, condition, eax);
                context.AppendInstruction2(X86.Xchg, result, eax, eax, result);
            }
        }
Exemple #9
0
 /// <summary>
 /// Creates the swap.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="destination">The destination.</param>
 /// <param name="source">The source.</param>
 public override void InsertExchangeInstruction(Context context, Operand destination, Operand source)
 {
     if (source.IsR4)
     {
         // TODO
         throw new CompilerException("R4 not implemented in InsertExchangeInstruction method");
     }
     else if (source.IsR8)
     {
         // TODO
         throw new CompilerException("R8 not implemented in InsertExchangeInstruction method");
     }
     else
     {
         context.AppendInstruction2(X86.Xchg, destination, source, source, destination);
     }
 }
        /// <summary>
        /// Visitation function for DivSigned.
        /// </summary>
        /// <param name="context">The context.</param>
        void IIRVisitor.DivSigned(Context context)
        {
            Operand operand1 = context.Operand1;
            Operand operand2 = context.Operand2;
            Operand result = context.Result;

            Operand v1 = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
            Operand v2 = AllocateVirtualRegister(TypeSystem.BuiltIn.U4);
            Operand v3 = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);

            context.SetInstruction2(X86.Cdq, v1, v2, operand1);
            context.AppendInstruction2(X86.IDiv, v3, result, v1, v2, operand2);
        }
        /// <summary>
        /// Visitation function for <see cref="IX86Visitor.Mov"/> instructions.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Mov(Context context)
        {
            if (context.Result.IsCPURegister && context.Operand1.IsCPURegister && context.Result.Register == context.Operand1.Register)
            {
                context.Empty();
                return;
            }

            // Mov can not use ESI or EDI registers with 8 or 16 bit memory or register
            if (context.Operand1.IsCPURegister && (context.Result.IsMemoryAddress || context.Result.IsCPURegister)
                && (context.Result.IsByte || context.Result.IsShort || context.Result.IsChar || context.Result.IsBoolean)
                && (context.Operand1.Register == GeneralPurposeRegister.ESI || context.Operand1.Register == GeneralPurposeRegister.EDI))
            {
                Operand source = context.Operand1;
                Operand dest = context.Result;

                var replace = (dest.IsMemoryAddress && dest.EffectiveOffsetBase == GeneralPurposeRegister.EAX)
                        ? GeneralPurposeRegister.EBX : GeneralPurposeRegister.EAX;

                Operand reg = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, replace);

                context.SetInstruction2(X86.Xchg, reg, source, source, reg);
                context.AppendInstruction(X86.Mov, dest, reg);
                context.AppendInstruction2(X86.Xchg, source, reg, reg, source);
            }
        }
        /// <summary>
        /// Expands the signed move instruction for 64-bits.
        /// </summary>
        /// <param name="context">The context.</param>
        private void ExpandSignedMove(Context context)
        {
            Operand op0 = context.Result;
            Operand op1 = context.Operand1;
            Debug.Assert(op0 != null, @"I8 not in a memory operand!");

            Operand op0L, op0H;
            SplitLongOperand(op0, out op0L, out op0H);

            if (op1.IsBoolean)
            {
                context.SetInstruction(X86.Movzx, InstructionSize.Size8, op0L, op1);
                context.AppendInstruction(X86.Mov, op0H, ConstantZero);
            }
            else if (op1.IsI1 || op1.IsI2)
            {
                Operand v1 = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
                Operand v2 = AllocateVirtualRegister(TypeSystem.BuiltIn.U4);
                Operand v3 = AllocateVirtualRegister(TypeSystem.BuiltIn.U4);

                InstructionSize size = op1.IsI1 ? InstructionSize.Size8 : InstructionSize.Size16;

                context.SetInstruction(X86.Movsx, size, v1, op1);
                context.AppendInstruction2(X86.Cdq, v3, v2, v1);
                context.AppendInstruction(X86.Mov, op0L, v2);
                context.AppendInstruction(X86.Mov, op0H, v3);
            }
            else if (op1.IsI4 || op1.IsU4 || op1.IsPointer || op1.IsI || op1.IsU)
            {
                Operand v1 = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
                Operand v2 = AllocateVirtualRegister(TypeSystem.BuiltIn.U4);
                Operand v3 = AllocateVirtualRegister(TypeSystem.BuiltIn.U4);

                context.SetInstruction(X86.Mov, v1, op1);
                context.AppendInstruction2(X86.Cdq, v3, v2, v1);
                context.AppendInstruction(X86.Mov, op0L, v2);
                context.AppendInstruction(X86.Mov, op0H, v3);
            }
            else if (op1.IsI8)
            {
                context.SetInstruction(X86.Mov, op0, op1);
            }
            else if (op1.IsU1 || op1.IsU2)
            {
                Operand v1 = AllocateVirtualRegister(TypeSystem.BuiltIn.U4);
                Operand v2 = AllocateVirtualRegister(TypeSystem.BuiltIn.U4);
                Operand v3 = AllocateVirtualRegister(TypeSystem.BuiltIn.U4);

                InstructionSize size = op1.IsI1 ? InstructionSize.Size8 : InstructionSize.Size16;

                context.SetInstruction(X86.Movzx, size, v1, op1);
                context.AppendInstruction2(X86.Cdq, v3, v2, v1);
                context.AppendInstruction(X86.Mov, op0L, v2);
                context.AppendInstruction(X86.Mov, op0H, ConstantZero);
            }
            else
            {
                throw new InvalidCompilerException();
            }
        }
        /// <summary>
        /// Expands the mul instruction for 64-bit operands.
        /// </summary>
        /// <param name="context">The context.</param>
        private void ExpandMul(Context context)
        {
            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);

            Operand eax = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
            Operand edx = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
            Operand ebx = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);

            Operand v20 = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
            Operand v12 = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);

            // unoptimized
            context.SetInstruction(X86.Mov, eax, op2L);
            context.AppendInstruction(X86.Mov, v20, eax);
            context.AppendInstruction(X86.Mov, eax, v20);
            context.AppendInstruction2(X86.Mul, edx, eax, eax, op1L);
            context.AppendInstruction(X86.Mov, op0L, eax);

            if (!op0H.IsConstantZero)
            {
                context.AppendInstruction(X86.Mov, v12, edx);
                context.AppendInstruction(X86.Mov, eax, op1L);
                context.AppendInstruction(X86.Mov, ebx, eax);
                context.AppendInstruction(X86.IMul, ebx, ebx, op2H);
                context.AppendInstruction(X86.Mov, eax, v12);
                context.AppendInstruction(X86.Add, eax, eax, ebx);
                context.AppendInstruction(X86.Mov, ebx, op2L);
                context.AppendInstruction(X86.IMul, ebx, ebx, op1H);
                context.AppendInstruction(X86.Add, eax, eax, ebx);
                context.AppendInstruction(X86.Mov, v12, eax);
                context.AppendInstruction(X86.Mov, op0H, v12);
            }
        }
        /// <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;

            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);

            //Operand eax = AllocateVirtualRegister(typeSystem.BuiltIn.I4);
            //Operand edx = AllocateVirtualRegister(typeSystem.BuiltIn.I4);
            //Operand ebx = AllocateVirtualRegister(typeSystem.BuiltIn.I4);
            Operand eax = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX);
            Operand edx = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EDX);
            Operand ebx = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EBX);

            Operand v16 = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
            Operand v20 = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
            Operand v12 = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);

            // unoptimized
            context.SetInstruction(X86.Mov, eax, op2L);
            context.AppendInstruction(X86.Mov, v20, eax);
            context.AppendInstruction(X86.Mov, eax, v20);
            context.AppendInstruction2(X86.Mul, edx, eax, eax, op1L);
            context.AppendInstruction(X86.Mov, v16, eax);
            context.AppendInstruction(X86.Mov, v12, edx);
            context.AppendInstruction(X86.Mov, eax, op1L);
            context.AppendInstruction(X86.Mov, ebx, eax);
            context.AppendInstruction(X86.IMul, ebx, ebx, op2H);
            context.AppendInstruction(X86.Mov, eax, v12);
            context.AppendInstruction(X86.Add, eax, eax, ebx);
            context.AppendInstruction(X86.Mov, ebx, op2L);
            context.AppendInstruction(X86.IMul, ebx, ebx, op1H);
            context.AppendInstruction(X86.Add, eax, eax, ebx);
            context.AppendInstruction(X86.Mov, v12, eax);
            context.AppendInstruction(X86.Mov, op0L, v16);
            context.AppendInstruction(X86.Mov, op0H, v12);
        }
        public void Mov(Context context)
        {
            Operand source = context.Operand1;
            Operand result = context.Result;

            Debug.Assert(result.IsCPURegister);

            if (source.IsCPURegister && result.Register == source.Register)
            {
                context.Empty();
                return;
            }

            var size = context.Size;

            // Mov can not use ESI or EDI registers for 8/16bit values
            if (!(size == InstructionSize.Size16 || size == InstructionSize.Size8))
                return;

            if (source.IsCPURegister && (source.Register == GeneralPurposeRegister.ESI || source.Register == GeneralPurposeRegister.EDI))
            {
                Operand eax = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX);

                context.SetInstruction2(X86.Xchg, eax, source, source, eax);
                context.AppendInstruction(X86.Mov, result, eax);
                context.AppendInstruction2(X86.Xchg, source, eax, eax, source);
            }
        }
        /// <summary>
        /// Visitation function for RemUnsigned.
        /// </summary>
        /// <param name="context">The context.</param>
        void IIRVisitor.RemUnsigned(Context context)
        {
            Operand result = context.Result;
            Operand operand1 = context.Operand1;
            Operand operand2 = context.Operand2;

            Operand v1 = AllocateVirtualRegister(TypeSystem.BuiltIn.U4);
            Operand v2 = AllocateVirtualRegister(TypeSystem.BuiltIn.U4);

            context.SetInstruction(X86.Mov, v1, ConstantZero);
            context.AppendInstruction2(X86.Div, v1, v2, v1, operand1, operand2);
            context.AppendInstruction(X86.Mov, result, v1);
        }
        /// <summary>
        /// Visitation function for RemSigned.
        /// </summary>
        /// <param name="context">The context.</param>
        void IIRVisitor.RemSigned(Context context)
        {
            EmitFloatingPointConstants(context);

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

            Operand v1 = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
            Operand v2 = AllocateVirtualRegister(TypeSystem.BuiltIn.U4);
            Operand v3 = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);

            // FIXME
            context.SetInstruction2(X86.Cdq, v1, v2, operand1);
            context.AppendInstruction2(X86.IDiv, result, v3, v1, v2, operand2);
        }
 /// <summary>
 /// Creates the swap.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="destination">The destination.</param>
 /// <param name="source">The source.</param>
 public override void InsertExchangeInstruction(Context context, Operand destination, Operand source)
 {
     if (source.IsR4)
     {
         // TODO
     }
     else if (source.IsR8)
     {
         // TODO
     }
     else
     {
         context.AppendInstruction2(X86.Xchg, destination, source, source, destination);
     }
 }
        public void MovStore(Context context)
        {
            var size = context.Size;

            // Mov can not use ESI or EDI registers for 8/16bit values
            if (!(size == InstructionSize.Size16 || size == InstructionSize.Size8))
                return;

            Operand value = context.Operand3;

            if (value.IsCPURegister && (value.Register == GeneralPurposeRegister.ESI || value.Register == GeneralPurposeRegister.EDI))
            {
                Operand dest = context.Operand1;
                Operand offset = context.Operand2;

                Operand temporaryRegister = null;

                if (dest.Register != GeneralPurposeRegister.EAX && offset.Register != GeneralPurposeRegister.EAX)
                {
                    temporaryRegister = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX);
                }
                else if (dest.Register != GeneralPurposeRegister.EBX && offset.Register != GeneralPurposeRegister.EBX)
                {
                    temporaryRegister = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EBX);
                }
                else if (dest.Register != GeneralPurposeRegister.ECX && offset.Register != GeneralPurposeRegister.ECX)
                {
                    temporaryRegister = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ECX);
                }
                else
                {
                    temporaryRegister = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EDX);
                }

                context.SetInstruction2(X86.Xchg, temporaryRegister, value, value, temporaryRegister);
                context.AppendInstruction(X86.MovStore, size, null, dest, offset, temporaryRegister);
                context.AppendInstruction2(X86.Xchg, value, temporaryRegister, temporaryRegister, value);
            }
        }