Example #1
0
        /// <summary>
        /// Computes the opcode.
        /// </summary>
        /// <param name="size">The size.</param>
        /// <param name="destination">The destination operand.</param>
        /// <param name="source">The source operand.</param>
        /// <returns></returns>
        /// <exception cref="NotImplementCompilerException"></exception>
        private OpCode ComputeOpCode(InstructionSize size, Operand destination, Operand source)
        {
            Debug.Assert(destination.IsConstant || destination.IsCPURegister);
            Debug.Assert(size != InstructionSize.None);
            Debug.Assert(size != InstructionSize.Native);

            //size = BaseMethodCompilerStage.GetInstructionSize(size, destination);

            if (destination.IsCPURegister)
            {
                if (size == InstructionSize.Size8)
                    return R_8;

                if (size == InstructionSize.Size16)
                    return R_16;

                return R_32;
            }

            if (destination.IsConstant)
            {
                if (size == InstructionSize.Size8)
                    return C_8;

                if (size == InstructionSize.Size16)
                    return C_16;

                return C_32;
            }

            throw new NotImplementCompilerException();
        }
Example #2
0
        /// <summary>
        /// Computes the opcode.
        /// </summary>
        /// <param name="size">The size.</param>
        /// <param name="destination">The destination operand.</param>
        /// <param name="source">The source operand.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentException">@No opcode for operand type. [ + destination + ,  + source + )</exception>
        private OpCode ComputeOpCode(InstructionSize size, Operand destination, Operand source)
        {
            Debug.Assert(destination.IsMemoryAddress);
            Debug.Assert(source.IsRegister || source.IsConstant || source.IsSymbol);

            size = BaseMethodCompilerStage.GetInstructionSize(size, destination);

            if (source.IsSymbol)
                return RM_C;

            if (source.IsConstant)
            {
                if (size == InstructionSize.Size8)
                    return RM_C_U8;

                if (size == InstructionSize.Size16)
                    return M_C_16;

                return RM_C;
            }

            if (source.IsRegister)
            {
                if (size == InstructionSize.Size8)
                    return RM_R_U8;

                if (size == InstructionSize.Size16)
                    return M_R_16;

                return M_R;
            }

            throw new ArgumentException(@"No opcode for operand type. [" + destination + ", " + source + ")");
        }
Example #3
0
        public static OpcodeEncoder AppendInteger(this OpcodeEncoder encoder, Operand operand, InstructionSize size)
        {
            if (size == InstructionSize.Size32)
                return encoder.AppendIntegerValue(operand.ConstantUnsignedInteger);
            if (size == InstructionSize.Size8)
                return encoder.AppendByteValue((byte)operand.ConstantUnsignedInteger);
            if (size == InstructionSize.Size16)
                return encoder.AppendShortValue((ushort)operand.ConstantUnsignedInteger);

            throw new InvalidCompilerException("Instruction size invalid");
        }
Example #4
0
        public OpcodeEncoder AppendIntegerOfSize(Operand operand, InstructionSize size)
        {
            if (size == InstructionSize.Size32)
            {
                return(AppendIntegerValue(operand.ConstantUnsignedInteger));
            }
            if (size == InstructionSize.Size8)
            {
                return(AppendByteValue((byte)operand.ConstantUnsignedInteger));
            }
            if (size == InstructionSize.Size16)
            {
                return(AppendShortValue((ushort)operand.ConstantUnsignedInteger));
            }

            throw new CompilerException("Instruction size invalid");
        }
Example #5
0
        /// <summary>
        /// Computes the opcode.
        /// </summary>
        /// <param name="size">The size.</param>
        /// <param name="destination">The destination operand.</param>
        /// <param name="source">The source operand.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentException">@No opcode for operand type. [ + destination + ,  + source + )</exception>
        private OpCode ComputeOpCode(InstructionSize size, Operand destination, Operand source)
        {
            Debug.Assert(destination.IsRegister);
            Debug.Assert(source.IsMemoryAddress);

            size = BaseMethodCompilerStage.GetInstructionSize(size, destination);

            Debug.Assert(size != InstructionSize.Size64);

            if (size == InstructionSize.Size8)
                return R_M_U8;

            if (size == InstructionSize.Size16)
                return R_RM_16;

            return R_RM;
        }
Example #6
0
        /// <summary>
        /// Inserts the load instruction.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="destination">The destination.</param>
        /// <param name="source">The source.</param>
        /// <param name="offset">The offset.</param>
        public override void InsertLoadInstruction(Context context, Operand destination, Operand source, Operand offset)
        {
            BaseInstruction instruction = X86.MovLoad;
            InstructionSize size        = InstructionSize.Size32;

            if (destination.IsR4)
            {
                instruction = X86.MovssLoad;
            }
            else if (destination.IsR8)
            {
                instruction = X86.MovsdLoad;
                size        = InstructionSize.Size64;
            }

            context.AppendInstruction(instruction, size, destination, source, offset);
        }
Example #7
0
        public override void InsertStoreInstruction(Context context, Operand destination, Operand offset, Operand value)
        {
            BaseInstruction instruction = X86.MovStore;
            InstructionSize size        = InstructionSize.Size32;

            if (value.IsR4)
            {
                instruction = X86.MovssStore;
            }
            else if (value.IsR8)
            {
                instruction = X86.MovsdStore;
                size        = InstructionSize.Size64;
            }

            context.AppendInstruction(instruction, size, null, destination, offset, value);
        }
Example #8
0
        /// <summary>
        /// Create platform move.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="destination">The destination.</param>
        /// <param name="source">The source.</param>
        public override void InsertMoveInstruction(Context context, Operand destination, Operand source)
        {
            BaseInstruction instruction = X86.Mov;
            InstructionSize size        = InstructionSize.Size32;

            if (destination.IsR4)
            {
                instruction = X86.Movss;
                size        = InstructionSize.Size32;
            }
            else if (destination.IsR8)
            {
                instruction = X86.Movsd;
                size        = InstructionSize.Size64;
            }

            context.AppendInstruction(instruction, size, destination, source);
        }
Example #9
0
        /// <summary>
        /// Computes the opcode.
        /// </summary>
        /// <param name="size">The size.</param>
        /// <param name="destination">The destination operand.</param>
        /// <param name="source">The source operand.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentException">@No opcode for operand type. [ + destination + ,  + source + )</exception>
        private OpCode ComputeOpCode(InstructionSize size, Operand destination, Operand source)
        {
            Debug.Assert(destination.IsMemoryAddress);
            Debug.Assert(source.IsRegister || source.IsConstant || source.IsSymbol);

            size = BaseMethodCompilerStage.GetInstructionSize(size, destination);

            if (source.IsSymbol)
            {
                return(RM_C);
            }

            if (source.IsConstant)
            {
                if (size == InstructionSize.Size8)
                {
                    return(RM_C_U8);
                }

                if (size == InstructionSize.Size16)
                {
                    return(M_C_16);
                }

                return(RM_C);
            }

            if (source.IsRegister)
            {
                if (size == InstructionSize.Size8)
                {
                    return(RM_R_U8);
                }

                if (size == InstructionSize.Size16)
                {
                    return(M_R_16);
                }

                return(M_R);
            }

            throw new ArgumentException(@"No opcode for operand type. [" + destination + ", " + source + ")");
        }
        public static string GetSizeString(InstructionSize size)
        {
            switch (size)
            {
            case InstructionSize.Size32: return("32");

            case InstructionSize.Size8: return("8");

            case InstructionSize.Size16: return("16");

            case InstructionSize.Size64: return("64");

            case InstructionSize.Size128: return("128");

            case InstructionSize.Native: return("Native");

            default: return(string.Empty);
            }
        }
Example #11
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The method compiler.</param>
        /// <exception cref="InvalidCompilerException"></exception>
        void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            const InstructionSize size = InstructionSize.Size16;

            if (context.OperandCount == 1)
            {
                context.SetInstruction(IRInstruction.LoadZeroExtended, size, context.Result, context.Operand1, methodCompiler.ConstantZero);
            }
            else if (context.OperandCount == 2)
            {
                context.SetInstruction(IRInstruction.LoadZeroExtended, size, context.Result, context.Operand1, context.Operand2);
            }
            else
            {
                throw new InvalidCompilerException();
            }

            LoadStore.OrderLoadOperands(context.Node, methodCompiler);
        }
Example #12
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The method compiler.</param>
        /// <exception cref="InvalidCompilerException"></exception>
        void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            const InstructionSize size = InstructionSize.Size32;

            if (context.OperandCount == 2)
            {
                context.SetInstruction(IRInstruction.StoreInteger, size, null, context.Operand1, methodCompiler.ConstantZero, context.Operand2);
            }
            else if (context.OperandCount == 3)
            {
                context.SetInstruction(IRInstruction.StoreInteger, size, null, context.Operand1, context.Operand2, context.Operand3);
            }
            else
            {
                throw new InvalidCompilerException();
            }

            LoadStore.OrderStoreOperands(context.Node, methodCompiler);
        }
Example #13
0
        /// <summary>
        /// Computes the opcode.
        /// </summary>
        /// <param name="size">The size.</param>
        /// <param name="destination">The destination operand.</param>
        /// <param name="source">The source operand.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentException">@No opcode for operand type. [ + destination + ,  + source + )</exception>
        private OpCode ComputeOpCode(InstructionSize size, Operand destination, Operand source)
        {
            Debug.Assert(destination.IsRegister);
            Debug.Assert(source.IsMemoryAddress);

            size = BaseMethodCompilerStage.GetInstructionSize(size, destination);

            Debug.Assert(size != InstructionSize.Size64);

            if (size == InstructionSize.Size8)
            {
                return(R_M_U8);
            }

            if (size == InstructionSize.Size16)
            {
                return(R_RM_16);
            }

            return(R_RM);
        }
Example #14
0
        /// <summary>
        /// Computes the opcode.
        /// </summary>
        /// <param name="size">The size.</param>
        /// <param name="destination">The destination operand.</param>
        /// <param name="source">The source operand.</param>
        /// <returns></returns>
        /// <exception cref="NotImplementCompilerException"></exception>
        private OpCode ComputeOpCode(InstructionSize size, Operand destination, Operand source)
        {
            Debug.Assert(destination.IsConstant || destination.IsCPURegister);
            Debug.Assert(size != InstructionSize.None);
            Debug.Assert(size != InstructionSize.Native);

            //size = BaseMethodCompilerStage.GetInstructionSize(size, destination);

            if (destination.IsCPURegister)
            {
                if (size == InstructionSize.Size8)
                {
                    return(R_8);
                }

                if (size == InstructionSize.Size16)
                {
                    return(R_16);
                }

                return(R_32);
            }

            if (destination.IsConstant)
            {
                if (size == InstructionSize.Size8)
                {
                    return(C_8);
                }

                if (size == InstructionSize.Size16)
                {
                    return(C_16);
                }

                return(C_32);
            }

            throw new NotImplementCompilerException();
        }
Example #15
0
        /// <summary>
        /// Visitation function for MoveInstruction.
        /// </summary>
        /// <param name="context">The context.</param>
        void IIRVisitor.Move(Context context)
        {
            Operand result  = context.Result;
            Operand operand = context.Operand1;

            X86Instruction  instruction = X86.Mov;
            InstructionSize size        = InstructionSize.None;

            if (result.IsR)
            {
                //Debug.Assert(operand.IsFloatingPoint, @"Move can't convert to floating point type.");

                if (result.Type == operand.Type)
                {
                    if (result.IsR4)
                    {
                        instruction = X86.Movss;
                        size        = InstructionSize.Size32;
                    }
                    else if (result.IsR8)
                    {
                        instruction = X86.Movsd;
                        size        = InstructionSize.Size64;
                    }
                }
                else if (result.IsR8)
                {
                    instruction = X86.Cvtss2sd;
                }
                else if (result.IsR4)
                {
                    instruction = X86.Cvtsd2ss;
                }
            }

            context.ReplaceInstructionOnly(instruction);
            context.Size = size;
        }
Example #16
0
        public OpcodeEncoder AppendConditionalIntegerOfSize(bool include, Operand operand, InstructionSize size)
        {
            if (!include)
            {
                return(this);
            }

            return(AppendIntegerOfSize(operand, size));
        }
        /// <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();
            }
        }
