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 #if V8_TARGET_ARCH_X64 | 5 #if V8_TARGET_ARCH_X64 |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/base/division-by-constant.h" | 8 #include "src/base/division-by-constant.h" |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 743 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 Register reg = saved_regs[i]; | 754 Register reg = saved_regs[i]; |
755 if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) { | 755 if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) { |
756 pushq(reg); | 756 pushq(reg); |
757 } | 757 } |
758 } | 758 } |
759 // R12 to r15 are callee save on all platforms. | 759 // R12 to r15 are callee save on all platforms. |
760 if (fp_mode == kSaveFPRegs) { | 760 if (fp_mode == kSaveFPRegs) { |
761 subp(rsp, Immediate(kDoubleSize * XMMRegister::kMaxNumRegisters)); | 761 subp(rsp, Immediate(kDoubleSize * XMMRegister::kMaxNumRegisters)); |
762 for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) { | 762 for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) { |
763 XMMRegister reg = XMMRegister::from_code(i); | 763 XMMRegister reg = XMMRegister::from_code(i); |
764 movsd(Operand(rsp, i * kDoubleSize), reg); | 764 Movsd(Operand(rsp, i * kDoubleSize), reg); |
765 } | 765 } |
766 } | 766 } |
767 } | 767 } |
768 | 768 |
769 | 769 |
770 void MacroAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, | 770 void MacroAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, |
771 Register exclusion1, | 771 Register exclusion1, |
772 Register exclusion2, | 772 Register exclusion2, |
773 Register exclusion3) { | 773 Register exclusion3) { |
774 if (fp_mode == kSaveFPRegs) { | 774 if (fp_mode == kSaveFPRegs) { |
775 for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) { | 775 for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) { |
776 XMMRegister reg = XMMRegister::from_code(i); | 776 XMMRegister reg = XMMRegister::from_code(i); |
777 movsd(reg, Operand(rsp, i * kDoubleSize)); | 777 Movsd(reg, Operand(rsp, i * kDoubleSize)); |
778 } | 778 } |
779 addp(rsp, Immediate(kDoubleSize * XMMRegister::kMaxNumRegisters)); | 779 addp(rsp, Immediate(kDoubleSize * XMMRegister::kMaxNumRegisters)); |
780 } | 780 } |
781 for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) { | 781 for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) { |
782 Register reg = saved_regs[i]; | 782 Register reg = saved_regs[i]; |
783 if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) { | 783 if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) { |
784 popq(reg); | 784 popq(reg); |
785 } | 785 } |
786 } | 786 } |
787 } | 787 } |
(...skipping 1642 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2430 Move(dst, lower); | 2430 Move(dst, lower); |
2431 } else { | 2431 } else { |
2432 movq(kScratchRegister, src); | 2432 movq(kScratchRegister, src); |
2433 movq(dst, kScratchRegister); | 2433 movq(dst, kScratchRegister); |
2434 } | 2434 } |
2435 } | 2435 } |
2436 } | 2436 } |
2437 } | 2437 } |
2438 | 2438 |
2439 | 2439 |
| 2440 void MacroAssembler::Movapd(XMMRegister dst, XMMRegister src) { |
| 2441 if (CpuFeatures::IsSupported(AVX)) { |
| 2442 CpuFeatureScope scope(this, AVX); |
| 2443 vmovapd(dst, src); |
| 2444 } else { |
| 2445 movapd(dst, src); |
| 2446 } |
| 2447 } |
| 2448 |
| 2449 |
| 2450 void MacroAssembler::Movsd(XMMRegister dst, XMMRegister src) { |
| 2451 if (CpuFeatures::IsSupported(AVX)) { |
| 2452 CpuFeatureScope scope(this, AVX); |
| 2453 vmovsd(dst, src); |
| 2454 } else { |
| 2455 movsd(dst, src); |
| 2456 } |
| 2457 } |
| 2458 |
| 2459 |
| 2460 void MacroAssembler::Movsd(XMMRegister dst, const Operand& src) { |
| 2461 if (CpuFeatures::IsSupported(AVX)) { |
| 2462 CpuFeatureScope scope(this, AVX); |
| 2463 vmovsd(dst, src); |
| 2464 } else { |
| 2465 movsd(dst, src); |
| 2466 } |
| 2467 } |
| 2468 |
| 2469 |
| 2470 void MacroAssembler::Movsd(const Operand& dst, XMMRegister src) { |
| 2471 if (CpuFeatures::IsSupported(AVX)) { |
| 2472 CpuFeatureScope scope(this, AVX); |
| 2473 vmovsd(dst, src); |
| 2474 } else { |
| 2475 movsd(dst, src); |
| 2476 } |
| 2477 } |
| 2478 |
| 2479 |
2440 void MacroAssembler::Cmp(Register dst, Handle<Object> source) { | 2480 void MacroAssembler::Cmp(Register dst, Handle<Object> source) { |
2441 AllowDeferredHandleDereference smi_check; | 2481 AllowDeferredHandleDereference smi_check; |
2442 if (source->IsSmi()) { | 2482 if (source->IsSmi()) { |
2443 Cmp(dst, Smi::cast(*source)); | 2483 Cmp(dst, Smi::cast(*source)); |
2444 } else { | 2484 } else { |
2445 MoveHeapObject(kScratchRegister, source); | 2485 MoveHeapObject(kScratchRegister, source); |
2446 cmpp(dst, kScratchRegister); | 2486 cmpp(dst, kScratchRegister); |
2447 } | 2487 } |
2448 } | 2488 } |
2449 | 2489 |
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3038 Move(xmm_scratch, 1.0); | 3078 Move(xmm_scratch, 1.0); |
3039 mulsd(xmm_scratch, FieldOperand(maybe_number, HeapNumber::kValueOffset)); | 3079 mulsd(xmm_scratch, FieldOperand(maybe_number, HeapNumber::kValueOffset)); |
3040 jmp(&done, Label::kNear); | 3080 jmp(&done, Label::kNear); |
3041 | 3081 |
3042 bind(&smi_value); | 3082 bind(&smi_value); |
3043 // Value is a smi. convert to a double and store. | 3083 // Value is a smi. convert to a double and store. |
3044 // Preserve original value. | 3084 // Preserve original value. |
3045 SmiToInteger32(kScratchRegister, maybe_number); | 3085 SmiToInteger32(kScratchRegister, maybe_number); |
3046 Cvtlsi2sd(xmm_scratch, kScratchRegister); | 3086 Cvtlsi2sd(xmm_scratch, kScratchRegister); |
3047 bind(&done); | 3087 bind(&done); |
3048 movsd(FieldOperand(elements, index, times_8, | 3088 Movsd(FieldOperand(elements, index, times_8, |
3049 FixedDoubleArray::kHeaderSize - elements_offset), | 3089 FixedDoubleArray::kHeaderSize - elements_offset), |
3050 xmm_scratch); | 3090 xmm_scratch); |
3051 } | 3091 } |
3052 | 3092 |
3053 | 3093 |
3054 void MacroAssembler::CompareMap(Register obj, Handle<Map> map) { | 3094 void MacroAssembler::CompareMap(Register obj, Handle<Map> map) { |
3055 Cmp(FieldOperand(obj, HeapObject::kMapOffset), map); | 3095 Cmp(FieldOperand(obj, HeapObject::kMapOffset), map); |
3056 } | 3096 } |
3057 | 3097 |
3058 | 3098 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3118 Register input_reg, | 3158 Register input_reg, |
3119 int offset) { | 3159 int offset) { |
3120 DoubleToIStub stub(isolate(), input_reg, result_reg, offset, true); | 3160 DoubleToIStub stub(isolate(), input_reg, result_reg, offset, true); |
3121 call(stub.GetCode(), RelocInfo::CODE_TARGET); | 3161 call(stub.GetCode(), RelocInfo::CODE_TARGET); |
3122 } | 3162 } |
3123 | 3163 |
3124 | 3164 |
3125 void MacroAssembler::TruncateHeapNumberToI(Register result_reg, | 3165 void MacroAssembler::TruncateHeapNumberToI(Register result_reg, |
3126 Register input_reg) { | 3166 Register input_reg) { |
3127 Label done; | 3167 Label done; |
3128 movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3168 Movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
3129 cvttsd2siq(result_reg, xmm0); | 3169 cvttsd2siq(result_reg, xmm0); |
3130 cmpq(result_reg, Immediate(1)); | 3170 cmpq(result_reg, Immediate(1)); |
3131 j(no_overflow, &done, Label::kNear); | 3171 j(no_overflow, &done, Label::kNear); |
3132 | 3172 |
3133 // Slow case. | 3173 // Slow case. |
3134 if (input_reg.is(result_reg)) { | 3174 if (input_reg.is(result_reg)) { |
3135 subp(rsp, Immediate(kDoubleSize)); | 3175 subp(rsp, Immediate(kDoubleSize)); |
3136 movsd(MemOperand(rsp, 0), xmm0); | 3176 Movsd(MemOperand(rsp, 0), xmm0); |
3137 SlowTruncateToI(result_reg, rsp, 0); | 3177 SlowTruncateToI(result_reg, rsp, 0); |
3138 addp(rsp, Immediate(kDoubleSize)); | 3178 addp(rsp, Immediate(kDoubleSize)); |
3139 } else { | 3179 } else { |
3140 SlowTruncateToI(result_reg, input_reg); | 3180 SlowTruncateToI(result_reg, input_reg); |
3141 } | 3181 } |
3142 | 3182 |
3143 bind(&done); | 3183 bind(&done); |
3144 // Keep our invariant that the upper 32 bits are zero. | 3184 // Keep our invariant that the upper 32 bits are zero. |
3145 movl(result_reg, result_reg); | 3185 movl(result_reg, result_reg); |
3146 } | 3186 } |
3147 | 3187 |
3148 | 3188 |
3149 void MacroAssembler::TruncateDoubleToI(Register result_reg, | 3189 void MacroAssembler::TruncateDoubleToI(Register result_reg, |
3150 XMMRegister input_reg) { | 3190 XMMRegister input_reg) { |
3151 Label done; | 3191 Label done; |
3152 cvttsd2siq(result_reg, input_reg); | 3192 cvttsd2siq(result_reg, input_reg); |
3153 cmpq(result_reg, Immediate(1)); | 3193 cmpq(result_reg, Immediate(1)); |
3154 j(no_overflow, &done, Label::kNear); | 3194 j(no_overflow, &done, Label::kNear); |
3155 | 3195 |
3156 subp(rsp, Immediate(kDoubleSize)); | 3196 subp(rsp, Immediate(kDoubleSize)); |
3157 movsd(MemOperand(rsp, 0), input_reg); | 3197 Movsd(MemOperand(rsp, 0), input_reg); |
3158 SlowTruncateToI(result_reg, rsp, 0); | 3198 SlowTruncateToI(result_reg, rsp, 0); |
3159 addp(rsp, Immediate(kDoubleSize)); | 3199 addp(rsp, Immediate(kDoubleSize)); |
3160 | 3200 |
3161 bind(&done); | 3201 bind(&done); |
3162 // Keep our invariant that the upper 32 bits are zero. | 3202 // Keep our invariant that the upper 32 bits are zero. |
3163 movl(result_reg, result_reg); | 3203 movl(result_reg, result_reg); |
3164 } | 3204 } |
3165 | 3205 |
3166 | 3206 |
3167 void MacroAssembler::DoubleToI(Register result_reg, XMMRegister input_reg, | 3207 void MacroAssembler::DoubleToI(Register result_reg, XMMRegister input_reg, |
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3713 // Optionally save all XMM registers. | 3753 // Optionally save all XMM registers. |
3714 if (save_doubles) { | 3754 if (save_doubles) { |
3715 int space = XMMRegister::kMaxNumRegisters * kDoubleSize + | 3755 int space = XMMRegister::kMaxNumRegisters * kDoubleSize + |
3716 arg_stack_space * kRegisterSize; | 3756 arg_stack_space * kRegisterSize; |
3717 subp(rsp, Immediate(space)); | 3757 subp(rsp, Immediate(space)); |
3718 int offset = -2 * kPointerSize; | 3758 int offset = -2 * kPointerSize; |
3719 const RegisterConfiguration* config = RegisterConfiguration::ArchDefault(); | 3759 const RegisterConfiguration* config = RegisterConfiguration::ArchDefault(); |
3720 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { | 3760 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { |
3721 DoubleRegister reg = | 3761 DoubleRegister reg = |
3722 DoubleRegister::from_code(config->GetAllocatableDoubleCode(i)); | 3762 DoubleRegister::from_code(config->GetAllocatableDoubleCode(i)); |
3723 movsd(Operand(rbp, offset - ((i + 1) * kDoubleSize)), reg); | 3763 Movsd(Operand(rbp, offset - ((i + 1) * kDoubleSize)), reg); |
3724 } | 3764 } |
3725 } else if (arg_stack_space > 0) { | 3765 } else if (arg_stack_space > 0) { |
3726 subp(rsp, Immediate(arg_stack_space * kRegisterSize)); | 3766 subp(rsp, Immediate(arg_stack_space * kRegisterSize)); |
3727 } | 3767 } |
3728 | 3768 |
3729 // Get the required frame alignment for the OS. | 3769 // Get the required frame alignment for the OS. |
3730 const int kFrameAlignment = base::OS::ActivationFrameAlignment(); | 3770 const int kFrameAlignment = base::OS::ActivationFrameAlignment(); |
3731 if (kFrameAlignment > 0) { | 3771 if (kFrameAlignment > 0) { |
3732 DCHECK(base::bits::IsPowerOfTwo32(kFrameAlignment)); | 3772 DCHECK(base::bits::IsPowerOfTwo32(kFrameAlignment)); |
3733 DCHECK(is_int8(kFrameAlignment)); | 3773 DCHECK(is_int8(kFrameAlignment)); |
(...skipping 25 matching lines...) Expand all Loading... |
3759 | 3799 |
3760 void MacroAssembler::LeaveExitFrame(bool save_doubles, bool pop_arguments) { | 3800 void MacroAssembler::LeaveExitFrame(bool save_doubles, bool pop_arguments) { |
3761 // Registers: | 3801 // Registers: |
3762 // r15 : argv | 3802 // r15 : argv |
3763 if (save_doubles) { | 3803 if (save_doubles) { |
3764 int offset = -2 * kPointerSize; | 3804 int offset = -2 * kPointerSize; |
3765 const RegisterConfiguration* config = RegisterConfiguration::ArchDefault(); | 3805 const RegisterConfiguration* config = RegisterConfiguration::ArchDefault(); |
3766 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { | 3806 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { |
3767 DoubleRegister reg = | 3807 DoubleRegister reg = |
3768 DoubleRegister::from_code(config->GetAllocatableDoubleCode(i)); | 3808 DoubleRegister::from_code(config->GetAllocatableDoubleCode(i)); |
3769 movsd(reg, Operand(rbp, offset - ((i + 1) * kDoubleSize))); | 3809 Movsd(reg, Operand(rbp, offset - ((i + 1) * kDoubleSize))); |
3770 } | 3810 } |
3771 } | 3811 } |
3772 | 3812 |
3773 if (pop_arguments) { | 3813 if (pop_arguments) { |
3774 // Get the return address from the stack and restore the frame pointer. | 3814 // Get the return address from the stack and restore the frame pointer. |
3775 movp(rcx, Operand(rbp, kFPOnStackSize)); | 3815 movp(rcx, Operand(rbp, kFPOnStackSize)); |
3776 movp(rbp, Operand(rbp, 0 * kPointerSize)); | 3816 movp(rbp, Operand(rbp, 0 * kPointerSize)); |
3777 | 3817 |
3778 // Drop everything up to and including the arguments and the receiver | 3818 // Drop everything up to and including the arguments and the receiver |
3779 // from the caller stack. | 3819 // from the caller stack. |
(...skipping 1221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5001 movl(rax, dividend); | 5041 movl(rax, dividend); |
5002 shrl(rax, Immediate(31)); | 5042 shrl(rax, Immediate(31)); |
5003 addl(rdx, rax); | 5043 addl(rdx, rax); |
5004 } | 5044 } |
5005 | 5045 |
5006 | 5046 |
5007 } // namespace internal | 5047 } // namespace internal |
5008 } // namespace v8 | 5048 } // namespace v8 |
5009 | 5049 |
5010 #endif // V8_TARGET_ARCH_X64 | 5050 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |