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