Example #18
0
 /// <summary>
 /// Appends the instruction after the current index.
 /// </summary>
 /// <param name="instruction">The instruction.</param>
 /// <param name="size">The size.</param>
 /// <param name="result">The result.</param>
 /// <param name="operand1">The operand1.</param>
 public void AppendInstruction(BaseInstruction instruction, InstructionSize size, Operand result, Operand operand1)
 {
     AppendInstruction(instruction, result, operand1);
     Size = size;
 }
 /// <summary>
 /// Sets the instruction.
 /// </summary>
 /// <param name="instruction">The instruction.</param>
 /// <param name="size">The size.</param>
 /// <param name="result">The result.</param>
 /// <param name="operand1">The operand1.</param>
 /// <param name="operand2">The operand2.</param>
 /// <param name="operand3">The operand3.</param>
 public void SetInstruction(BaseInstruction instruction, InstructionSize size, Operand result, Operand operand1, Operand operand2, Operand operand3)
 {
     SetInstruction(instruction, result, operand1, operand2, operand3);
     Size = size;
 }
Example #20
0
 /// <summary>
 /// Sets the instruction.
 /// </summary>
 /// <param name="instruction">The instruction.</param>
 /// <param name="size">The size.</param>
 /// <param name="result">The result.</param>
 /// <param name="operand1">The operand1.</param>
 public void SetInstruction(BaseInstruction instruction, InstructionSize size, Operand result, Operand operand1)
 {
     Node.SetInstruction(instruction, size, result, operand1);
 }
Example #21
0
 /// <summary>
 /// Appends the instruction.
 /// </summary>
 /// <param name="instruction">The instruction.</param>
 /// <param name="size">The size.</param>
 /// <param name="result">The result.</param>
 /// <param name="operand1">The operand1.</param>
 /// <param name="operand2">The operand2.</param>
 public void AppendInstruction(BaseInstruction instruction, InstructionSize size, Operand result, Operand operand1, Operand operand2)
 {
     AppendInstruction();
     SetInstruction(instruction, size, result, operand1, operand2);
 }
Example #22
0
        /// <summary>
        /// Appends the instruction.
        /// </summary>
        /// <param name="instruction">The instruction.</param>
        /// <param name="size">The size.</param>
        /// <param name="result">The result.</param>
        /// <param name="operand1">The operand1.</param>
        /// <param name="operand2">The operand2.</param>
        /// <param name="operand3">The operand3.</param>
        /// <param name="operand4">The operand4.</param>
        public void AppendInstruction(BaseInstruction instruction, InstructionSize size, Operand result, Operand operand1, Operand operand2, Operand operand3, Operand operand4)
        {
            AppendInstruction();

            Node.SetInstruction(instruction, size, result, operand1, operand2, operand3, operand4);
        }
Example #23
0
        /// <summary>
        /// Floating point compare instruction.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="instruction">The instruction.</param>
        /// <param name="size">The size.</param>
        private void FloatCompare(Context context, X86Instruction instruction, InstructionSize size)
        {
            Operand       result    = context.Result;
            Operand       left      = context.Operand1;
            Operand       right     = context.Operand2;
            ConditionCode condition = context.ConditionCode;

            // normalize condition
            switch (condition)
            {
            case ConditionCode.Equal: break;

            case ConditionCode.NotEqual: break;

            case ConditionCode.UnsignedGreaterOrEqual: condition = ConditionCode.GreaterOrEqual; break;

            case ConditionCode.UnsignedGreaterThan: condition = ConditionCode.GreaterThan; break;

            case ConditionCode.UnsignedLessOrEqual: condition = ConditionCode.LessOrEqual; break;

            case ConditionCode.UnsignedLessThan: condition = ConditionCode.LessThan; break;
            }

            Debug.Assert(!(left.IsR4 && right.IsR8));
            Debug.Assert(!(left.IsR8 && right.IsR4));

            switch (condition)
            {
            case ConditionCode.Equal:
            {
                //  a==b
                //	mov	eax, 1
                //	ucomisd	xmm0, xmm1
                //	jp	L3
                //	jne	L3
                //	ret
                //L3:
                //	mov	eax, 0

                var newBlocks = CreateNewBlockContexts(2);
                var nextBlock = Split(context);

                context.SetInstruction(X86.Mov, result, CreateConstant(1));
                context.AppendInstruction(instruction, size, null, left, right);
                context.AppendInstruction(X86.Branch, ConditionCode.Parity, newBlocks[1].Block);
                context.AppendInstruction(X86.Jmp, newBlocks[0].Block);

                newBlocks[0].AppendInstruction(X86.Branch, ConditionCode.NotEqual, newBlocks[1].Block);
                newBlocks[0].AppendInstruction(X86.Jmp, nextBlock.Block);

                newBlocks[1].AppendInstruction(X86.Mov, result, ConstantZero);
                newBlocks[1].AppendInstruction(X86.Jmp, nextBlock.Block);
                break;
            }

            case ConditionCode.NotEqual:
            {
                //  a!=b
                //	mov	eax, 1
                //	ucomisd	xmm0, xmm1
                //	jp	L5
                //	setne	al
                //	movzx	eax, al
                //L5:

                var newBlocks = CreateNewBlockContexts(1);
                var nextBlock = Split(context);

                context.SetInstruction(X86.Mov, result, CreateConstant(1));
                context.AppendInstruction(instruction, size, null, left, right);
                context.AppendInstruction(X86.Branch, ConditionCode.Parity, nextBlock.Block);
                context.AppendInstruction(X86.Jmp, newBlocks[0].Block);
                newBlocks[0].AppendInstruction(X86.Setcc, ConditionCode.NotEqual, result);

                //newBlocks[0].AppendInstruction(X86.Movzx, InstructionSize.Size8, result, result);
                newBlocks[0].AppendInstruction(X86.Jmp, nextBlock.Block);
                break;
            }

            case ConditionCode.LessThan:
            {
                //	a<b
                //	mov	eax, 0
                //	ucomisd	xmm1, xmm0
                //	seta	al

                context.SetInstruction(X86.Mov, result, ConstantZero);
                context.AppendInstruction(instruction, size, null, right, left);
                context.AppendInstruction(X86.Setcc, ConditionCode.UnsignedGreaterThan, result);
                break;
            }

            case ConditionCode.GreaterThan:
            {
                //	a>b
                //	mov	eax, 0
                //	ucomisd	xmm0, xmm1
                //	seta	al

                context.SetInstruction(X86.Mov, result, ConstantZero);
                context.AppendInstruction(instruction, size, null, left, right);
                context.AppendInstruction(X86.Setcc, ConditionCode.UnsignedGreaterThan, result);
                break;
            }

            case ConditionCode.LessOrEqual:
            {
                //	a<=b
                //	mov	eax, 0
                //	ucomisd	xmm1, xmm0
                //	setae	al

                context.SetInstruction(X86.Mov, result, ConstantZero);
                context.AppendInstruction(instruction, size, null, right, left);
                context.AppendInstruction(X86.Setcc, ConditionCode.UnsignedGreaterOrEqual, result);
                break;
            }

            case ConditionCode.GreaterOrEqual:
            {
                //	a>=b
                //	mov	eax, 0
                //	ucomisd	xmm0, xmm1
                //	setae	al

                context.SetInstruction(X86.Mov, result, ConstantZero);
                context.AppendInstruction(instruction, size, null, left, right);
                context.AppendInstruction(X86.Setcc, ConditionCode.UnsignedGreaterOrEqual, result);
                break;
            }
            }
        }
 /// <summary>
 /// Sets the instruction.
 /// </summary>
 /// <param name="instruction">The instruction.</param>
 /// <param name="size">The size.</param>
 /// <param name="result">The result.</param>
 /// <param name="operand1">The operand1.</param>
 /// <param name="operand2">The operand2.</param>
 /// <param name="operand3">The operand3.</param>
 public void SetInstruction(BaseInstruction instruction, InstructionSize size, Operand result, Operand operand1, Operand operand2, Operand operand3)
 {
     SetInstruction(instruction, result, operand1, operand2, operand3);
     Size = size;
 }
        /// <summary>
        /// Gets the size of the instruction.
        /// </summary>
        /// <param name="size">The size.</param>
        /// <param name="type">The type.</param>
        /// <returns></returns>
        public static InstructionSize GetInstructionSize(InstructionSize size, MosaType type)
        {
            if (size != InstructionSize.None)
                return size;

            return GetInstructionSize(type);
        }
