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/x64/codegen-x64.h" | 5 #include "src/x64/codegen-x64.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/macro-assembler.h" | 10 #include "src/macro-assembler.h" |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 | 80 |
81 CodeDesc desc; | 81 CodeDesc desc; |
82 masm.GetCode(&desc); | 82 masm.GetCode(&desc); |
83 DCHECK(!RelocInfo::RequiresRelocation(desc)); | 83 DCHECK(!RelocInfo::RequiresRelocation(desc)); |
84 | 84 |
85 Assembler::FlushICache(isolate, buffer, actual_size); | 85 Assembler::FlushICache(isolate, buffer, actual_size); |
86 base::OS::ProtectCode(buffer, actual_size); | 86 base::OS::ProtectCode(buffer, actual_size); |
87 return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer); | 87 return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer); |
88 } | 88 } |
89 | 89 |
90 | |
91 #ifdef _WIN64 | |
92 typedef double (*ModuloFunction)(double, double); | |
93 // Define custom fmod implementation. | |
94 ModuloFunction CreateModuloFunction() { | |
95 size_t actual_size; | |
96 byte* buffer = static_cast<byte*>( | |
97 base::OS::Allocate(Assembler::kMinimalBufferSize, &actual_size, true)); | |
98 CHECK(buffer); | |
99 MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size), | |
100 CodeObjectRequired::kNo); | |
101 // Generated code is put into a fixed, unmovable, buffer, and not into | |
102 // the V8 heap. We can't, and don't, refer to any relocatable addresses | |
103 // (e.g. the JavaScript nan-object). | |
104 | |
105 // Windows 64 ABI passes double arguments in xmm0, xmm1 and | |
106 // returns result in xmm0. | |
107 // Argument backing space is allocated on the stack above | |
108 // the return address. | |
109 | |
110 // Compute x mod y. | |
111 // Load y and x (use argument backing store as temporary storage). | |
112 __ Movsd(Operand(rsp, kRegisterSize * 2), xmm1); | |
113 __ Movsd(Operand(rsp, kRegisterSize), xmm0); | |
114 __ fld_d(Operand(rsp, kRegisterSize * 2)); | |
115 __ fld_d(Operand(rsp, kRegisterSize)); | |
116 | |
117 // Clear exception flags before operation. | |
118 { | |
119 Label no_exceptions; | |
120 __ fwait(); | |
121 __ fnstsw_ax(); | |
122 // Clear if Illegal Operand or Zero Division exceptions are set. | |
123 __ testb(rax, Immediate(5)); | |
124 __ j(zero, &no_exceptions); | |
125 __ fnclex(); | |
126 __ bind(&no_exceptions); | |
127 } | |
128 | |
129 // Compute st(0) % st(1) | |
130 { | |
131 Label partial_remainder_loop; | |
132 __ bind(&partial_remainder_loop); | |
133 __ fprem(); | |
134 __ fwait(); | |
135 __ fnstsw_ax(); | |
136 __ testl(rax, Immediate(0x400 /* C2 */)); | |
137 // If C2 is set, computation only has partial result. Loop to | |
138 // continue computation. | |
139 __ j(not_zero, &partial_remainder_loop); | |
140 } | |
141 | |
142 Label valid_result; | |
143 Label return_result; | |
144 // If Invalid Operand or Zero Division exceptions are set, | |
145 // return NaN. | |
146 __ testb(rax, Immediate(5)); | |
147 __ j(zero, &valid_result); | |
148 __ fstp(0); // Drop result in st(0). | |
149 int64_t kNaNValue = V8_INT64_C(0x7ff8000000000000); | |
150 __ movq(rcx, kNaNValue); | |
151 __ movq(Operand(rsp, kRegisterSize), rcx); | |
152 __ Movsd(xmm0, Operand(rsp, kRegisterSize)); | |
153 __ jmp(&return_result); | |
154 | |
155 // If result is valid, return that. | |
156 __ bind(&valid_result); | |
157 __ fstp_d(Operand(rsp, kRegisterSize)); | |
158 __ Movsd(xmm0, Operand(rsp, kRegisterSize)); | |
159 | |
160 // Clean up FPU stack and exceptions and return xmm0 | |
161 __ bind(&return_result); | |
162 __ fstp(0); // Unload y. | |
163 | |
164 Label clear_exceptions; | |
165 __ testb(rax, Immediate(0x3f /* Any Exception*/)); | |
166 __ j(not_zero, &clear_exceptions); | |
167 __ ret(0); | |
168 __ bind(&clear_exceptions); | |
169 __ fnclex(); | |
170 __ ret(0); | |
171 | |
172 CodeDesc desc; | |
173 masm.GetCode(&desc); | |
174 base::OS::ProtectCode(buffer, actual_size); | |
175 // Call the function from C++ through this pointer. | |
176 return FUNCTION_CAST<ModuloFunction>(buffer); | |
177 } | |
178 | |
179 #endif | |
180 | |
181 #undef __ | 90 #undef __ |
182 | 91 |
183 // ------------------------------------------------------------------------- | 92 // ------------------------------------------------------------------------- |
184 // Code generators | 93 // Code generators |
185 | 94 |
186 #define __ ACCESS_MASM(masm) | 95 #define __ ACCESS_MASM(masm) |
187 | 96 |
188 void ElementsTransitionGenerator::GenerateMapChangeElementsTransition( | 97 void ElementsTransitionGenerator::GenerateMapChangeElementsTransition( |
189 MacroAssembler* masm, | 98 MacroAssembler* masm, |
190 Register receiver, | 99 Register receiver, |
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
723 return Operand(base_reg_, argument_count_reg_, times_pointer_size, | 632 return Operand(base_reg_, argument_count_reg_, times_pointer_size, |
724 displacement_to_last_argument + (receiver - 1 - index) * kPointerSize); | 633 displacement_to_last_argument + (receiver - 1 - index) * kPointerSize); |
725 } | 634 } |
726 } | 635 } |
727 | 636 |
728 | 637 |
729 } // namespace internal | 638 } // namespace internal |
730 } // namespace v8 | 639 } // namespace v8 |
731 | 640 |
732 #endif // V8_TARGET_ARCH_X64 | 641 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |