Exemple #1
0
        private void FloatCompare(Context context, X64Instruction instruction)
        {
            var result    = context.Result;
            var condition = context.ConditionCode;
            var operand1  = context.Operand1;
            var operand2  = context.Operand2;

            operand1 = MoveConstantToFloatRegister(context, operand1);
            operand2 = MoveConstantToFloatRegister(context, operand2);

            var v1 = AllocateVirtualRegisterI32();

            if (condition == ConditionCode.Equal)
            {
                context.SetInstruction(instruction, null, operand1, operand2);
                context.AppendInstruction(X64.Setcc, ConditionCode.NoParity, result);
                context.AppendInstruction(X64.Mov32, v1, ConstantZero32);
                context.AppendInstruction(X64.CMov32, ConditionCode.NotEqual, result, result, v1);
                context.AppendInstruction(X64.Movzx8To32, result, result);
                return;
            }
            else if (condition == ConditionCode.NotEqual)
            {
                context.SetInstruction(instruction, null, operand1, operand2);
                context.AppendInstruction(X64.Setcc, ConditionCode.Parity, result);
                context.AppendInstruction(X64.Mov32, v1, CreateConstant32(1));
                context.AppendInstruction(X64.CMov32, ConditionCode.NotEqual, result, result, v1);
                context.AppendInstruction(X64.Movzx8To32, result, result);
                return;
            }
            else if (condition == ConditionCode.Greater || condition == ConditionCode.UnsignedGreater)
            {
                context.SetInstruction(instruction, null, operand1, operand2);
                context.AppendInstruction(X64.Setcc, ConditionCode.UnsignedGreater, v1);
                context.AppendInstruction(X64.Movzx8To32, result, v1);
                return;
            }
            else if (condition == ConditionCode.Less || condition == ConditionCode.UnsignedLess)
            {
                context.SetInstruction(instruction, null, operand2, operand1);
                context.AppendInstruction(X64.Setcc, ConditionCode.UnsignedGreater, v1);
                context.AppendInstruction(X64.Movzx8To32, result, v1);
                return;
            }
            else if (condition == ConditionCode.GreaterOrEqual || condition == ConditionCode.UnsignedGreaterOrEqual)
            {
                context.SetInstruction(instruction, null, operand2, operand1);
                context.AppendInstruction(X64.Setcc, ConditionCode.NoCarry, v1);
                context.AppendInstruction(X64.Movzx8To32, result, v1);
                return;
            }
            else if (condition == ConditionCode.LessOrEqual || condition == ConditionCode.UnsignedLessOrEqual)
            {
                context.SetInstruction(instruction, null, operand2, operand1);
                context.AppendInstruction(X64.Setcc, ConditionCode.NoCarry, v1);
                context.AppendInstruction(X64.Movzx8To32, result, v1);
                return;
            }
        }
        private void FloatCompare(Context context, X64Instruction instruction)
        {
            var result    = context.Result;
            var left      = context.Operand1;
            var right     = context.Operand2;
            var 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, context.Label);
                var nextBlock = Split(context);

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

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

                newBlocks[1].AppendInstruction(X64.Mov32, result, ConstantZero64);
                newBlocks[1].AppendInstruction(X64.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.Label);
                var nextBlock = Split(context);

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

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

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

                context.SetInstruction(X64.Mov64, result, ConstantZero64);
                context.AppendInstruction(instruction, null, right, left);
                context.AppendInstruction(X64.Setcc, ConditionCode.UnsignedGreaterThan, result);
                break;
            }

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

                context.SetInstruction(X64.Mov32, result, ConstantZero64);
                context.AppendInstruction(instruction, null, left, right);
                context.AppendInstruction(X64.Setcc, ConditionCode.UnsignedGreaterThan, result);
                break;
            }

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

                context.SetInstruction(X64.Mov32, result, ConstantZero64);
                context.AppendInstruction(instruction, null, right, left);
                context.AppendInstruction(X64.Setcc, ConditionCode.UnsignedGreaterOrEqual, result);
                break;
            }

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

                context.SetInstruction(X64.Mov32, result, ConstantZero64);
                context.AppendInstruction(instruction, null, left, right);
                context.AppendInstruction(X64.Setcc, ConditionCode.UnsignedGreaterOrEqual, result);
                break;
            }
            }
        }