OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 2928 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2939 | 2939 |
2940 void MathPowStub::Generate(MacroAssembler* masm) { | 2940 void MathPowStub::Generate(MacroAssembler* masm) { |
2941 CpuFeatures::Scope use_sse2(SSE2); | 2941 CpuFeatures::Scope use_sse2(SSE2); |
2942 Factory* factory = masm->isolate()->factory(); | 2942 Factory* factory = masm->isolate()->factory(); |
2943 Label double_int_runtime, generic_runtime, done; | 2943 Label double_int_runtime, generic_runtime, done; |
2944 Label base_is_smi, unpack_exponent, exponent_not_smi, int_exponent; | 2944 Label base_is_smi, unpack_exponent, exponent_not_smi, int_exponent; |
2945 // Save 1 in xmm3 - we need this several times later on. | 2945 // Save 1 in xmm3 - we need this several times later on. |
2946 __ mov(ecx, Immediate(1)); | 2946 __ mov(ecx, Immediate(1)); |
2947 __ cvtsi2sd(xmm3, ecx); | 2947 __ cvtsi2sd(xmm3, ecx); |
2948 | 2948 |
2949 switch (exponent_type_) { | 2949 if (exponent_type_ == ON_STACK) { |
2950 case ON_STACK: | 2950 // The exponent (and base) are supplied as arguments on the stack. |
2951 // The exponent (and base) are supplied as arguments on the stack. | 2951 // This can only happen if the stub is called from non-optimized code. |
2952 // This can only happen if the stub is called from non-optimized code. | 2952 // Load input parameters from stack |
2953 // Load input parameters from stack | 2953 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
2954 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2954 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
2955 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 2955 // edx: base (smi or heap number) |
2956 // edx: base (smi or heap number) | 2956 // eax: exponent (smi or heap number) |
2957 // eax: exponent (smi or heap number) | 2957 __ JumpIfSmi(edx, &base_is_smi, Label::kNear); |
2958 __ JumpIfSmi(edx, &base_is_smi, Label::kNear); | 2958 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
2959 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2959 factory->heap_number_map()); |
2960 factory->heap_number_map()); | 2960 __ j(not_equal, &generic_runtime); |
2961 __ j(not_equal, &generic_runtime); | |
2962 | 2961 |
2963 // Check base for NaN or +/-Infinity | 2962 __ movdbl(xmm1, FieldOperand(edx, HeapNumber::kValueOffset)); |
2964 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); | 2963 __ jmp(&unpack_exponent, Label::kNear); |
2965 __ and_(ecx, HeapNumber::kExponentMask); | |
2966 __ cmp(ecx, Immediate(HeapNumber::kExponentMask)); | |
2967 __ j(equal, &generic_runtime); | |
2968 __ movdbl(xmm1, FieldOperand(edx, HeapNumber::kValueOffset)); | |
2969 __ jmp(&unpack_exponent, Label::kNear); | |
2970 | 2964 |
2971 __ bind(&base_is_smi); | 2965 __ bind(&base_is_smi); |
2972 __ SmiUntag(edx); | 2966 __ SmiUntag(edx); |
2973 __ cvtsi2sd(xmm1, edx); | 2967 __ cvtsi2sd(xmm1, edx); |
2974 __ bind(&unpack_exponent); | 2968 __ bind(&unpack_exponent); |
2975 | 2969 |
2976 __ JumpIfNotSmi(eax, &exponent_not_smi, Label::kNear); | 2970 __ JumpIfNotSmi(eax, &exponent_not_smi, Label::kNear); |
2977 __ SmiUntag(eax); | 2971 __ SmiUntag(eax); |
2978 __ jmp(&int_exponent); | 2972 __ jmp(&int_exponent); |
2979 | 2973 |
2980 __ bind(&exponent_not_smi); | 2974 __ bind(&exponent_not_smi); |
2981 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 2975 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
2982 factory->heap_number_map()); | 2976 factory->heap_number_map()); |
2983 __ j(not_equal, &generic_runtime); | 2977 __ j(not_equal, &generic_runtime); |
2984 __ movdbl(xmm2, FieldOperand(eax, HeapNumber::kValueOffset)); | 2978 __ movdbl(xmm2, FieldOperand(eax, HeapNumber::kValueOffset)); |
2985 break; | 2979 } else if (exponent_type_ == TAGGED) { |
| 2980 // xmm1: base as double |
| 2981 // eax: exponent (smi or heap number) |
| 2982 __ JumpIfNotSmi(eax, &exponent_not_smi, Label::kNear); |
| 2983 __ SmiUntag(eax); |
| 2984 __ jmp(&int_exponent); |
2986 | 2985 |
2987 case TAGGED: | 2986 __ bind(&exponent_not_smi); |
2988 // xmm1: base as double | 2987 __ movdbl(xmm2, FieldOperand(eax, HeapNumber::kValueOffset)); |
2989 // eax: exponent (smi or heap number) | |
2990 __ JumpIfNotSmi(eax, &exponent_not_smi, Label::kNear); | |
2991 __ SmiUntag(eax); | |
2992 __ jmp(&int_exponent); | |
2993 | |
2994 __ bind(&exponent_not_smi); | |
2995 __ movdbl(xmm2, FieldOperand(eax, HeapNumber::kValueOffset)); | |
2996 // Fall through intended | |
2997 case INTEGER: | |
2998 // xmm1: base as double | |
2999 // eax: exponent as untagged integer | |
3000 case DOUBLE: | |
3001 // xmm1: base as double | |
3002 // xmm2: exponent as double | |
3003 // Check base in xmm1 for NaN or +/-Infinity | |
3004 const int kExponentShift = kBitsPerByte * | |
3005 (HeapNumber::kExponentOffset - HeapNumber::kMantissaOffset); | |
3006 __ movsd(xmm4, xmm1); | |
3007 __ psrlq(xmm4, kExponentShift); | |
3008 __ movd(ecx, xmm4); | |
3009 __ and_(ecx, HeapNumber::kExponentMask); | |
3010 __ cmp(ecx, Immediate(HeapNumber::kExponentMask)); | |
3011 __ j(equal, &generic_runtime); | |
3012 break; | |
3013 } | 2988 } |
3014 | 2989 |
3015 if (exponent_type_ != INTEGER) { | 2990 if (exponent_type_ != INTEGER) { |
3016 Label not_minus_half, fast_power; | 2991 Label fast_power; |
3017 // xmm1: base as double that is not +/- Infinity or NaN | 2992 // xmm1: base as double that is not +/- Infinity or NaN |
3018 // xmm2: exponent as double | 2993 // xmm2: exponent as double |
3019 // Detect integer exponents stored as double. | 2994 // Detect integer exponents stored as double. |
3020 __ cvttsd2si(eax, Operand(xmm2)); | 2995 __ cvttsd2si(eax, Operand(xmm2)); |
3021 // Skip to runtime if possibly NaN (indicated by the indefinite integer). | 2996 // Skip to runtime if possibly NaN (indicated by the indefinite integer). |
3022 __ cmp(eax, Immediate(0x80000000u)); | 2997 __ cmp(eax, Immediate(0x80000000u)); |
3023 __ j(equal, &generic_runtime); | 2998 __ j(equal, &generic_runtime); |
3024 __ cvtsi2sd(xmm4, eax); | 2999 __ cvtsi2sd(xmm4, eax); |
3025 __ ucomisd(xmm2, xmm4); | 3000 __ ucomisd(xmm2, xmm4); |
3026 __ j(equal, &int_exponent); | 3001 __ j(equal, &int_exponent); |
3027 | 3002 |
3028 if (exponent_type_ == ON_STACK) { | 3003 if (exponent_type_ == ON_STACK) { |
3029 // Detect square root case. Crankshaft detects constant +/-0.5 at | 3004 // Detect square root case. Crankshaft detects constant +/-0.5 at |
3030 // compile time and uses DoMathPowHalf instead. We then skip this check | 3005 // compile time and uses DoMathPowHalf instead. We then skip this check |
3031 // for non-constant cases of +/-0.5 as these hardly occur. | 3006 // for non-constant cases of +/-0.5 as these hardly occur. |
| 3007 Label continue_sqrt, continue_rsqrt, not_plus_half; |
| 3008 // Test for 0.5. |
| 3009 // Load xmm4 with 0.5. |
| 3010 __ mov(ecx, Immediate(0x3F000000u)); |
| 3011 __ movd(xmm4, ecx); |
| 3012 __ cvtss2sd(xmm4, xmm4); |
| 3013 // xmm3 now has 0.5. |
| 3014 __ ucomisd(xmm4, xmm2); |
| 3015 __ j(not_equal, ¬_plus_half, Label::kNear); |
| 3016 |
| 3017 // Calculates square root. Check for the special case of |
| 3018 // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13). |
| 3019 // According to IEEE-754, single-precision -Infinity has the highest |
| 3020 // 9 bits set and the lowest 23 bits cleared. |
| 3021 __ mov(ecx, 0xFF800000u); |
| 3022 __ movd(xmm4, ecx); |
| 3023 __ cvtss2sd(xmm4, xmm4); |
| 3024 __ ucomisd(xmm1, xmm4); |
| 3025 __ j(not_equal, &continue_sqrt, Label::kNear); |
| 3026 |
| 3027 // Set result to Infinity in the special case. |
| 3028 __ xorps(xmm3, xmm3); |
| 3029 __ subsd(xmm3, xmm4); |
| 3030 __ jmp(&done); |
| 3031 |
| 3032 __ bind(&continue_sqrt); |
| 3033 // sqrtsd returns -0 when input is -0. ECMA spec requires +0. |
| 3034 __ xorps(xmm4, xmm4); |
| 3035 __ addsd(xmm4, xmm1); // Convert -0 to +0. |
| 3036 __ sqrtsd(xmm3, xmm4); |
| 3037 __ jmp(&done); |
3032 | 3038 |
3033 // Test for -0.5. | 3039 // Test for -0.5. |
3034 // Load xmm4 with -0.5. | 3040 __ bind(¬_plus_half); |
3035 __ mov(ecx, Immediate(0xBF000000u)); | 3041 // Load xmm2 with -0.5. |
| 3042 // Since xmm3 is 1 and xmm4 is 0.5 this is simply xmm4 - xmm3. |
| 3043 __ subsd(xmm4, xmm3); |
| 3044 // xmm2 now has -0.5. |
| 3045 __ ucomisd(xmm4, xmm2); |
| 3046 __ j(not_equal, &fast_power, Label::kNear); |
| 3047 |
| 3048 // Calculates reciprocal of square root. Check for the special case of |
| 3049 // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13). |
| 3050 // According to IEEE-754, single-precision -Infinity has the highest |
| 3051 // 9 bits set and the lowest 23 bits cleared. |
| 3052 __ mov(ecx, 0xFF800000u); |
3036 __ movd(xmm4, ecx); | 3053 __ movd(xmm4, ecx); |
3037 __ cvtss2sd(xmm4, xmm4); | 3054 __ cvtss2sd(xmm4, xmm4); |
3038 // xmm3 now has -0.5. | 3055 __ ucomisd(xmm1, xmm4); |
3039 __ ucomisd(xmm4, xmm2); | 3056 __ j(not_equal, &continue_rsqrt, Label::kNear); |
3040 __ j(not_equal, ¬_minus_half, Label::kNear); | |
3041 | 3057 |
3042 // Calculates reciprocal of square root.eax | 3058 // Set result to 0 in the special case. |
| 3059 __ xorps(xmm3, xmm3); |
| 3060 __ jmp(&done); |
| 3061 |
| 3062 __ bind(&continue_rsqrt); |
3043 // sqrtsd returns -0 when input is -0. ECMA spec requires +0. | 3063 // sqrtsd returns -0 when input is -0. ECMA spec requires +0. |
3044 __ xorps(xmm2, xmm2); | 3064 __ xorps(xmm2, xmm2); |
3045 __ addsd(xmm2, xmm1); | 3065 __ addsd(xmm2, xmm1); // Convert -0 to +0. |
3046 __ sqrtsd(xmm2, xmm2); | 3066 __ sqrtsd(xmm2, xmm2); |
3047 __ divsd(xmm3, xmm2); | 3067 __ divsd(xmm3, xmm2); |
3048 __ jmp(&done); | 3068 __ jmp(&done); |
3049 | |
3050 // Test for 0.5. | |
3051 __ bind(¬_minus_half); | |
3052 // Load xmm2 with 0.5. | |
3053 // Since xmm3 is 1 and xmm4 is -0.5 this is simply xmm4 + xmm3. | |
3054 __ addsd(xmm4, xmm3); | |
3055 // xmm2 now has 0.5. | |
3056 __ ucomisd(xmm4, xmm2); | |
3057 __ j(not_equal, &fast_power, Label::kNear); | |
3058 // Calculates square root. | |
3059 // sqrtsd returns -0 when input is -0. ECMA spec requires +0. | |
3060 __ xorps(xmm4, xmm4); | |
3061 __ addsd(xmm4, xmm1); | |
3062 __ sqrtsd(xmm3, xmm4); | |
3063 __ jmp(&done); | |
3064 } | 3069 } |
3065 | 3070 |
3066 // Using FPU instructions to calculate power. | 3071 // Using FPU instructions to calculate power. |
3067 Label fast_power_failed; | 3072 Label fast_power_failed; |
3068 __ bind(&fast_power); | 3073 __ bind(&fast_power); |
3069 __ fnclex(); // Clear flags to catch exceptions later. | 3074 __ fnclex(); // Clear flags to catch exceptions later. |
3070 // Transfer (B)ase and (E)xponent onto the FPU register stack. | 3075 // Transfer (B)ase and (E)xponent onto the FPU register stack. |
3071 __ sub(esp, Immediate(kDoubleSize)); | 3076 __ sub(esp, Immediate(kDoubleSize)); |
3072 __ movdbl(Operand(esp, 0), xmm2); | 3077 __ movdbl(Operand(esp, 0), xmm2); |
3073 __ fld_d(Operand(esp, 0)); // E | 3078 __ fld_d(Operand(esp, 0)); // E |
(...skipping 4205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7279 false); | 7284 false); |
7280 __ pop(edx); | 7285 __ pop(edx); |
7281 __ ret(0); | 7286 __ ret(0); |
7282 } | 7287 } |
7283 | 7288 |
7284 #undef __ | 7289 #undef __ |
7285 | 7290 |
7286 } } // namespace v8::internal | 7291 } } // namespace v8::internal |
7287 | 7292 |
7288 #endif // V8_TARGET_ARCH_IA32 | 7293 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |