Index: src/ia32/code-stubs-ia32.cc |
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc |
index 6bea2dc685c8329dcb53eab5cd7cf3b0f7d6d859..35c24e2f8989e0868be09cdd872290e8b5eedb14 100644 |
--- a/src/ia32/code-stubs-ia32.cc |
+++ b/src/ia32/code-stubs-ia32.cc |
@@ -2940,64 +2940,72 @@ void FloatingPointHelper::CheckFloatOperandsAreInt32(MacroAssembler* masm, |
void MathPowStub::Generate(MacroAssembler* masm) { |
CpuFeatures::Scope use_sse2(SSE2); |
Factory* factory = masm->isolate()->factory(); |
+ const Register exponent = eax; |
+ const Register base = edx; |
+ const Register scratch = ecx; |
+ const XMMRegister double_result = xmm3; |
+ const XMMRegister double_base = xmm2; |
+ const XMMRegister double_exponent = xmm1; |
+ const XMMRegister double_scratch = xmm4; |
+ |
Label double_int_runtime, generic_runtime, done; |
- Label base_is_smi, unpack_exponent, exponent_not_smi, int_exponent; |
- // Save 1 in xmm3 - we need this several times later on. |
- __ mov(ecx, Immediate(1)); |
- __ cvtsi2sd(xmm3, ecx); |
+ Label exponent_not_smi, int_exponent; |
+ |
+ // Save 1 in double_result - we need this several times later on. |
+ __ mov(scratch, Immediate(1)); |
+ __ cvtsi2sd(double_result, scratch); |
if (exponent_type_ == ON_STACK) { |
- // The exponent (and base) are supplied as arguments on the stack. |
+ Label base_is_smi, unpack_exponent; |
+ // The exponent and base are supplied as arguments on the stack. |
// This can only happen if the stub is called from non-optimized code. |
- // Load input parameters from stack |
- __ mov(edx, Operand(esp, 2 * kPointerSize)); |
- __ mov(eax, Operand(esp, 1 * kPointerSize)); |
- // edx: base (smi or heap number) |
- // eax: exponent (smi or heap number) |
- __ JumpIfSmi(edx, &base_is_smi, Label::kNear); |
- __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
+ // Load input parameters from stack. |
+ __ mov(base, Operand(esp, 2 * kPointerSize)); |
+ __ mov(exponent, Operand(esp, 1 * kPointerSize)); |
+ |
+ __ JumpIfSmi(base, &base_is_smi, Label::kNear); |
+ __ cmp(FieldOperand(base, HeapObject::kMapOffset), |
factory->heap_number_map()); |
__ j(not_equal, &generic_runtime); |
- __ movdbl(xmm1, FieldOperand(edx, HeapNumber::kValueOffset)); |
+ __ movdbl(double_base, FieldOperand(base, HeapNumber::kValueOffset)); |
__ jmp(&unpack_exponent, Label::kNear); |
__ bind(&base_is_smi); |
- __ SmiUntag(edx); |
- __ cvtsi2sd(xmm1, edx); |
+ __ SmiUntag(base); |
+ __ cvtsi2sd(double_base, base); |
__ bind(&unpack_exponent); |
- __ JumpIfNotSmi(eax, &exponent_not_smi, Label::kNear); |
- __ SmiUntag(eax); |
+ __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); |
+ __ SmiUntag(exponent); |
__ jmp(&int_exponent); |
__ bind(&exponent_not_smi); |
- __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
+ __ cmp(FieldOperand(exponent, HeapObject::kMapOffset), |
factory->heap_number_map()); |
__ j(not_equal, &generic_runtime); |
- __ movdbl(xmm2, FieldOperand(eax, HeapNumber::kValueOffset)); |
+ __ movdbl(double_exponent, |
+ FieldOperand(exponent, HeapNumber::kValueOffset)); |
} else if (exponent_type_ == TAGGED) { |
- // xmm1: base as double |
- // eax: exponent (smi or heap number) |
- __ JumpIfNotSmi(eax, &exponent_not_smi, Label::kNear); |
- __ SmiUntag(eax); |
+ __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); |
+ __ SmiUntag(exponent); |
__ jmp(&int_exponent); |
__ bind(&exponent_not_smi); |
- __ movdbl(xmm2, FieldOperand(eax, HeapNumber::kValueOffset)); |
+ __ movdbl(double_exponent, |
+ FieldOperand(exponent, HeapNumber::kValueOffset)); |
} |
if (exponent_type_ != INTEGER) { |
Label fast_power; |
- // xmm1: base as double that is not +/- Infinity or NaN |
- // xmm2: exponent as double |
// Detect integer exponents stored as double. |
- __ cvttsd2si(eax, Operand(xmm2)); |
+ __ cvttsd2si(exponent, Operand(double_exponent)); |
// Skip to runtime if possibly NaN (indicated by the indefinite integer). |
- __ cmp(eax, Immediate(0x80000000u)); |
+ __ cmp(exponent, Immediate(0x80000000u)); |
__ j(equal, &generic_runtime); |
- __ cvtsi2sd(xmm4, eax); |
- __ ucomisd(xmm2, xmm4); // Already ruled out NaNs for exponent. |
+ __ cvtsi2sd(double_scratch, exponent); |
+ // Already ruled out NaNs for exponent. |
+ __ ucomisd(double_exponent, double_scratch); |
__ j(equal, &int_exponent); |
if (exponent_type_ == ON_STACK) { |
@@ -3006,71 +3014,70 @@ void MathPowStub::Generate(MacroAssembler* masm) { |
// for non-constant cases of +/-0.5 as these hardly occur. |
Label continue_sqrt, continue_rsqrt, not_plus_half; |
// Test for 0.5. |
- // Load xmm4 with 0.5. |
- __ mov(ecx, Immediate(0x3F000000u)); |
- __ movd(xmm4, ecx); |
- __ cvtss2sd(xmm4, xmm4); |
- // xmm4 now has 0.5. |
- __ ucomisd(xmm4, xmm2); // Already ruled out NaNs for exponent. |
+ // Load double_scratch with 0.5. |
+ __ mov(scratch, Immediate(0x3F000000u)); |
+ __ movd(double_scratch, scratch); |
+ __ cvtss2sd(double_scratch, double_scratch); |
+ // Already ruled out NaNs for exponent. |
+ __ ucomisd(double_scratch, double_exponent); |
__ j(not_equal, ¬_plus_half, Label::kNear); |
// Calculates square root of base. Check for the special case of |
// Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13). |
// According to IEEE-754, single-precision -Infinity has the highest |
// 9 bits set and the lowest 23 bits cleared. |
- __ mov(ecx, 0xFF800000u); |
- __ movd(xmm4, ecx); |
- __ cvtss2sd(xmm4, xmm4); |
- __ ucomisd(xmm1, xmm4); |
+ __ mov(scratch, 0xFF800000u); |
+ __ movd(double_scratch, scratch); |
+ __ cvtss2sd(double_scratch, double_scratch); |
+ __ ucomisd(double_base, double_scratch); |
// Comparing -Infinity with NaN results in "unordered", which sets the |
// zero flag as if both were equal. However, it also sets the carry flag. |
__ j(not_equal, &continue_sqrt, Label::kNear); |
__ j(carry, &continue_sqrt, Label::kNear); |
// Set result to Infinity in the special case. |
- __ xorps(xmm3, xmm3); |
- __ subsd(xmm3, xmm4); |
+ __ xorps(double_result, double_result); |
+ __ subsd(double_result, double_scratch); |
__ jmp(&done); |
__ bind(&continue_sqrt); |
// sqrtsd returns -0 when input is -0. ECMA spec requires +0. |
- __ xorps(xmm4, xmm4); |
- __ addsd(xmm4, xmm1); // Convert -0 to +0. |
- __ sqrtsd(xmm3, xmm4); |
+ __ xorps(double_scratch, double_scratch); |
+ __ addsd(double_scratch, double_base); // Convert -0 to +0. |
+ __ sqrtsd(double_result, double_scratch); |
__ jmp(&done); |
// Test for -0.5. |
__ bind(¬_plus_half); |
- // Load xmm2 with -0.5. |
- // Since xmm3 is 1 and xmm4 is 0.5 this is simply xmm4 - xmm3. |
- __ subsd(xmm4, xmm3); |
- // xmm4 now has -0.5. |
- __ ucomisd(xmm4, xmm2); // Already ruled out NaNs for exponent. |
+ // Load double_exponent with -0.5 by substracting 1. |
+ __ subsd(double_scratch, double_result); |
+ // Already ruled out NaNs for exponent. |
+ __ ucomisd(double_scratch, double_exponent); |
__ j(not_equal, &fast_power, Label::kNear); |
// Calculates reciprocal of square root of base. Check for the special |
// case of Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13). |
// According to IEEE-754, single-precision -Infinity has the highest |
// 9 bits set and the lowest 23 bits cleared. |
- __ mov(ecx, 0xFF800000u); |
- __ movd(xmm4, ecx); |
- __ cvtss2sd(xmm4, xmm4); |
- __ ucomisd(xmm1, xmm4); |
+ __ mov(scratch, 0xFF800000u); |
+ __ movd(double_scratch, scratch); |
+ __ cvtss2sd(double_scratch, double_scratch); |
+ __ ucomisd(double_base, double_scratch); |
// Comparing -Infinity with NaN results in "unordered", which sets the |
// zero flag as if both were equal. However, it also sets the carry flag. |
__ j(not_equal, &continue_rsqrt, Label::kNear); |
__ j(carry, &continue_rsqrt, Label::kNear); |
// Set result to 0 in the special case. |
- __ xorps(xmm3, xmm3); |
+ __ xorps(double_result, double_result); |
__ jmp(&done); |
__ bind(&continue_rsqrt); |
// sqrtsd returns -0 when input is -0. ECMA spec requires +0. |
- __ xorps(xmm2, xmm2); |
- __ addsd(xmm2, xmm1); // Convert -0 to +0. |
- __ sqrtsd(xmm2, xmm2); |
- __ divsd(xmm3, xmm2); |
+ __ xorps(double_exponent, double_exponent); |
+ __ addsd(double_exponent, double_base); // Convert -0 to +0. |
+ __ sqrtsd(double_exponent, double_exponent); |
+ __ divsd(double_result, double_exponent); |
__ jmp(&done); |
} |
@@ -3080,9 +3087,9 @@ void MathPowStub::Generate(MacroAssembler* masm) { |
__ fnclex(); // Clear flags to catch exceptions later. |
// Transfer (B)ase and (E)xponent onto the FPU register stack. |
__ sub(esp, Immediate(kDoubleSize)); |
- __ movdbl(Operand(esp, 0), xmm2); |
+ __ movdbl(Operand(esp, 0), double_exponent); |
__ fld_d(Operand(esp, 0)); // E |
- __ movdbl(Operand(esp, 0), xmm1); |
+ __ movdbl(Operand(esp, 0), double_base); |
__ fld_d(Operand(esp, 0)); // B, E |
// Exponent is in st(1) and base is in st(0) |
@@ -3102,10 +3109,10 @@ void MathPowStub::Generate(MacroAssembler* masm) { |
__ fstp(1); |
// Bail out to runtime in case of exceptions in the status word. |
__ fnstsw_ax(); |
- __ test_b(eax, 0x5F); // We check for all but precision exception. |
+ __ test_b(exponent, 0x5F); // We check for all but precision exception. |
__ j(not_zero, &fast_power_failed, Label::kNear); |
__ fstp_d(Operand(esp, 0)); |
- __ movdbl(xmm3, Operand(esp, 0)); |
+ __ movdbl(double_result, Operand(esp, 0)); |
__ add(esp, Immediate(kDoubleSize)); |
__ jmp(&done); |
@@ -3117,49 +3124,46 @@ void MathPowStub::Generate(MacroAssembler* masm) { |
// Calculate power with integer exponent. |
__ bind(&int_exponent); |
- // xmm1: base as double that is not +/- Infinity or NaN |
- // eax: exponent as untagged integer |
- __ mov(ecx, eax); // Back up exponent. |
- __ movsd(xmm4, xmm1); // Back up base. |
- __ movsd(xmm2, xmm3); // Load xmm2 with 1. |
- |
+ const XMMRegister double_scratch2 = double_exponent; |
+ __ mov(scratch, exponent); // Back up exponent. |
+ __ movsd(double_scratch, double_base); // Back up base. |
+ __ movsd(double_scratch2, double_result); // Load double_exponent with 1. |
// Get absolute value of exponent. |
Label no_neg, while_true, no_multiply; |
- __ cmp(eax, 0); |
+ __ cmp(exponent, 0); |
__ j(greater_equal, &no_neg, Label::kNear); |
- __ neg(eax); |
+ __ neg(exponent); |
__ bind(&no_neg); |
__ bind(&while_true); |
- __ shr(eax, 1); |
+ __ shr(exponent, 1); |
__ j(not_carry, &no_multiply, Label::kNear); |
- __ mulsd(xmm3, xmm1); |
+ __ mulsd(double_result, double_base); |
__ bind(&no_multiply); |
- __ mulsd(xmm1, xmm1); |
+ __ mulsd(double_base, double_base); |
__ j(not_zero, &while_true); |
- // base has the original value of the exponent - if the exponent is |
- // negative return 1/result. |
- __ test(ecx, ecx); |
+ // scratch has the original value of the exponent - if the exponent is |
+ // negative, return 1/result. |
+ __ test(scratch, scratch); |
__ j(positive, &done); |
- __ divsd(xmm2, xmm3); |
- __ movsd(xmm3, xmm2); |
+ __ divsd(double_scratch2, double_result); |
+ __ movsd(double_result, double_scratch2); |
// Test whether result is zero. Bail out to check for subnormal result. |
// Due to subnormals, x^-y == (1/x)^y does not hold in all cases. |
- __ xorps(xmm2, xmm2); |
- __ ucomisd(xmm2, xmm3); // Result cannot be NaN. |
+ __ xorps(double_scratch2, double_scratch2); |
+ __ ucomisd(double_scratch2, double_result); // Result cannot be NaN. |
__ j(equal, &double_int_runtime); |
// Returning or bailing out. |
if (exponent_type_ == ON_STACK) { |
// The stub is called from non-optimized code, which expects the result |
- // as heap number in eax. |
+ // as heap number in exponent. |
__ bind(&done); |
- // xmm3: result |
- __ AllocateHeapNumber(eax, ecx, edx, &generic_runtime); |
- __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm3); |
+ __ AllocateHeapNumber(exponent, scratch, base, &generic_runtime); |
+ __ movdbl(FieldOperand(exponent, HeapNumber::kValueOffset), double_result); |
__ ret(2 * kPointerSize); |
// The arguments are still on the stack. |
@@ -3170,28 +3174,23 @@ void MathPowStub::Generate(MacroAssembler* masm) { |
__ jmp(&done); |
Label return_from_runtime; |
- StubRuntimeCallHelper callhelper; |
__ bind(&generic_runtime); |
- // xmm1: base |
- // xmm2: exponent |
{ |
AllowExternalCallThatCantCauseGC scope(masm); |
- __ PrepareCallCFunction(4, eax); |
- __ movdbl(Operand(esp, 0 * kDoubleSize), xmm1); |
- __ movdbl(Operand(esp, 1 * kDoubleSize), xmm2); |
+ __ PrepareCallCFunction(4, exponent); |
+ __ movdbl(Operand(esp, 0 * kDoubleSize), double_base); |
+ __ movdbl(Operand(esp, 1 * kDoubleSize), double_exponent); |
__ CallCFunction( |
ExternalReference::power_double_double_function(masm->isolate()), 4); |
} |
__ jmp(&return_from_runtime, Label::kNear); |
__ bind(&double_int_runtime); |
- // xmm4: base |
- // ecx: exponent |
{ |
AllowExternalCallThatCantCauseGC scope(masm); |
- __ PrepareCallCFunction(4, eax); |
- __ movdbl(Operand(esp, 0 * kDoubleSize), xmm4); |
- __ mov(Operand(esp, 1 * kDoubleSize), ecx); |
+ __ PrepareCallCFunction(4, exponent); |
+ __ movdbl(Operand(esp, 0 * kDoubleSize), double_scratch); |
+ __ mov(Operand(esp, 1 * kDoubleSize), scratch); |
__ CallCFunction( |
ExternalReference::power_double_int_function(masm->isolate()), 4); |
} |
@@ -3201,10 +3200,9 @@ void MathPowStub::Generate(MacroAssembler* masm) { |
// Store it into the (fixed) result register. |
__ sub(esp, Immediate(kDoubleSize)); |
__ fstp_d(Operand(esp, 0)); |
- __ movdbl(xmm3, Operand(esp, 0)); |
+ __ movdbl(double_result, Operand(esp, 0)); |
__ add(esp, Immediate(kDoubleSize)); |
- // xmm3: result |
__ bind(&done); |
__ ret(0); |
} |