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 1983 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1994 __ Move(ToRegister(instr->result()), Immediate(instr->value())); | 1994 __ Move(ToRegister(instr->result()), Immediate(instr->value())); |
1995 } | 1995 } |
1996 | 1996 |
1997 | 1997 |
1998 void LCodeGen::DoConstantS(LConstantS* instr) { | 1998 void LCodeGen::DoConstantS(LConstantS* instr) { |
1999 __ Move(ToRegister(instr->result()), Immediate(instr->value())); | 1999 __ Move(ToRegister(instr->result()), Immediate(instr->value())); |
2000 } | 2000 } |
2001 | 2001 |
2002 | 2002 |
2003 void LCodeGen::DoConstantD(LConstantD* instr) { | 2003 void LCodeGen::DoConstantD(LConstantD* instr) { |
2004 double v = instr->value(); | 2004 uint64_t const bits = instr->bits(); |
2005 uint64_t int_val = bit_cast<uint64_t, double>(v); | 2005 uint32_t const lower = static_cast<uint32_t>(bits); |
2006 int32_t lower = static_cast<int32_t>(int_val); | 2006 uint32_t const upper = static_cast<uint32_t>(bits >> 32); |
2007 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); | |
2008 DCHECK(instr->result()->IsDoubleRegister()); | 2007 DCHECK(instr->result()->IsDoubleRegister()); |
2009 | 2008 |
2010 __ push(Immediate(upper)); | 2009 __ push(Immediate(upper)); |
2011 __ push(Immediate(lower)); | 2010 __ push(Immediate(lower)); |
2012 X87Register reg = ToX87Register(instr->result()); | 2011 X87Register reg = ToX87Register(instr->result()); |
2013 X87Mov(reg, Operand(esp, 0)); | 2012 X87Mov(reg, Operand(esp, 0)); |
2014 __ add(Operand(esp), Immediate(kDoubleSize)); | 2013 __ add(Operand(esp), Immediate(kDoubleSize)); |
2015 } | 2014 } |
2016 | 2015 |
2017 | 2016 |
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2606 __ fstp(0); | 2605 __ fstp(0); |
2607 EmitFalseBranch(instr, no_condition); | 2606 EmitFalseBranch(instr, no_condition); |
2608 __ bind(&ok); | 2607 __ bind(&ok); |
2609 | 2608 |
2610 | 2609 |
2611 __ sub(esp, Immediate(kDoubleSize)); | 2610 __ sub(esp, Immediate(kDoubleSize)); |
2612 __ fstp_d(MemOperand(esp, 0)); | 2611 __ fstp_d(MemOperand(esp, 0)); |
2613 | 2612 |
2614 __ add(esp, Immediate(kDoubleSize)); | 2613 __ add(esp, Immediate(kDoubleSize)); |
2615 int offset = sizeof(kHoleNanUpper32); | 2614 int offset = sizeof(kHoleNanUpper32); |
2616 __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32)); | 2615 // x87 converts sNaN(0xfff7fffffff7ffff) to QNaN(0xfffffffffff7ffff), |
| 2616 // so we check the upper with 0xffffffff for hole as a temporary fix. |
| 2617 __ cmp(MemOperand(esp, -offset), Immediate(0xffffffff)); |
2617 EmitBranch(instr, equal); | 2618 EmitBranch(instr, equal); |
2618 } | 2619 } |
2619 | 2620 |
2620 | 2621 |
2621 void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) { | 2622 void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) { |
2622 Representation rep = instr->hydrogen()->value()->representation(); | 2623 Representation rep = instr->hydrogen()->value()->representation(); |
2623 DCHECK(!rep.IsInteger32()); | 2624 DCHECK(!rep.IsInteger32()); |
2624 | 2625 |
2625 if (rep.IsDouble()) { | 2626 if (rep.IsDouble()) { |
2626 X87Register input = ToX87Register(instr->value()); | 2627 X87Register input = ToX87Register(instr->value()); |
(...skipping 1608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4235 // Positive input. | 4236 // Positive input. |
4236 // {input, ln2}. | 4237 // {input, ln2}. |
4237 __ fldln2(); | 4238 __ fldln2(); |
4238 // {ln2, input}. | 4239 // {ln2, input}. |
4239 __ fxch(); | 4240 __ fxch(); |
4240 // {result}. | 4241 // {result}. |
4241 __ fyl2x(); | 4242 __ fyl2x(); |
4242 __ jmp(&done, Label::kNear); | 4243 __ jmp(&done, Label::kNear); |
4243 | 4244 |
4244 __ bind(&nan_result); | 4245 __ bind(&nan_result); |
4245 ExternalReference nan = | |
4246 ExternalReference::address_of_canonical_non_hole_nan(); | |
4247 X87PrepareToWrite(input_reg); | 4246 X87PrepareToWrite(input_reg); |
4248 __ fld_d(Operand::StaticVariable(nan)); | 4247 __ push(Immediate(0xffffffff)); |
| 4248 __ push(Immediate(0x7fffffff)); |
| 4249 __ fld_d(MemOperand(esp, 0)); |
| 4250 __ lea(esp, Operand(esp, kDoubleSize)); |
4249 X87CommitWrite(input_reg); | 4251 X87CommitWrite(input_reg); |
4250 __ jmp(&done, Label::kNear); | 4252 __ jmp(&done, Label::kNear); |
4251 | 4253 |
4252 __ bind(&zero); | 4254 __ bind(&zero); |
4253 ExternalReference ninf = ExternalReference::address_of_negative_infinity(); | 4255 ExternalReference ninf = ExternalReference::address_of_negative_infinity(); |
4254 X87PrepareToWrite(input_reg); | 4256 X87PrepareToWrite(input_reg); |
4255 __ fld_d(Operand::StaticVariable(ninf)); | 4257 __ fld_d(Operand::StaticVariable(ninf)); |
4256 X87CommitWrite(input_reg); | 4258 X87CommitWrite(input_reg); |
4257 | 4259 |
4258 __ bind(&done); | 4260 __ bind(&done); |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4633 case DICTIONARY_ELEMENTS: | 4635 case DICTIONARY_ELEMENTS: |
4634 case SLOPPY_ARGUMENTS_ELEMENTS: | 4636 case SLOPPY_ARGUMENTS_ELEMENTS: |
4635 UNREACHABLE(); | 4637 UNREACHABLE(); |
4636 break; | 4638 break; |
4637 } | 4639 } |
4638 } | 4640 } |
4639 } | 4641 } |
4640 | 4642 |
4641 | 4643 |
4642 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { | 4644 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { |
4643 ExternalReference canonical_nan_reference = | |
4644 ExternalReference::address_of_canonical_non_hole_nan(); | |
4645 Operand double_store_operand = BuildFastArrayOperand( | 4645 Operand double_store_operand = BuildFastArrayOperand( |
4646 instr->elements(), | 4646 instr->elements(), |
4647 instr->key(), | 4647 instr->key(), |
4648 instr->hydrogen()->key()->representation(), | 4648 instr->hydrogen()->key()->representation(), |
4649 FAST_DOUBLE_ELEMENTS, | 4649 FAST_DOUBLE_ELEMENTS, |
4650 instr->base_offset()); | 4650 instr->base_offset()); |
4651 | 4651 |
4652 // Can't use SSE2 in the serializer | 4652 uint64_t int_val = kHoleNanInt64; |
| 4653 int32_t lower = static_cast<int32_t>(int_val); |
| 4654 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); |
| 4655 Operand double_store_operand2 = BuildFastArrayOperand( |
| 4656 instr->elements(), instr->key(), |
| 4657 instr->hydrogen()->key()->representation(), FAST_DOUBLE_ELEMENTS, |
| 4658 instr->base_offset() + kPointerSize); |
| 4659 |
4653 if (instr->hydrogen()->IsConstantHoleStore()) { | 4660 if (instr->hydrogen()->IsConstantHoleStore()) { |
4654 // This means we should store the (double) hole. No floating point | 4661 // This means we should store the (double) hole. No floating point |
4655 // registers required. | 4662 // registers required. |
4656 double nan_double = FixedDoubleArray::hole_nan_as_double(); | |
4657 uint64_t int_val = bit_cast<uint64_t, double>(nan_double); | |
4658 int32_t lower = static_cast<int32_t>(int_val); | |
4659 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); | |
4660 | |
4661 __ mov(double_store_operand, Immediate(lower)); | 4663 __ mov(double_store_operand, Immediate(lower)); |
4662 Operand double_store_operand2 = BuildFastArrayOperand( | |
4663 instr->elements(), | |
4664 instr->key(), | |
4665 instr->hydrogen()->key()->representation(), | |
4666 FAST_DOUBLE_ELEMENTS, | |
4667 instr->base_offset() + kPointerSize); | |
4668 __ mov(double_store_operand2, Immediate(upper)); | 4664 __ mov(double_store_operand2, Immediate(upper)); |
4669 } else { | 4665 } else { |
4670 Label no_special_nan_handling; | 4666 Label no_special_nan_handling, done; |
4671 X87Register value = ToX87Register(instr->value()); | 4667 X87Register value = ToX87Register(instr->value()); |
4672 X87Fxch(value); | 4668 X87Fxch(value); |
4673 | 4669 |
4674 if (instr->NeedsCanonicalization()) { | 4670 if (instr->NeedsCanonicalization()) { |
4675 __ fld(0); | 4671 __ fld(0); |
4676 __ fld(0); | 4672 __ fld(0); |
4677 __ FCmp(); | 4673 __ FCmp(); |
4678 | |
4679 __ j(parity_odd, &no_special_nan_handling, Label::kNear); | 4674 __ j(parity_odd, &no_special_nan_handling, Label::kNear); |
4680 __ sub(esp, Immediate(kDoubleSize)); | 4675 // All NaNs are Canonicalized to 0x7fffffffffffffff |
| 4676 __ mov(double_store_operand, Immediate(0xffffffff)); |
| 4677 __ mov(double_store_operand2, Immediate(0x7fffffff)); |
| 4678 __ jmp(&done, Label::kNear); |
| 4679 } else { |
| 4680 __ lea(esp, Operand(esp, -kDoubleSize)); |
4681 __ fst_d(MemOperand(esp, 0)); | 4681 __ fst_d(MemOperand(esp, 0)); |
4682 __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)), | 4682 __ lea(esp, Operand(esp, kDoubleSize)); |
4683 Immediate(kHoleNanUpper32)); | 4683 int offset = sizeof(kHoleNanUpper32); |
4684 __ add(esp, Immediate(kDoubleSize)); | 4684 // x87 converts sNaN(0xfff7fffffff7ffff) to QNaN(0xfffffffffff7ffff), |
4685 Label canonicalize; | 4685 // so we check the upper with 0xffffffff for hole as a temporary fix. |
4686 __ j(not_equal, &canonicalize, Label::kNear); | 4686 __ cmp(MemOperand(esp, -offset), Immediate(0xffffffff)); |
4687 __ jmp(&no_special_nan_handling, Label::kNear); | 4687 __ j(not_equal, &no_special_nan_handling, Label::kNear); |
4688 __ bind(&canonicalize); | 4688 __ mov(double_store_operand, Immediate(lower)); |
4689 __ fstp(0); | 4689 __ mov(double_store_operand2, Immediate(upper)); |
4690 __ fld_d(Operand::StaticVariable(canonical_nan_reference)); | 4690 __ jmp(&done, Label::kNear); |
4691 } | 4691 } |
4692 | |
4693 __ bind(&no_special_nan_handling); | 4692 __ bind(&no_special_nan_handling); |
4694 __ fst_d(double_store_operand); | 4693 __ fst_d(double_store_operand); |
| 4694 __ bind(&done); |
4695 } | 4695 } |
4696 } | 4696 } |
4697 | 4697 |
4698 | 4698 |
4699 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { | 4699 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { |
4700 Register elements = ToRegister(instr->elements()); | 4700 Register elements = ToRegister(instr->elements()); |
4701 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; | 4701 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; |
4702 | 4702 |
4703 Operand operand = BuildFastArrayOperand( | 4703 Operand operand = BuildFastArrayOperand( |
4704 instr->elements(), | 4704 instr->elements(), |
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5182 DeoptimizeIf(not_equal, instr, "not a heap number"); | 5182 DeoptimizeIf(not_equal, instr, "not a heap number"); |
5183 } else { | 5183 } else { |
5184 Label heap_number, convert; | 5184 Label heap_number, convert; |
5185 __ j(equal, &heap_number); | 5185 __ j(equal, &heap_number); |
5186 | 5186 |
5187 // Convert undefined (or hole) to NaN. | 5187 // Convert undefined (or hole) to NaN. |
5188 __ cmp(input_reg, factory()->undefined_value()); | 5188 __ cmp(input_reg, factory()->undefined_value()); |
5189 DeoptimizeIf(not_equal, instr, "not a heap number/undefined"); | 5189 DeoptimizeIf(not_equal, instr, "not a heap number/undefined"); |
5190 | 5190 |
5191 __ bind(&convert); | 5191 __ bind(&convert); |
5192 ExternalReference nan = | 5192 __ push(Immediate(0xffffffff)); |
5193 ExternalReference::address_of_canonical_non_hole_nan(); | 5193 __ push(Immediate(0x7fffffff)); |
5194 __ fld_d(Operand::StaticVariable(nan)); | 5194 __ fld_d(MemOperand(esp, 0)); |
| 5195 __ lea(esp, Operand(esp, kDoubleSize)); |
5195 __ jmp(&done, Label::kNear); | 5196 __ jmp(&done, Label::kNear); |
5196 | 5197 |
5197 __ bind(&heap_number); | 5198 __ bind(&heap_number); |
5198 } | 5199 } |
5199 // Heap number to x87 conversion. | 5200 // Heap number to x87 conversion. |
5200 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | 5201 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); |
5201 if (deoptimize_on_minus_zero) { | 5202 if (deoptimize_on_minus_zero) { |
5202 __ fldz(); | 5203 __ fldz(); |
5203 __ FCmp(); | 5204 __ FCmp(); |
5204 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | 5205 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); |
(...skipping 1125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6330 CallRuntime(Runtime::kPushBlockContext, 2, instr); | 6331 CallRuntime(Runtime::kPushBlockContext, 2, instr); |
6331 RecordSafepoint(Safepoint::kNoLazyDeopt); | 6332 RecordSafepoint(Safepoint::kNoLazyDeopt); |
6332 } | 6333 } |
6333 | 6334 |
6334 | 6335 |
6335 #undef __ | 6336 #undef __ |
6336 | 6337 |
6337 } } // namespace v8::internal | 6338 } } // namespace v8::internal |
6338 | 6339 |
6339 #endif // V8_TARGET_ARCH_X87 | 6340 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |