Index: src/compiler/x87/code-generator-x87.cc |
diff --git a/src/compiler/x87/code-generator-x87.cc b/src/compiler/x87/code-generator-x87.cc |
index 2ac66d838c4490db09a9d1e6907cc47a27f78953..dcd85737da73f60f8c5b2c816909ccaeb51715cb 100644 |
--- a/src/compiler/x87/code-generator-x87.cc |
+++ b/src/compiler/x87/code-generator-x87.cc |
@@ -191,18 +191,14 @@ class OutOfLineLoadInteger final : public OutOfLineCode { |
Register const result_; |
}; |
- |
-class OutOfLineLoadFloat final : public OutOfLineCode { |
+class OutOfLineLoadNaN final : public OutOfLineCode { |
public: |
- OutOfLineLoadFloat(CodeGenerator* gen, X87Register result) |
+ OutOfLineLoadNaN(CodeGenerator* gen, X87Register result) |
: OutOfLineCode(gen), result_(result) {} |
void Generate() final { |
DCHECK(result_.code() == 0); |
USE(result_); |
- if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
- __ VerifyX87StackDepth(1); |
- } |
__ fstp(0); |
__ push(Immediate(0xffffffff)); |
__ push(Immediate(0x7fffffff)); |
@@ -275,25 +271,23 @@ class OutOfLineRecordWrite final : public OutOfLineCode { |
} // namespace |
- |
-#define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr) \ |
- do { \ |
- auto result = i.OutputDoubleRegister(); \ |
- auto offset = i.InputRegister(0); \ |
- DCHECK(result.code() == 0); \ |
- if (instr->InputAt(1)->IsRegister()) { \ |
- __ cmp(offset, i.InputRegister(1)); \ |
- } else { \ |
- __ cmp(offset, i.InputImmediate(1)); \ |
- } \ |
- OutOfLineCode* ool = new (zone()) OutOfLineLoadFloat(this, result); \ |
- __ j(above_equal, ool->entry()); \ |
- __ fstp(0); \ |
- __ asm_instr(i.MemoryOperand(2)); \ |
- __ bind(ool->exit()); \ |
+#define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr) \ |
+ do { \ |
+ auto result = i.OutputDoubleRegister(); \ |
+ auto offset = i.InputRegister(0); \ |
+ DCHECK(result.code() == 0); \ |
+ if (instr->InputAt(1)->IsRegister()) { \ |
+ __ cmp(offset, i.InputRegister(1)); \ |
+ } else { \ |
+ __ cmp(offset, i.InputImmediate(1)); \ |
+ } \ |
+ OutOfLineCode* ool = new (zone()) OutOfLineLoadNaN(this, result); \ |
+ __ j(above_equal, ool->entry()); \ |
+ __ fstp(0); \ |
+ __ asm_instr(i.MemoryOperand(2)); \ |
+ __ bind(ool->exit()); \ |
} while (false) |
- |
#define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ |
do { \ |
auto result = i.OutputRegister(); \ |
@@ -1164,93 +1158,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
__ X87SetFPUCW(0x037F); |
break; |
} |
- case kX87Float32Max: { |
- Label check_nan_left, check_zero, return_left, return_right; |
- Condition condition = below; |
- if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
- __ VerifyX87StackDepth(1); |
- } |
- __ fstp(0); |
- __ fld_s(MemOperand(esp, kFloatSize)); |
- __ fld_s(MemOperand(esp, 0)); |
- __ fld(1); |
- __ fld(1); |
- __ FCmp(); |
- |
- // At least one NaN. |
- // Return the second operands if one of the two operands is NaN |
- __ j(parity_even, &return_right, Label::kNear); |
- __ j(equal, &check_zero, Label::kNear); // left == right. |
- __ j(condition, &return_left, Label::kNear); |
- __ jmp(&return_right, Label::kNear); |
- |
- __ bind(&check_zero); |
- __ fld(0); |
- __ fldz(); |
- __ FCmp(); |
- __ j(not_equal, &return_left, Label::kNear); // left == right != 0. |
- |
- __ fadd(1); |
- __ jmp(&return_left, Label::kNear); |
- |
- __ bind(&return_right); |
- __ fxch(); |
- |
- __ bind(&return_left); |
- __ fstp(0); |
- __ lea(esp, Operand(esp, 2 * kFloatSize)); |
- break; |
- } |
- case kX87Float32Min: { |
- Label check_nan_left, check_zero, return_left, return_right; |
- Condition condition = above; |
- if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
- __ VerifyX87StackDepth(1); |
- } |
- __ fstp(0); |
- __ fld_s(MemOperand(esp, kFloatSize)); |
- __ fld_s(MemOperand(esp, 0)); |
- __ fld(1); |
- __ fld(1); |
- __ FCmp(); |
- // At least one NaN. |
- // Return the second operands if one of the two operands is NaN |
- __ j(parity_even, &return_right, Label::kNear); |
- __ j(equal, &check_zero, Label::kNear); // left == right. |
- __ j(condition, &return_left, Label::kNear); |
- __ jmp(&return_right, Label::kNear); |
- |
- __ bind(&check_zero); |
- __ fld(0); |
- __ fldz(); |
- __ FCmp(); |
- __ j(not_equal, &return_left, Label::kNear); // left == right != 0. |
- // At this point, both left and right are either 0 or -0. |
- // Push st0 and st1 to stack, then pop them to temp registers and OR them, |
- // load it to left. |
- __ push(eax); |
- __ fld(1); |
- __ fld(1); |
- __ sub(esp, Immediate(2 * kPointerSize)); |
- __ fstp_s(MemOperand(esp, 0)); |
- __ fstp_s(MemOperand(esp, kPointerSize)); |
- __ pop(eax); |
- __ xor_(MemOperand(esp, 0), eax); |
- __ fstp(0); |
- __ fld_s(MemOperand(esp, 0)); |
- __ pop(eax); // restore esp |
- __ pop(eax); // restore esp |
- __ jmp(&return_left, Label::kNear); |
- |
- |
- __ bind(&return_right); |
- __ fxch(); |
- __ bind(&return_left); |
- __ fstp(0); |
- __ lea(esp, Operand(esp, 2 * kFloatSize)); |
- break; |
- } |
case kX87Float32Sqrt: { |
if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
__ VerifyX87StackDepth(1); |
@@ -1366,8 +1274,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
break; |
} |
case kX87Float64Max: { |
- Label check_zero, return_left, return_right; |
- Condition condition = below; |
+ Label compare_swap, done_compare; |
if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
__ VerifyX87StackDepth(1); |
} |
@@ -1377,29 +1284,32 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
__ fld(1); |
__ fld(1); |
__ FCmp(); |
- __ j(parity_even, &return_right, |
- Label::kNear); // At least one NaN, Return right. |
- __ j(equal, &check_zero, Label::kNear); // left == right. |
- __ j(condition, &return_left, Label::kNear); |
- __ jmp(&return_right, Label::kNear); |
- __ bind(&check_zero); |
- __ fld(0); |
- __ fldz(); |
- __ FCmp(); |
- __ j(not_equal, &return_left, Label::kNear); // left == right != 0. |
+ auto ool = new (zone()) OutOfLineLoadNaN(this, i.OutputDoubleRegister()); |
+ __ j(parity_even, ool->entry()); |
+ __ j(below, &done_compare, Label::kNear); |
+ __ j(above, &compare_swap, Label::kNear); |
+ __ push(eax); |
+ __ lea(esp, Operand(esp, -kDoubleSize)); |
+ __ fld(1); |
+ __ fstp_d(Operand(esp, 0)); |
+ __ mov(eax, MemOperand(esp, 4)); |
+ __ and_(eax, Immediate(0x80000000)); |
+ __ lea(esp, Operand(esp, kDoubleSize)); |
+ __ pop(eax); |
+ __ j(zero, &done_compare, Label::kNear); |
- __ bind(&return_right); |
- __ fxch(); |
+ __ bind(&compare_swap); |
+ __ bind(ool->exit()); |
+ __ fxch(1); |
- __ bind(&return_left); |
+ __ bind(&done_compare); |
__ fstp(0); |
__ lea(esp, Operand(esp, 2 * kDoubleSize)); |
break; |
} |
case kX87Float64Min: { |
- Label check_zero, return_left, return_right; |
- Condition condition = above; |
+ Label compare_swap, done_compare; |
if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
__ VerifyX87StackDepth(1); |
} |
@@ -1409,22 +1319,26 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
__ fld(1); |
__ fld(1); |
__ FCmp(); |
- __ j(parity_even, &return_right, |
- Label::kNear); // At least one NaN, return right value. |
- __ j(equal, &check_zero, Label::kNear); // left == right. |
- __ j(condition, &return_left, Label::kNear); |
- __ jmp(&return_right, Label::kNear); |
- __ bind(&check_zero); |
+ auto ool = new (zone()) OutOfLineLoadNaN(this, i.OutputDoubleRegister()); |
+ __ j(parity_even, ool->entry()); |
+ __ j(above, &done_compare, Label::kNear); |
+ __ j(below, &compare_swap, Label::kNear); |
+ __ push(eax); |
+ __ lea(esp, Operand(esp, -kDoubleSize)); |
__ fld(0); |
- __ fldz(); |
- __ FCmp(); |
- __ j(not_equal, &return_left, Label::kNear); // left == right != 0. |
+ __ fstp_d(Operand(esp, 0)); |
+ __ mov(eax, MemOperand(esp, 4)); |
+ __ and_(eax, Immediate(0x80000000)); |
+ __ lea(esp, Operand(esp, kDoubleSize)); |
+ __ pop(eax); |
+ __ j(zero, &done_compare, Label::kNear); |
- __ bind(&return_right); |
- __ fxch(); |
+ __ bind(&compare_swap); |
+ __ bind(ool->exit()); |
+ __ fxch(1); |
- __ bind(&return_left); |
+ __ bind(&done_compare); |
__ fstp(0); |
__ lea(esp, Operand(esp, 2 * kDoubleSize)); |
break; |