OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 #endif | 402 #endif |
403 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry()); | 403 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry()); |
404 int res = reinterpret_cast<int>( | 404 int res = reinterpret_cast<int>( |
405 CALL_GENERATED_CODE(f, 0xFFFF, 0, 0, 0, 0)); | 405 CALL_GENERATED_CODE(f, 0xFFFF, 0, 0, 0, 0)); |
406 ::printf("f() = %d\n", res); | 406 ::printf("f() = %d\n", res); |
407 CHECK_EQ(382, res); | 407 CHECK_EQ(382, res); |
408 } | 408 } |
409 } | 409 } |
410 | 410 |
411 | 411 |
412 static void TestRoundingMode(int32_t mode, double value, int expected) { | 412 enum VCVTTypes { |
| 413 s32_f64, |
| 414 u32_f64 |
| 415 }; |
| 416 |
| 417 static void TestRoundingMode(VCVTTypes types, |
| 418 VFPRoundingMode mode, |
| 419 double value, |
| 420 int expected, |
| 421 bool expected_exception = false) { |
413 InitializeVM(); | 422 InitializeVM(); |
414 v8::HandleScope scope; | 423 v8::HandleScope scope; |
415 | 424 |
416 Assembler assm(NULL, 0); | 425 Assembler assm(NULL, 0); |
417 | 426 |
418 __ vmrs(r1); | 427 if (CpuFeatures::IsSupported(VFP3)) { |
419 // Set custom FPSCR. | 428 CpuFeatures::Scope scope(VFP3); |
420 __ bic(r2, r1, Operand(((mode ^ 3) << 22) | 0xf)); | |
421 __ orr(r2, r2, Operand(mode << 22)); | |
422 __ vmsr(r2); | |
423 | 429 |
424 // Load value, convert, and move back result to r0. | 430 Label wrong_exception; |
425 __ vmov(d1, value); | |
426 __ vcvt_s32_f64(s0, d1, Assembler::FPSCRRounding, al); | |
427 __ vmov(r0, s0); | |
428 | 431 |
429 __ mov(pc, Operand(lr)); | 432 __ vmrs(r1); |
| 433 // Set custom FPSCR. |
| 434 __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask)); |
| 435 __ orr(r2, r2, Operand(mode)); |
| 436 __ vmsr(r2); |
430 | 437 |
431 CodeDesc desc; | 438 // Load value, convert, and move back result to r0 if everything went well. |
432 assm.GetCode(&desc); | 439 __ vmov(d1, value); |
433 Object* code = Heap::CreateCode( | 440 switch (types) { |
434 desc, | 441 case s32_f64: |
435 Code::ComputeFlags(Code::STUB), | 442 __ vcvt_s32_f64(s0, d1, kFPSCRRounding); |
436 Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); | 443 break; |
437 CHECK(code->IsCode()); | 444 |
| 445 case u32_f64: |
| 446 __ vcvt_u32_f64(s0, d1, kFPSCRRounding); |
| 447 break; |
| 448 |
| 449 default: |
| 450 UNREACHABLE(); |
| 451 break; |
| 452 } |
| 453 // Check for vfp exceptions |
| 454 __ vmrs(r2); |
| 455 __ tst(r2, Operand(kVFPExceptionMask)); |
| 456 // Check that we behaved as expected. |
| 457 __ b(&wrong_exception, |
| 458 expected_exception ? eq : ne); |
| 459 // There was no exception. Retrieve the result and return. |
| 460 __ vmov(r0, s0); |
| 461 __ mov(pc, Operand(lr)); |
| 462 |
| 463 // The exception behaviour is not what we expected. |
| 464 // Load a special value and return. |
| 465 __ bind(&wrong_exception); |
| 466 __ mov(r0, Operand(11223344)); |
| 467 __ mov(pc, Operand(lr)); |
| 468 |
| 469 CodeDesc desc; |
| 470 assm.GetCode(&desc); |
| 471 Object* code = Heap::CreateCode( |
| 472 desc, |
| 473 Code::ComputeFlags(Code::STUB), |
| 474 Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); |
| 475 CHECK(code->IsCode()); |
438 #ifdef DEBUG | 476 #ifdef DEBUG |
439 Code::cast(code)->Print(); | 477 Code::cast(code)->Print(); |
440 #endif | 478 #endif |
441 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry()); | 479 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry()); |
442 int res = reinterpret_cast<int>( | 480 int res = reinterpret_cast<int>( |
443 CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); | 481 CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); |
444 ::printf("res = %d\n", res); | 482 ::printf("res = %d\n", res); |
445 CHECK_EQ(expected, res); | 483 CHECK_EQ(expected, res); |
| 484 } |
446 } | 485 } |
447 | 486 |
448 | 487 |
449 TEST(7) { | 488 TEST(7) { |
450 // Test vfp rounding modes. | 489 // Test vfp rounding modes. |
451 | 490 |
452 // See ARM DDI 0406B Page A2-29. | 491 // s32_f64 (double to integer). |
453 enum FPSCRRoungingMode { | |
454 RN, // Round to Nearest. | |
455 RP, // Round towards Plus Infinity. | |
456 RM, // Round towards Minus Infinity. | |
457 RZ // Round towards zero. | |
458 }; | |
459 | 492 |
460 if (CpuFeatures::IsSupported(VFP3)) { | 493 TestRoundingMode(s32_f64, RN, 0, 0); |
461 CpuFeatures::Scope scope(VFP3); | 494 TestRoundingMode(s32_f64, RN, 0.5, 0); |
| 495 TestRoundingMode(s32_f64, RN, -0.5, 0); |
| 496 TestRoundingMode(s32_f64, RN, 1.5, 2); |
| 497 TestRoundingMode(s32_f64, RN, -1.5, -2); |
| 498 TestRoundingMode(s32_f64, RN, 123.7, 124); |
| 499 TestRoundingMode(s32_f64, RN, -123.7, -124); |
| 500 TestRoundingMode(s32_f64, RN, 123456.2, 123456); |
| 501 TestRoundingMode(s32_f64, RN, -123456.2, -123456); |
| 502 TestRoundingMode(s32_f64, RN, static_cast<double>(kMaxInt), kMaxInt); |
| 503 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.49), kMaxInt); |
| 504 TestRoundingMode(s32_f64, RN, (kMaxInt + 1.0), kMaxInt, true); |
| 505 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.5), kMaxInt, true); |
| 506 TestRoundingMode(s32_f64, RN, static_cast<double>(kMinInt), kMinInt); |
| 507 TestRoundingMode(s32_f64, RN, (kMinInt - 0.5), kMinInt); |
| 508 TestRoundingMode(s32_f64, RN, (kMinInt - 1.0), kMinInt, true); |
| 509 TestRoundingMode(s32_f64, RN, (kMinInt - 0.51), kMinInt, true); |
462 | 510 |
463 TestRoundingMode(RZ, 0.5, 0); | 511 TestRoundingMode(s32_f64, RM, 0, 0); |
464 TestRoundingMode(RZ, -0.5, 0); | 512 TestRoundingMode(s32_f64, RM, 0.5, 0); |
465 TestRoundingMode(RZ, 123.7, 123); | 513 TestRoundingMode(s32_f64, RM, -0.5, -1); |
466 TestRoundingMode(RZ, -123.7, -123); | 514 TestRoundingMode(s32_f64, RM, 123.7, 123); |
467 TestRoundingMode(RZ, 123456.2, 123456); | 515 TestRoundingMode(s32_f64, RM, -123.7, -124); |
468 TestRoundingMode(RZ, -123456.2, -123456); | 516 TestRoundingMode(s32_f64, RM, 123456.2, 123456); |
| 517 TestRoundingMode(s32_f64, RM, -123456.2, -123457); |
| 518 TestRoundingMode(s32_f64, RM, static_cast<double>(kMaxInt), kMaxInt); |
| 519 TestRoundingMode(s32_f64, RM, (kMaxInt + 0.5), kMaxInt); |
| 520 TestRoundingMode(s32_f64, RM, (kMaxInt + 1.0), kMaxInt, true); |
| 521 TestRoundingMode(s32_f64, RM, static_cast<double>(kMinInt), kMinInt); |
| 522 TestRoundingMode(s32_f64, RM, (kMinInt - 0.5), kMinInt, true); |
| 523 TestRoundingMode(s32_f64, RM, (kMinInt + 0.5), kMinInt); |
469 | 524 |
470 TestRoundingMode(RM, 0.5, 0); | 525 TestRoundingMode(s32_f64, RZ, 0, 0); |
471 TestRoundingMode(RM, -0.5, -1); | 526 TestRoundingMode(s32_f64, RZ, 0.5, 0); |
472 TestRoundingMode(RM, 123.7, 123); | 527 TestRoundingMode(s32_f64, RZ, -0.5, 0); |
473 TestRoundingMode(RM, -123.7, -124); | 528 TestRoundingMode(s32_f64, RZ, 123.7, 123); |
474 TestRoundingMode(RM, 123456.2, 123456); | 529 TestRoundingMode(s32_f64, RZ, -123.7, -123); |
475 TestRoundingMode(RM, -123456.2, -123457); | 530 TestRoundingMode(s32_f64, RZ, 123456.2, 123456); |
476 } | 531 TestRoundingMode(s32_f64, RZ, -123456.2, -123456); |
| 532 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt); |
| 533 TestRoundingMode(s32_f64, RZ, (kMaxInt + 0.5), kMaxInt); |
| 534 TestRoundingMode(s32_f64, RZ, (kMaxInt + 1.0), kMaxInt, true); |
| 535 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMinInt), kMinInt); |
| 536 TestRoundingMode(s32_f64, RZ, (kMinInt - 0.5), kMinInt); |
| 537 TestRoundingMode(s32_f64, RZ, (kMinInt - 1.0), kMinInt, true); |
| 538 |
| 539 |
| 540 // u32_f64 (double to integer). |
| 541 |
| 542 // Negative values. |
| 543 TestRoundingMode(u32_f64, RN, -0.5, 0); |
| 544 TestRoundingMode(u32_f64, RN, -123456.7, 0, true); |
| 545 TestRoundingMode(u32_f64, RN, static_cast<double>(kMinInt), 0, true); |
| 546 TestRoundingMode(u32_f64, RN, kMinInt - 1.0, 0, true); |
| 547 |
| 548 TestRoundingMode(u32_f64, RM, -0.5, 0, true); |
| 549 TestRoundingMode(u32_f64, RM, -123456.7, 0, true); |
| 550 TestRoundingMode(u32_f64, RM, static_cast<double>(kMinInt), 0, true); |
| 551 TestRoundingMode(u32_f64, RM, kMinInt - 1.0, 0, true); |
| 552 |
| 553 TestRoundingMode(u32_f64, RZ, -0.5, 0); |
| 554 TestRoundingMode(u32_f64, RZ, -123456.7, 0, true); |
| 555 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMinInt), 0, true); |
| 556 TestRoundingMode(u32_f64, RZ, kMinInt - 1.0, 0, true); |
| 557 |
| 558 // Positive values. |
| 559 // kMaxInt is the maximum *signed* integer: 0x7fffffff. |
| 560 static const uint32_t kMaxUInt = 0xffffffffu; |
| 561 TestRoundingMode(u32_f64, RZ, 0, 0); |
| 562 TestRoundingMode(u32_f64, RZ, 0.5, 0); |
| 563 TestRoundingMode(u32_f64, RZ, 123.7, 123); |
| 564 TestRoundingMode(u32_f64, RZ, 123456.2, 123456); |
| 565 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt); |
| 566 TestRoundingMode(u32_f64, RZ, (kMaxInt + 0.5), kMaxInt); |
| 567 TestRoundingMode(u32_f64, RZ, (kMaxInt + 1.0), |
| 568 static_cast<uint32_t>(kMaxInt) + 1); |
| 569 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 0.5), kMaxUInt); |
| 570 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 1.0), kMaxUInt, true); |
| 571 |
| 572 TestRoundingMode(u32_f64, RM, 0, 0); |
| 573 TestRoundingMode(u32_f64, RM, 0.5, 0); |
| 574 TestRoundingMode(u32_f64, RM, 123.7, 123); |
| 575 TestRoundingMode(u32_f64, RM, 123456.2, 123456); |
| 576 TestRoundingMode(u32_f64, RM, static_cast<double>(kMaxInt), kMaxInt); |
| 577 TestRoundingMode(u32_f64, RM, (kMaxInt + 0.5), kMaxInt); |
| 578 TestRoundingMode(u32_f64, RM, (kMaxInt + 1.0), |
| 579 static_cast<uint32_t>(kMaxInt) + 1); |
| 580 TestRoundingMode(u32_f64, RM, (kMaxUInt + 0.5), kMaxUInt); |
| 581 TestRoundingMode(u32_f64, RM, (kMaxUInt + 1.0), kMaxUInt, true); |
| 582 |
| 583 TestRoundingMode(u32_f64, RN, 0, 0); |
| 584 TestRoundingMode(u32_f64, RN, 0.5, 0); |
| 585 TestRoundingMode(u32_f64, RN, 1.5, 2); |
| 586 TestRoundingMode(u32_f64, RN, 123.7, 124); |
| 587 TestRoundingMode(u32_f64, RN, 123456.2, 123456); |
| 588 TestRoundingMode(u32_f64, RN, static_cast<double>(kMaxInt), kMaxInt); |
| 589 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.49), kMaxInt); |
| 590 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.5), |
| 591 static_cast<uint32_t>(kMaxInt) + 1); |
| 592 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.49), kMaxUInt); |
| 593 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.5), kMaxUInt, true); |
| 594 TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true); |
477 } | 595 } |
478 | 596 |
479 #undef __ | 597 #undef __ |
OLD | NEW |