Chromium Code Reviews| 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 |