Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 2226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2237 DeoptimizeIf(equal, instr->environment()); | 2237 DeoptimizeIf(equal, instr->environment()); |
| 2238 } | 2238 } |
| 2239 | 2239 |
| 2240 | 2240 |
| 2241 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { | 2241 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
| 2242 XMMRegister xmm_scratch = xmm0; | 2242 XMMRegister xmm_scratch = xmm0; |
| 2243 Register output_reg = ToRegister(instr->result()); | 2243 Register output_reg = ToRegister(instr->result()); |
| 2244 XMMRegister input_reg = ToDoubleRegister(instr->input()); | 2244 XMMRegister input_reg = ToDoubleRegister(instr->input()); |
| 2245 | 2245 |
| 2246 // xmm_scratch = 0.5 | 2246 // xmm_scratch = 0.5 |
| 2247 ExternalReference one_half = ExternalReference::address_of_one_half(); | 2247 ExternalReference one_half = ExternalReference::address_of_one_half(); |
|
Erik Corry
2011/01/04 22:33:00
Here's how to load a constant into an XMM register
| |
| 2248 __ movdbl(xmm_scratch, Operand::StaticVariable(one_half)); | 2248 __ movdbl(xmm_scratch, Operand::StaticVariable(one_half)); |
| 2249 | 2249 |
| 2250 // input = input + 0.5 | 2250 // input = input + 0.5 |
| 2251 __ addsd(input_reg, xmm_scratch); | 2251 __ addsd(input_reg, xmm_scratch); |
| 2252 | 2252 |
| 2253 // We need to return -0 for the input range [-0.5, 0[, otherwise | 2253 // We need to return -0 for the input range [-0.5, 0[, otherwise |
| 2254 // compute Math.floor(value + 0.5). | 2254 // compute Math.floor(value + 0.5). |
| 2255 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 2255 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 2256 __ ucomisd(input_reg, xmm_scratch); | 2256 __ ucomisd(input_reg, xmm_scratch); |
| 2257 DeoptimizeIf(below_equal, instr->environment()); | 2257 DeoptimizeIf(below_equal, instr->environment()); |
| (...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2878 __ add(Operand(esp), Immediate(kDoubleSize)); | 2878 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 2879 DeoptimizeIf(no_condition, instr->environment()); | 2879 DeoptimizeIf(no_condition, instr->environment()); |
| 2880 __ bind(&convert); | 2880 __ bind(&convert); |
| 2881 // Do conversion, which cannot fail because we checked the exponent. | 2881 // Do conversion, which cannot fail because we checked the exponent. |
| 2882 __ fld_d(Operand(esp, 0)); | 2882 __ fld_d(Operand(esp, 0)); |
| 2883 __ fisttp_d(Operand(esp, 0)); | 2883 __ fisttp_d(Operand(esp, 0)); |
| 2884 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. | 2884 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. |
| 2885 __ add(Operand(esp), Immediate(kDoubleSize)); | 2885 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 2886 __ bind(&done); | 2886 __ bind(&done); |
| 2887 } else { | 2887 } else { |
| 2888 // This will bail out if the input was not in the int32 range (or, | 2888 NearLabel done; |
| 2889 // unfortunately, if the input was 0x80000000). | 2889 Register temp_reg = ToRegister(instr->temporary()); |
| 2890 DeoptimizeIf(equal, instr->environment()); | 2890 XMMRegister xmm_scratch = xmm0; |
| 2891 | |
| 2892 __ j(not_equal, &done); | |
| 2893 | |
| 2894 // Get high 32 bits of the input in temp_reg. | |
| 2895 __ pshufd(xmm_scratch, input_reg, 1); | |
| 2896 __ movd(Operand(temp_reg), xmm_scratch); | |
| 2897 | |
| 2898 // Zero out the sign and the exponent in the input (by shifting | |
| 2899 // it to the left) and restore the implicit mantissa bit, | |
| 2900 // i.e. convert the input to unsigned int64 shifted left by | |
| 2901 // kExponentBits. | |
| 2902 __ mov(result_reg, 1); | |
| 2903 __ movd(xmm_scratch, Operand(result_reg)); | |
| 2904 __ psllq(xmm_scratch, kDoubleSize * kBitsPerByte - 1); | |
|
Erik Corry
2011/01/04 22:33:00
It might be faster to load xmm_scratch using the t
| |
| 2905 __ psllq(input_reg, HeapNumber::kExponentBits); | |
| 2906 __ por(input_reg, xmm_scratch); | |
| 2907 | |
| 2908 // Restore high 32 bits of the input in result_reg. | |
| 2909 __ mov(result_reg, temp_reg); | |
| 2910 | |
| 2911 // Prepare negation mask in temp_reg. | |
| 2912 __ sar(temp_reg, kBitsPerInt - 1); | |
| 2913 | |
| 2914 // Extract the exponent from result_reg and subtract adjusted | |
| 2915 // bias from it. The adjustment is selected in a way such that | |
| 2916 // when the difference is zero, the answer is in the low 32 bits | |
| 2917 // of the input, otherwise a shift has to be performed. | |
| 2918 __ shr(result_reg, HeapNumber::kExponentShift); | |
| 2919 __ and_(result_reg, | |
| 2920 HeapNumber::kExponentMask >> HeapNumber::kExponentShift); | |
| 2921 __ sub(Operand(result_reg), | |
| 2922 Immediate(HeapNumber::kExponentBias + | |
| 2923 HeapNumber::kExponentBits + | |
| 2924 HeapNumber::kMantissaBits)); | |
| 2925 // Don't handle big (or special) exponents. | |
|
Erik Corry
2011/01/04 22:33:00
Could you add a comment describing the range handl
| |
| 2926 DeoptimizeIf(greater_equal, instr->environment()); | |
| 2927 | |
| 2928 // Get the amount to shift the input right in xmm_scratch. | |
| 2929 __ neg(result_reg); | |
| 2930 __ movd(xmm_scratch, Operand(result_reg)); | |
| 2931 | |
| 2932 // Shift the input right and extract low 32 bits. | |
| 2933 __ psrlq(input_reg, xmm_scratch); | |
| 2934 __ movd(Operand(result_reg), input_reg); | |
| 2935 | |
| 2936 // Use the prepared mask in temp_reg to negate the result if necessary. | |
| 2937 __ xor_(result_reg, Operand(temp_reg)); | |
| 2938 __ sub(result_reg, Operand(temp_reg)); | |
|
Erik Corry
2011/01/04 22:33:00
ooh, nice!
| |
| 2939 __ bind(&done); | |
| 2891 } | 2940 } |
| 2892 } else { | 2941 } else { |
| 2893 NearLabel done; | 2942 NearLabel done; |
| 2894 __ cvttsd2si(result_reg, Operand(input_reg)); | 2943 __ cvttsd2si(result_reg, Operand(input_reg)); |
| 2895 __ cvtsi2sd(xmm0, Operand(result_reg)); | 2944 __ cvtsi2sd(xmm0, Operand(result_reg)); |
| 2896 __ ucomisd(xmm0, input_reg); | 2945 __ ucomisd(xmm0, input_reg); |
| 2897 DeoptimizeIf(not_equal, instr->environment()); | 2946 DeoptimizeIf(not_equal, instr->environment()); |
| 2898 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 2947 DeoptimizeIf(parity_even, instr->environment()); // NaN. |
| 2899 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 2948 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 2900 // The integer converted back is equal to the original. We | 2949 // The integer converted back is equal to the original. We |
| (...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3300 ASSERT(!environment->HasBeenRegistered()); | 3349 ASSERT(!environment->HasBeenRegistered()); |
| 3301 RegisterEnvironmentForDeoptimization(environment); | 3350 RegisterEnvironmentForDeoptimization(environment); |
| 3302 ASSERT(osr_pc_offset_ == -1); | 3351 ASSERT(osr_pc_offset_ == -1); |
| 3303 osr_pc_offset_ = masm()->pc_offset(); | 3352 osr_pc_offset_ = masm()->pc_offset(); |
| 3304 } | 3353 } |
| 3305 | 3354 |
| 3306 | 3355 |
| 3307 #undef __ | 3356 #undef __ |
| 3308 | 3357 |
| 3309 } } // namespace v8::internal | 3358 } } // namespace v8::internal |
| OLD | NEW |