Example #26
0
 /// <summary>
 /// Sets the instruction.
 /// </summary>
 /// <param name="instruction">The instruction.</param>
 /// <param name="size">The size.</param>
 /// <param name="result">The result.</param>
 /// <param name="operand1">The operand1.</param>
 /// <param name="operand2">The operand2.</param>
 /// <param name="operand3">The operand3.</param>
 public void SetInstruction(BaseInstruction instruction, InstructionSize size, Operand result, Operand operand1, Operand operand2, Operand operand3)
 {
     Node.SetInstruction(instruction, size, result, operand1, operand2, operand3);
 }
        /// <summary>
        /// Gets the size of the instruction.
        /// </summary>
        /// <param name="size">The size.</param>
        /// <param name="operand">The operand.</param>
        /// <returns></returns>
        public static InstructionSize GetInstructionSize(InstructionSize size, Operand operand)
        {
            if (size != InstructionSize.None)
                return size;

            return GetInstructionSize(operand);
        }
Example #28
0
        /// <summary>
        /// Floating point compare instruction.
        /// </summary>
        /// <param name="context">The context.</param>
        void IIRVisitor.FloatCompare(Context context)
        {
            Operand       result    = context.Result;
            Operand       left      = context.Operand1;
            Operand       right     = context.Operand2;
            ConditionCode condition = context.ConditionCode;

            // normalize condition
            switch (condition)
            {
            case ConditionCode.Equal: break;

            case ConditionCode.NotEqual: break;

            case ConditionCode.UnsignedGreaterOrEqual: condition = ConditionCode.GreaterOrEqual; break;

            case ConditionCode.UnsignedGreaterThan: condition = ConditionCode.GreaterThan; break;

            case ConditionCode.UnsignedLessOrEqual: condition = ConditionCode.LessOrEqual; break;

            case ConditionCode.UnsignedLessThan: condition = ConditionCode.LessThan; break;
            }

            // TODO - Move the following to its own pre-IR decomposition stage for this instruction
            // Swap, if necessary, the operands to place register operand first than memory operand
            // otherwise the memory operand will have to be loaded into a register
            if ((condition == ConditionCode.Equal || condition == ConditionCode.NotEqual) && left.IsMemoryAddress && !right.IsMemoryAddress)
            {
                // swap order of operands to move
                var t = left;
                left  = right;
                right = t;
            }

            Context before = context.InsertBefore();

            // Compare using the smallest precision
            if (left.IsR4 && right.IsR8)
            {
                Operand rop = AllocateVirtualRegister(TypeSystem.BuiltIn.R4);
                before.SetInstruction(X86.Cvtsd2ss, rop, right);
                right = rop;
            }
            if (left.IsR8 && right.IsR4)
            {
                Operand rop = AllocateVirtualRegister(TypeSystem.BuiltIn.R4);
                before.SetInstruction(X86.Cvtsd2ss, rop, left);
                left = rop;
            }

            X86Instruction  instruction = null;
            InstructionSize size        = InstructionSize.None;

            if (left.IsR4)
            {
                instruction = X86.Ucomiss;
                size        = InstructionSize.Size32;
            }
            else
            {
                instruction = X86.Ucomisd;
                size        = InstructionSize.Size64;
            }

            switch (condition)
            {
            case ConditionCode.Equal:
            {
                //  a==b
                //	mov	eax, 1
                //	ucomisd	xmm0, xmm1
                //	jp	L3
                //	jne	L3
                //	ret
                //L3:
                //	mov	eax, 0

                var     newBlocks = CreateNewBlockContexts(2);
                Context nextBlock = Split(context);

                context.SetInstruction(X86.Mov, result, Operand.CreateConstant(TypeSystem, 1));
                context.AppendInstruction(instruction, size, null, left, right);
                context.AppendInstruction(X86.Branch, ConditionCode.Parity, newBlocks[1].Block);
                context.AppendInstruction(X86.Jmp, newBlocks[0].Block);

                newBlocks[0].AppendInstruction(X86.Branch, ConditionCode.NotEqual, newBlocks[1].Block);
                newBlocks[0].AppendInstruction(X86.Jmp, nextBlock.Block);

                newBlocks[1].AppendInstruction(X86.Mov, result, ConstantZero);
                newBlocks[1].AppendInstruction(X86.Jmp, nextBlock.Block);

                break;
            }

            case ConditionCode.NotEqual:
            {
                //  a!=b
                //	mov	eax, 1
                //	ucomisd	xmm0, xmm1
                //	jp	L5
                //	setne	al
                //	movzx	eax, al
                //L5:

                var     newBlocks = CreateNewBlockContexts(1);
                Context nextBlock = Split(context);

                context.SetInstruction(X86.Mov, result, Operand.CreateConstant(TypeSystem, 1));
                context.AppendInstruction(instruction, size, null, left, right);
                context.AppendInstruction(X86.Branch, ConditionCode.Parity, nextBlock.Block);
                context.AppendInstruction(X86.Jmp, newBlocks[0].Block);

                newBlocks[0].AppendInstruction(X86.Setcc, ConditionCode.NotEqual, result);
                newBlocks[0].AppendInstruction(X86.Movzx, result, result);
                newBlocks[0].AppendInstruction(X86.Jmp, nextBlock.Block);

                break;
            }

            case ConditionCode.LessThan:
            {
                //	a<b
                //	mov	eax, 0
                //	ucomisd	xmm1, xmm0
                //	seta	al

                context.SetInstruction(X86.Mov, result, ConstantZero);
                context.AppendInstruction(instruction, size, null, right, left);
                context.AppendInstruction(X86.Setcc, ConditionCode.UnsignedGreaterThan, result);
                break;
            }

            case ConditionCode.GreaterThan:
            {
                //	a>b
                //	mov	eax, 0
                //	ucomisd	xmm0, xmm1
                //	seta	al

                context.SetInstruction(X86.Mov, result, ConstantZero);
                context.AppendInstruction(instruction, size, null, left, right);
                context.AppendInstruction(X86.Setcc, ConditionCode.UnsignedGreaterThan, result);
                break;
            }

            case ConditionCode.LessOrEqual:
            {
                //	a<=b
                //	mov	eax, 0
                //	ucomisd	xmm1, xmm0
                //	setae	al

                context.SetInstruction(X86.Mov, result, ConstantZero);
                context.AppendInstruction(instruction, size, null, right, left);
                context.AppendInstruction(X86.Setcc, ConditionCode.UnsignedGreaterOrEqual, result);
                break;
            }

            case ConditionCode.GreaterOrEqual:
            {
                //	a>=b
                //	mov	eax, 0
                //	ucomisd	xmm0, xmm1
                //	setae	al

                context.SetInstruction(X86.Mov, result, ConstantZero);
                context.AppendInstruction(instruction, size, null, left, right);
                context.AppendInstruction(X86.Setcc, ConditionCode.UnsignedGreaterOrEqual, result);
                break;
            }
            }
        }
Example #29
0
 /// <summary>
 /// Appends the instruction.
 /// </summary>
 /// <param name="instruction">The instruction.</param>
 /// <param name="size">The size.</param>
 /// <param name="result">The result.</param>
 /// <param name="operand1">The operand1.</param>
 public void AppendInstruction(BaseInstruction instruction, InstructionSize size, Operand result, Operand operand1)
 {
     AppendInstruction();
     Node.SetInstruction(instruction, size, result, operand1);
 }
Example #30
0
 public void EmitNew(OpCode opCode, ConstructorInfo constructor, int?argumentCount = null,
                     int?resultCount = null)
 {
     ilSize += InstructionSize.Get(opCode);
     AdjustStack(opCode, argumentCount ?? constructor.GetParameters().Length, resultCount);
 }
Example #31
0
 public static string GetSizeString(InstructionSize size)
 {
     switch (size)
     {
         case InstructionSize.Size32: return "32";
         case InstructionSize.Size8: return "8";
         case InstructionSize.Size16: return "16";
         case InstructionSize.Size64: return "64";
         case InstructionSize.Size128: return "128";
         case InstructionSize.Native: return "Native";
         default: return string.Empty;
     }
 }
Example #32
0
 /// <summary>
 /// Replaces the instruction only.
 /// </summary>
 /// <param name="instruction">The instruction.</param>
 /// <param name="size">The size.</param>
 public void ReplaceInstruction(BaseInstruction instruction, InstructionSize size)
 {
     Instruction = instruction;
     Size        = size;
 }