OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
208 void MacroAssembler::ClampUint8(Register reg) { | 208 void MacroAssembler::ClampUint8(Register reg) { |
209 Label done; | 209 Label done; |
210 test(reg, Immediate(0xFFFFFF00)); | 210 test(reg, Immediate(0xFFFFFF00)); |
211 j(zero, &done, Label::kNear); | 211 j(zero, &done, Label::kNear); |
212 setcc(negative, reg); // 1 if negative, 0 if positive. | 212 setcc(negative, reg); // 1 if negative, 0 if positive. |
213 dec_b(reg); // 0 if negative, 255 if positive. | 213 dec_b(reg); // 0 if negative, 255 if positive. |
214 bind(&done); | 214 bind(&done); |
215 } | 215 } |
216 | 216 |
217 | 217 |
218 void MacroAssembler::SlowTruncateToI(Register input_reg, Register result_reg, | |
219 int index) { | |
220 DoubleToIStub stub(input_reg, result_reg, index, true); | |
221 call(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); | |
222 } | |
223 | |
224 | |
225 void MacroAssembler::TruncateDoubleToI( | |
226 XMMRegister input_reg, Register result_reg) { | |
227 Label done; | |
228 cvttsd2si(result_reg, Operand(input_reg)); | |
229 cmp(result_reg, 0x80000000u); | |
230 j(not_equal, &done, Label::kNear); | |
231 | |
232 sub(esp, Immediate(kDoubleSize)); | |
233 movdbl(MemOperand(esp, 0), input_reg); | |
234 SlowTruncateToI(esp, result_reg, 0); | |
235 add(esp, Immediate(kDoubleSize)); | |
236 bind(&done); | |
237 } | |
238 | |
239 | |
240 void MacroAssembler::TruncateX87TOSToI(Register result_reg) { | |
241 sub(esp, Immediate(kDoubleSize)); | |
242 fst_d(MemOperand(esp, 0)); | |
243 SlowTruncateToI(esp, result_reg, 0); | |
244 add(esp, Immediate(kDoubleSize)); | |
245 } | |
246 | |
247 | |
248 void MacroAssembler::X87TOSToI(Register result_reg, | |
249 bool treat_minus_zero_as_zero, | |
250 Label* conversion_failed, | |
251 Label::Distance dst) { | |
252 Label done; | |
253 sub(esp, Immediate(kPointerSize)); | |
254 fist_s(MemOperand(esp, 0)); | |
255 fld(0); | |
256 fild_s(MemOperand(esp, 0)); | |
257 pop(result_reg); | |
258 FCmp(); | |
259 j(not_equal, conversion_failed, dst); | |
260 j(parity_even, conversion_failed, dst); | |
261 if (!treat_minus_zero_as_zero) { | |
262 test(result_reg, Operand(result_reg)); | |
263 j(not_zero, &done, Label::kNear); | |
264 // To check for minus zero, we load the value again as float, and check | |
265 // if that is still 0. | |
266 sub(esp, Immediate(kPointerSize)); | |
267 fst_s(MemOperand(esp, 0)); | |
268 pop(result_reg); | |
269 test(result_reg, Operand(result_reg)); | |
270 j(not_zero, conversion_failed, dst); | |
271 } | |
272 bind(&done); | |
273 } | |
274 | |
275 | |
276 void MacroAssembler::DoubleToI(XMMRegister input_reg, Register result_reg, | |
277 XMMRegister scratch, bool treat_minus_zero_as_zero, | |
278 Label* conversion_failed, Label::Distance dst) { | |
279 ASSERT(!input_reg.is(scratch)); | |
280 Label done; | |
281 cvttsd2si(result_reg, Operand(input_reg)); | |
282 cvtsi2sd(scratch, Operand(result_reg)); | |
283 ucomisd(scratch, input_reg); | |
284 j(not_equal, conversion_failed, dst); | |
285 j(parity_even, conversion_failed, dst); // NaN. | |
286 if (!treat_minus_zero_as_zero) { | |
287 test(result_reg, Operand(result_reg)); | |
288 j(not_zero, &done, Label::kNear); | |
289 movmskpd(result_reg, input_reg); | |
290 and_(result_reg, 1); | |
291 j(not_zero, conversion_failed, dst); | |
292 } | |
293 bind(&done); | |
294 } | |
295 | |
296 | |
297 void MacroAssembler::TruncateHeapNumberToI(Register input_reg, | |
298 Register result_reg) { | |
299 Label done, slow_case; | |
300 | |
301 if (CpuFeatures::IsSupported(SSE3)) { | |
302 CpuFeatureScope scope(this, SSE3); | |
303 Label convert; | |
304 // Use more powerful conversion when sse3 is available. | |
305 // Load x87 register with heap number. | |
306 fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | |
307 // Get exponent alone and check for too-big exponent. | |
308 mov(result_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | |
309 and_(result_reg, HeapNumber::kExponentMask); | |
310 const uint32_t kTooBigExponent = | |
311 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; | |
312 cmp(Operand(result_reg), Immediate(kTooBigExponent)); | |
313 j(greater_equal, &slow_case, Label::kNear); | |
314 | |
315 // Reserve space for 64 bit answer. | |
316 sub(Operand(esp), Immediate(kDoubleSize)); | |
317 // Do conversion, which cannot fail because we checked the exponent. | |
318 fisttp_d(Operand(esp, 0)); | |
319 mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. | |
320 add(Operand(esp), Immediate(kDoubleSize)); | |
321 jmp(&done, Label::kNear); | |
322 | |
323 // Slow case. | |
324 bind(&slow_case); | |
325 if (input_reg.is(result_reg)) { | |
326 // Input is clobbered. Restore number from fpu stack | |
327 sub(Operand(esp), Immediate(kDoubleSize)); | |
328 fstp_d(Operand(esp, 0)); | |
329 SlowTruncateToI(esp, result_reg, 0); | |
330 add(esp, Immediate(kDoubleSize)); | |
331 } else { | |
332 fstp(0); | |
333 SlowTruncateToI(input_reg, result_reg); | |
334 } | |
335 } else if (CpuFeatures::IsSupported(SSE2)) { | |
336 CpuFeatureScope scope(this, SSE2); | |
337 movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | |
338 cvttsd2si(result_reg, Operand(xmm0)); | |
339 cmp(result_reg, 0x80000000u); | |
340 j(not_equal, &done, Label::kNear); | |
341 // Check if the input was 0x8000000 (kMinInt). | |
342 // If no, then we got an overflow and we deoptimize. | |
343 ExternalReference min_int = ExternalReference::address_of_min_int(); | |
344 ucomisd(xmm0, Operand::StaticVariable(min_int)); | |
345 j(not_equal, &slow_case, Label::kNear); | |
346 j(parity_even, &slow_case, Label::kNear); // NaN. | |
347 jmp(&done, Label::kNear); | |
348 | |
349 // Slow case. | |
350 bind(&slow_case); | |
351 if (input_reg.is(result_reg)) { | |
352 // Input is clobbered. Restore number from double scratch. | |
353 sub(esp, Immediate(kDoubleSize)); | |
354 movdbl(MemOperand(esp, 0), xmm0); | |
355 SlowTruncateToI(esp, result_reg, 0); | |
356 add(esp, Immediate(kDoubleSize)); | |
357 } else { | |
358 SlowTruncateToI(input_reg, result_reg); | |
359 } | |
360 } else { | |
361 SlowTruncateToI(input_reg, result_reg); | |
362 } | |
363 bind(&done); | |
364 } | |
365 | |
366 | |
367 void MacroAssembler::TaggedToI(Register input_reg, Register result_reg, | |
368 XMMRegister temp, bool treat_minus_zero_as_zero, Label* lost_precision) { | |
369 Label done; | |
370 ASSERT(!temp.is(xmm0)); | |
371 | |
372 cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | |
373 isolate()->factory()->heap_number_map()); | |
374 j(not_equal, lost_precision, Label::kNear); | |
375 | |
376 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { | |
377 ASSERT(!temp.is(no_xmm_reg)); | |
378 CpuFeatureScope scope(this, SSE2); | |
379 | |
380 movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | |
381 cvttsd2si(result_reg, Operand(xmm0)); | |
382 cvtsi2sd(temp, Operand(result_reg)); | |
383 ucomisd(xmm0, temp); | |
384 RecordComment("Deferred TaggedToI: lost precision"); | |
385 j(not_equal, lost_precision, Label::kNear); | |
386 RecordComment("Deferred TaggedToI: NaN"); | |
387 j(parity_even, lost_precision, Label::kNear); | |
388 if (!treat_minus_zero_as_zero) { | |
389 test(result_reg, Operand(result_reg)); | |
390 j(not_zero, &done, Label::kNear); | |
391 movmskpd(result_reg, xmm0); | |
392 and_(result_reg, 1); | |
393 RecordComment("Deferred TaggedToI: minus zero"); | |
394 j(not_zero, lost_precision, Label::kNear); | |
395 } | |
396 } else { | |
397 // TODO(olivf) Converting a number on the fpu is actually quite slow. We | |
398 // should first try a fast conversion and then bailout to this slow case. | |
399 Label lost_precision_pop, zero_check; | |
400 sub(esp, Immediate(kPointerSize)); | |
401 fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | |
402 if (!treat_minus_zero_as_zero) fld(0); | |
403 fist_s(MemOperand(esp, 0)); | |
404 fild_s(MemOperand(esp, 0)); | |
405 FCmp(); | |
406 pop(result_reg); | |
407 j(not_equal, !treat_minus_zero_as_zero | |
danno
2013/08/20 16:14:28
nit: Factor this label decision out into a variabl
oliv
2013/08/20 16:56:23
Done.
| |
408 ? &lost_precision_pop : lost_precision, Label::kNear); | |
409 j(parity_even, !treat_minus_zero_as_zero | |
410 ? &lost_precision_pop : lost_precision, Label::kNear); // NaN. | |
411 if (!treat_minus_zero_as_zero) { | |
412 test(result_reg, Operand(result_reg)); | |
413 j(zero, &zero_check, Label::kNear); | |
414 fstp(0); | |
415 jmp(&done, Label::kNear); | |
416 bind(&zero_check); | |
417 // To check for minus zero, we load the value again as float, and check | |
418 // if that is still 0. | |
419 sub(esp, Immediate(kPointerSize)); | |
420 fstp_s(Operand(esp, 0)); | |
421 pop(result_reg); | |
422 test(result_reg, Operand(result_reg)); | |
423 j(zero, &done, Label::kNear); | |
424 jmp(lost_precision, Label::kNear); | |
425 | |
426 bind(&lost_precision_pop); | |
427 fstp(0); | |
428 jmp(lost_precision, Label::kNear); | |
429 } | |
430 } | |
431 bind(&done); | |
432 } | |
433 | |
434 | |
435 | |
218 static double kUint32Bias = | 436 static double kUint32Bias = |
219 static_cast<double>(static_cast<uint32_t>(0xFFFFFFFF)) + 1; | 437 static_cast<double>(static_cast<uint32_t>(0xFFFFFFFF)) + 1; |
220 | 438 |
221 | 439 |
222 void MacroAssembler::LoadUint32(XMMRegister dst, | 440 void MacroAssembler::LoadUint32(XMMRegister dst, |
223 Register src, | 441 Register src, |
224 XMMRegister scratch) { | 442 XMMRegister scratch) { |
225 Label done; | 443 Label done; |
226 cmp(src, Immediate(0)); | 444 cmp(src, Immediate(0)); |
227 movdbl(scratch, | 445 movdbl(scratch, |
(...skipping 3009 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3237 j(greater, &no_memento_available); | 3455 j(greater, &no_memento_available); |
3238 cmp(MemOperand(scratch_reg, -AllocationMemento::kSize), | 3456 cmp(MemOperand(scratch_reg, -AllocationMemento::kSize), |
3239 Immediate(Handle<Map>(isolate()->heap()->allocation_memento_map()))); | 3457 Immediate(Handle<Map>(isolate()->heap()->allocation_memento_map()))); |
3240 bind(&no_memento_available); | 3458 bind(&no_memento_available); |
3241 } | 3459 } |
3242 | 3460 |
3243 | 3461 |
3244 } } // namespace v8::internal | 3462 } } // namespace v8::internal |
3245 | 3463 |
3246 #endif // V8_TARGET_ARCH_IA32 | 3464 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |