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