Index: src/codegen-ia32.cc |
=================================================================== |
--- src/codegen-ia32.cc (revision 1324) |
+++ src/codegen-ia32.cc (working copy) |
@@ -4482,31 +4482,63 @@ |
FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx); |
FloatingPointHelper::LoadFloatOperands(masm, ecx); |
- Label non_int32_operands, non_smi_result, skip_allocation; |
- // Reserve space for converted numbers. |
- __ sub(Operand(esp), Immediate(2 * kPointerSize)); |
+ Label non_smi_result, skip_allocation, operands_too_large; |
- // Check if right operand is int32. |
- __ fist_s(Operand(esp, 1 * kPointerSize)); |
- __ fild_s(Operand(esp, 1 * kPointerSize)); |
- __ fucompp(); |
+ // Make sure that the operands can be truncated into 64-bit |
+ // integers. Otherwise, the fistt instruction will signal an IA |
+ // exception which will cause us to overwrite the operand with |
+ // zero. |
+ __ push(Immediate(0x7fffffff)); |
+ __ push(Immediate(-1)); |
+ __ fild_d(Operand(esp, 0)); |
+ __ add(Operand(esp), Immediate(2 * kPointerSize)); |
+ |
+ // Convert the operands to absolute values before comparing |
+ // against the limit. |
+ __ fld(2); |
+ __ fabs(); |
+ __ fld(2); |
+ __ fabs(); |
+ |
+ // Do the comparison. If the operands are too large we go |
+ // slow-case through the runtime system. |
+ __ fucomp(2); |
__ fnstsw_ax(); |
__ sahf(); |
- __ j(not_zero, &non_int32_operands); |
- __ j(parity_even, &non_int32_operands); |
- |
- // Check if left operand is int32. |
- __ fist_s(Operand(esp, 0 * kPointerSize)); |
- __ fild_s(Operand(esp, 0 * kPointerSize)); |
+ __ j(above, &operands_too_large); |
__ fucompp(); |
__ fnstsw_ax(); |
__ sahf(); |
- __ j(not_zero, &non_int32_operands); |
- __ j(parity_even, &non_int32_operands); |
+ __ j(above, &operands_too_large); |
+ // Reserve space for converted numbers. |
+ __ sub(Operand(esp), Immediate(4 * kPointerSize)); |
+ |
+ // Convert right operand to int32. |
+ Label done_right; |
+ __ fnclex(); |
+ __ fisttp_d(Operand(esp, 2 * kPointerSize)); |
Erik Corry
2009/02/20 16:40:41
This is an SSE3 instruction :-(. I guess we can s
|
+ __ fnstsw_ax(); |
+ __ test(eax, Immediate(1)); |
+ __ j(zero, &done_right); |
+ __ fnclex(); |
+ __ mov(Operand(esp, 2 * kPointerSize), Immediate(0)); |
+ __ bind(&done_right); |
+ |
+ // Convert left operand to int32. |
+ Label done_left; |
+ __ fisttp_d(Operand(esp, 0 * kPointerSize)); |
+ __ fnstsw_ax(); |
+ __ test(eax, Immediate(1)); |
+ __ j(zero, &done_left); |
+ __ mov(Operand(esp, 0 * kPointerSize), Immediate(0)); |
+ __ bind(&done_left); |
+ |
// Get int32 operands and perform bitop. |
__ pop(eax); |
+ __ add(Operand(esp), Immediate(kPointerSize)); |
__ pop(ecx); |
+ __ add(Operand(esp), Immediate(kPointerSize)); |
switch (op_) { |
case Token::BIT_OR: __ or_(eax, Operand(ecx)); break; |
case Token::BIT_AND: __ and_(eax, Operand(ecx)); break; |
@@ -4554,10 +4586,11 @@ |
__ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
__ ret(2 * kPointerSize); |
} |
- __ bind(&non_int32_operands); |
- // Restore stacks and operands before calling runtime. |
+ |
+ // Free ST(0) and ST(1) before calling runtime. |
+ __ bind(&operands_too_large); |
__ ffree(0); |
- __ add(Operand(esp), Immediate(2 * kPointerSize)); |
+ __ ffree(1); |
// SHR should return uint32 - go to runtime for non-smi/negative result. |
if (op_ == Token::SHR) __ bind(&non_smi_result); |