OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X87 | 7 #if V8_TARGET_ARCH_X87 |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 3957 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3968 __ fld(0); | 3968 __ fld(0); |
3969 __ fadd_d(Operand::StaticVariable(one_half)); | 3969 __ fadd_d(Operand::StaticVariable(one_half)); |
3970 // rc=11B, round toward zero. | 3970 // rc=11B, round toward zero. |
3971 __ X87SetRC(0x0c00); | 3971 __ X87SetRC(0x0c00); |
3972 __ sub(esp, Immediate(kPointerSize)); | 3972 __ sub(esp, Immediate(kPointerSize)); |
3973 // Clear exception bits. | 3973 // Clear exception bits. |
3974 __ fnclex(); | 3974 __ fnclex(); |
3975 __ fistp_s(MemOperand(esp, 0)); | 3975 __ fistp_s(MemOperand(esp, 0)); |
3976 // Check overflow. | 3976 // Check overflow. |
3977 __ X87CheckIA(); | 3977 __ X87CheckIA(); |
3978 __ RecordComment("D2I conversion overflow"); | |
3979 __ pop(result); | 3978 __ pop(result); |
3980 DeoptimizeIf(equal, instr); | 3979 DeoptimizeIf(equal, instr, "conversion overflow"); |
3981 __ fnclex(); | 3980 __ fnclex(); |
3982 // Restore round mode. | 3981 // Restore round mode. |
3983 __ X87SetRC(0x0000); | 3982 __ X87SetRC(0x0000); |
3984 __ jmp(&done); | 3983 __ jmp(&done); |
3985 | 3984 |
3986 __ bind(&below_one_half); | 3985 __ bind(&below_one_half); |
3987 __ fld_d(Operand::StaticVariable(minus_one_half)); | 3986 __ fld_d(Operand::StaticVariable(minus_one_half)); |
3988 __ fld(1); | 3987 __ fld(1); |
3989 __ FCmp(); | 3988 __ FCmp(); |
3990 __ j(carry, &below_minus_one_half); | 3989 __ j(carry, &below_minus_one_half); |
3991 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if | 3990 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if |
3992 // we can ignore the difference between a result of -0 and +0. | 3991 // we can ignore the difference between a result of -0 and +0. |
3993 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3992 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3994 // If the sign is positive, we return +0. | 3993 // If the sign is positive, we return +0. |
3995 __ fld(0); | 3994 __ fld(0); |
3996 __ FXamSign(); | 3995 __ FXamSign(); |
3997 __ RecordComment("Minus zero"); | 3996 DeoptimizeIf(not_zero, instr, "minus zero"); |
3998 DeoptimizeIf(not_zero, instr); | |
3999 } | 3997 } |
4000 __ Move(result, Immediate(0)); | 3998 __ Move(result, Immediate(0)); |
4001 __ jmp(&done); | 3999 __ jmp(&done); |
4002 | 4000 |
4003 __ bind(&below_minus_one_half); | 4001 __ bind(&below_minus_one_half); |
4004 __ fld(0); | 4002 __ fld(0); |
4005 __ fadd_d(Operand::StaticVariable(one_half)); | 4003 __ fadd_d(Operand::StaticVariable(one_half)); |
4006 // rc=01B, round down. | 4004 // rc=01B, round down. |
4007 __ X87SetRC(0x0400); | 4005 __ X87SetRC(0x0400); |
4008 __ sub(esp, Immediate(kPointerSize)); | 4006 __ sub(esp, Immediate(kPointerSize)); |
4009 // Clear exception bits. | 4007 // Clear exception bits. |
4010 __ fnclex(); | 4008 __ fnclex(); |
4011 __ fistp_s(MemOperand(esp, 0)); | 4009 __ fistp_s(MemOperand(esp, 0)); |
4012 // Check overflow. | 4010 // Check overflow. |
4013 __ X87CheckIA(); | 4011 __ X87CheckIA(); |
4014 __ RecordComment("D2I conversion overflow"); | |
4015 __ pop(result); | 4012 __ pop(result); |
4016 DeoptimizeIf(equal, instr); | 4013 DeoptimizeIf(equal, instr, "conversion overflow"); |
4017 __ fnclex(); | 4014 __ fnclex(); |
4018 // Restore round mode. | 4015 // Restore round mode. |
4019 __ X87SetRC(0x0000); | 4016 __ X87SetRC(0x0000); |
4020 | 4017 |
4021 __ bind(&done); | 4018 __ bind(&done); |
4022 } | 4019 } |
4023 | 4020 |
4024 | 4021 |
4025 void LCodeGen::DoMathFround(LMathFround* instr) { | 4022 void LCodeGen::DoMathFround(LMathFround* instr) { |
4026 X87Register input_reg = ToX87Register(instr->value()); | 4023 X87Register input_reg = ToX87Register(instr->value()); |
(...skipping 1152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5179 __ jmp(done); | 5176 __ jmp(done); |
5180 | 5177 |
5181 __ bind(&check_bools); | 5178 __ bind(&check_bools); |
5182 __ cmp(input_reg, factory()->true_value()); | 5179 __ cmp(input_reg, factory()->true_value()); |
5183 __ j(not_equal, &check_false, Label::kNear); | 5180 __ j(not_equal, &check_false, Label::kNear); |
5184 __ Move(input_reg, Immediate(1)); | 5181 __ Move(input_reg, Immediate(1)); |
5185 __ jmp(done); | 5182 __ jmp(done); |
5186 | 5183 |
5187 __ bind(&check_false); | 5184 __ bind(&check_false); |
5188 __ cmp(input_reg, factory()->false_value()); | 5185 __ cmp(input_reg, factory()->false_value()); |
5189 __ RecordComment("Deferred TaggedToI: cannot truncate"); | 5186 DeoptimizeIf(not_equal, instr, "cannot truncate"); |
5190 DeoptimizeIf(not_equal, instr); | |
5191 __ Move(input_reg, Immediate(0)); | 5187 __ Move(input_reg, Immediate(0)); |
5192 } else { | 5188 } else { |
5193 // TODO(olivf) Converting a number on the fpu is actually quite slow. We | 5189 // TODO(olivf) Converting a number on the fpu is actually quite slow. We |
5194 // should first try a fast conversion and then bailout to this slow case. | 5190 // should first try a fast conversion and then bailout to this slow case. |
5195 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 5191 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
5196 isolate()->factory()->heap_number_map()); | 5192 isolate()->factory()->heap_number_map()); |
5197 __ RecordComment("Deferred TaggedToI: not a heap number"); | 5193 DeoptimizeIf(not_equal, instr, "not a heap number"); |
5198 DeoptimizeIf(not_equal, instr); | |
5199 | 5194 |
5200 __ sub(esp, Immediate(kPointerSize)); | 5195 __ sub(esp, Immediate(kPointerSize)); |
5201 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | 5196 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); |
5202 | 5197 |
5203 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) { | 5198 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) { |
5204 Label no_precision_lost, not_nan, zero_check; | 5199 Label no_precision_lost, not_nan, zero_check; |
5205 __ fld(0); | 5200 __ fld(0); |
5206 | 5201 |
5207 __ fist_s(MemOperand(esp, 0)); | 5202 __ fist_s(MemOperand(esp, 0)); |
5208 __ fild_s(MemOperand(esp, 0)); | 5203 __ fild_s(MemOperand(esp, 0)); |
5209 __ FCmp(); | 5204 __ FCmp(); |
5210 __ pop(input_reg); | 5205 __ pop(input_reg); |
5211 | 5206 |
5212 __ j(equal, &no_precision_lost, Label::kNear); | 5207 __ j(equal, &no_precision_lost, Label::kNear); |
5213 __ fstp(0); | 5208 __ fstp(0); |
5214 __ RecordComment("Deferred TaggedToI: lost precision"); | 5209 DeoptimizeIf(no_condition, instr, "lost precision"); |
5215 DeoptimizeIf(no_condition, instr); | |
5216 __ bind(&no_precision_lost); | 5210 __ bind(&no_precision_lost); |
5217 | 5211 |
5218 __ j(parity_odd, ¬_nan); | 5212 __ j(parity_odd, ¬_nan); |
5219 __ fstp(0); | 5213 __ fstp(0); |
5220 __ RecordComment("Deferred TaggedToI: NaN"); | 5214 DeoptimizeIf(no_condition, instr, "NaN"); |
5221 DeoptimizeIf(no_condition, instr); | |
5222 __ bind(¬_nan); | 5215 __ bind(¬_nan); |
5223 | 5216 |
5224 __ test(input_reg, Operand(input_reg)); | 5217 __ test(input_reg, Operand(input_reg)); |
5225 __ j(zero, &zero_check, Label::kNear); | 5218 __ j(zero, &zero_check, Label::kNear); |
5226 __ fstp(0); | 5219 __ fstp(0); |
5227 __ jmp(done); | 5220 __ jmp(done); |
5228 | 5221 |
5229 __ bind(&zero_check); | 5222 __ bind(&zero_check); |
5230 // To check for minus zero, we load the value again as float, and check | 5223 // To check for minus zero, we load the value again as float, and check |
5231 // if that is still 0. | 5224 // if that is still 0. |
5232 __ sub(esp, Immediate(kPointerSize)); | 5225 __ sub(esp, Immediate(kPointerSize)); |
5233 __ fstp_s(Operand(esp, 0)); | 5226 __ fstp_s(Operand(esp, 0)); |
5234 __ pop(input_reg); | 5227 __ pop(input_reg); |
5235 __ test(input_reg, Operand(input_reg)); | 5228 __ test(input_reg, Operand(input_reg)); |
5236 __ RecordComment("Deferred TaggedToI: minus zero"); | 5229 DeoptimizeIf(not_zero, instr, "minus zero"); |
5237 DeoptimizeIf(not_zero, instr); | |
5238 } else { | 5230 } else { |
5239 __ fist_s(MemOperand(esp, 0)); | 5231 __ fist_s(MemOperand(esp, 0)); |
5240 __ fild_s(MemOperand(esp, 0)); | 5232 __ fild_s(MemOperand(esp, 0)); |
5241 __ FCmp(); | 5233 __ FCmp(); |
5242 __ pop(input_reg); | 5234 __ pop(input_reg); |
5243 __ RecordComment("Deferred TaggedToI: lost precision"); | 5235 DeoptimizeIf(not_equal, instr, "lost precision"); |
5244 DeoptimizeIf(not_equal, instr); | 5236 DeoptimizeIf(parity_even, instr, "NaN"); |
5245 __ RecordComment("Deferred TaggedToI: NaN"); | |
5246 DeoptimizeIf(parity_even, instr); | |
5247 } | 5237 } |
5248 } | 5238 } |
5249 } | 5239 } |
5250 | 5240 |
5251 | 5241 |
5252 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 5242 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
5253 class DeferredTaggedToI FINAL : public LDeferredCode { | 5243 class DeferredTaggedToI FINAL : public LDeferredCode { |
5254 public: | 5244 public: |
5255 DeferredTaggedToI(LCodeGen* codegen, | 5245 DeferredTaggedToI(LCodeGen* codegen, |
5256 LTaggedToI* instr, | 5246 LTaggedToI* instr, |
(...skipping 996 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6253 CallRuntime(Runtime::kPushBlockContext, 2, instr); | 6243 CallRuntime(Runtime::kPushBlockContext, 2, instr); |
6254 RecordSafepoint(Safepoint::kNoLazyDeopt); | 6244 RecordSafepoint(Safepoint::kNoLazyDeopt); |
6255 } | 6245 } |
6256 | 6246 |
6257 | 6247 |
6258 #undef __ | 6248 #undef __ |
6259 | 6249 |
6260 } } // namespace v8::internal | 6250 } } // namespace v8::internal |
6261 | 6251 |
6262 #endif // V8_TARGET_ARCH_X87 | 6252 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |