OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLsa); | 516 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLsa); |
517 for (size_t i = 0; i < nr_test_cases; ++i) { | 517 for (size_t i = 0; i < nr_test_cases; ++i) { |
518 uint64_t res = run_dlsa(tc[i].rt, tc[i].rs, tc[i].sa); | 518 uint64_t res = run_dlsa(tc[i].rt, tc[i].rs, tc[i].sa); |
519 PrintF("0x%" PRIx64 " =? 0x%" PRIx64 " == Dlsa(v0, %" PRIx64 ", %" PRIx64 | 519 PrintF("0x%" PRIx64 " =? 0x%" PRIx64 " == Dlsa(v0, %" PRIx64 ", %" PRIx64 |
520 ", %hhu)\n", | 520 ", %hhu)\n", |
521 tc[i].expected_res, res, tc[i].rt, tc[i].rs, tc[i].sa); | 521 tc[i].expected_res, res, tc[i].rt, tc[i].rs, tc[i].sa); |
522 CHECK_EQ(tc[i].expected_res, res); | 522 CHECK_EQ(tc[i].expected_res, res); |
523 } | 523 } |
524 } | 524 } |
525 | 525 |
526 static const std::vector<uint32_t> uint32_test_values() { | 526 static const std::vector<uint32_t> cvt_trunc_uint32_test_values() { |
527 static const uint32_t kValues[] = {0x00000000, 0x00000001, 0x00ffff00, | 527 static const uint32_t kValues[] = {0x00000000, 0x00000001, 0x00ffff00, |
528 0x7fffffff, 0x80000000, 0x80000001, | 528 0x7fffffff, 0x80000000, 0x80000001, |
529 0x80ffff00, 0x8fffffff, 0xffffffff}; | 529 0x80ffff00, 0x8fffffff, 0xffffffff}; |
530 return std::vector<uint32_t>(&kValues[0], &kValues[arraysize(kValues)]); | 530 return std::vector<uint32_t>(&kValues[0], &kValues[arraysize(kValues)]); |
531 } | 531 } |
532 | 532 |
533 static const std::vector<int32_t> int32_test_values() { | 533 static const std::vector<int32_t> cvt_trunc_int32_test_values() { |
534 static const int32_t kValues[] = { | 534 static const int32_t kValues[] = { |
535 static_cast<int32_t>(0x00000000), static_cast<int32_t>(0x00000001), | 535 static_cast<int32_t>(0x00000000), static_cast<int32_t>(0x00000001), |
536 static_cast<int32_t>(0x00ffff00), static_cast<int32_t>(0x7fffffff), | 536 static_cast<int32_t>(0x00ffff00), static_cast<int32_t>(0x7fffffff), |
537 static_cast<int32_t>(0x80000000), static_cast<int32_t>(0x80000001), | 537 static_cast<int32_t>(0x80000000), static_cast<int32_t>(0x80000001), |
538 static_cast<int32_t>(0x80ffff00), static_cast<int32_t>(0x8fffffff), | 538 static_cast<int32_t>(0x80ffff00), static_cast<int32_t>(0x8fffffff), |
539 static_cast<int32_t>(0xffffffff)}; | 539 static_cast<int32_t>(0xffffffff)}; |
540 return std::vector<int32_t>(&kValues[0], &kValues[arraysize(kValues)]); | 540 return std::vector<int32_t>(&kValues[0], &kValues[arraysize(kValues)]); |
541 } | 541 } |
542 | 542 |
543 static const std::vector<uint64_t> uint64_test_values() { | 543 static const std::vector<uint64_t> cvt_trunc_uint64_test_values() { |
544 static const uint64_t kValues[] = { | 544 static const uint64_t kValues[] = { |
545 0x0000000000000000, 0x0000000000000001, 0x0000ffffffff0000, | 545 0x0000000000000000, 0x0000000000000001, 0x0000ffffffff0000, |
546 0x7fffffffffffffff, 0x8000000000000000, 0x8000000000000001, | 546 0x7fffffffffffffff, 0x8000000000000000, 0x8000000000000001, |
547 0x8000ffffffff0000, 0x8fffffffffffffff, 0xffffffffffffffff}; | 547 0x8000ffffffff0000, 0x8fffffffffffffff, 0xffffffffffffffff}; |
548 return std::vector<uint64_t>(&kValues[0], &kValues[arraysize(kValues)]); | 548 return std::vector<uint64_t>(&kValues[0], &kValues[arraysize(kValues)]); |
549 } | 549 } |
550 | 550 |
551 static const std::vector<int64_t> int64_test_values() { | 551 static const std::vector<int64_t> cvt_trunc_int64_test_values() { |
552 static const int64_t kValues[] = {static_cast<int64_t>(0x0000000000000000), | 552 static const int64_t kValues[] = {static_cast<int64_t>(0x0000000000000000), |
553 static_cast<int64_t>(0x0000000000000001), | 553 static_cast<int64_t>(0x0000000000000001), |
554 static_cast<int64_t>(0x0000ffffffff0000), | 554 static_cast<int64_t>(0x0000ffffffff0000), |
555 static_cast<int64_t>(0x7fffffffffffffff), | 555 static_cast<int64_t>(0x7fffffffffffffff), |
556 static_cast<int64_t>(0x8000000000000000), | 556 static_cast<int64_t>(0x8000000000000000), |
557 static_cast<int64_t>(0x8000000000000001), | 557 static_cast<int64_t>(0x8000000000000001), |
558 static_cast<int64_t>(0x8000ffffffff0000), | 558 static_cast<int64_t>(0x8000ffffffff0000), |
559 static_cast<int64_t>(0x8fffffffffffffff), | 559 static_cast<int64_t>(0x8fffffffffffffff), |
560 static_cast<int64_t>(0xffffffffffffffff)}; | 560 static_cast<int64_t>(0xffffffffffffffff)}; |
561 return std::vector<int64_t>(&kValues[0], &kValues[arraysize(kValues)]); | 561 return std::vector<int64_t>(&kValues[0], &kValues[arraysize(kValues)]); |
562 } | 562 } |
563 | 563 |
564 // Helper macros that can be used in FOR_INT32_INPUTS(i) { ... *i ... } | 564 // Helper macros that can be used in FOR_INT32_INPUTS(i) { ... *i ... } |
565 #define FOR_INPUTS(ctype, itype, var) \ | 565 #define FOR_INPUTS(ctype, itype, var, test_vector) \ |
566 std::vector<ctype> var##_vec = itype##_test_values(); \ | 566 std::vector<ctype> var##_vec = test_vector(); \ |
567 for (std::vector<ctype>::iterator var = var##_vec.begin(); \ | 567 for (std::vector<ctype>::iterator var = var##_vec.begin(); \ |
568 var != var##_vec.end(); ++var) | 568 var != var##_vec.end(); ++var) |
569 | 569 |
570 #define FOR_INT32_INPUTS(var) FOR_INPUTS(int32_t, int32, var) | 570 #define FOR_ENUM_INPUTS(var, type, test_vector) \ |
571 #define FOR_INT64_INPUTS(var) FOR_INPUTS(int64_t, int64, var) | 571 FOR_INPUTS(enum type, type, var, test_vector) |
572 #define FOR_UINT32_INPUTS(var) FOR_INPUTS(uint32_t, uint32, var) | 572 #define FOR_STRUCT_INPUTS(var, type, test_vector) \ |
573 #define FOR_UINT64_INPUTS(var) FOR_INPUTS(uint64_t, uint64, var) | 573 FOR_INPUTS(struct type, type, var, test_vector) |
| 574 #define FOR_INT32_INPUTS(var, test_vector) \ |
| 575 FOR_INPUTS(int32_t, int32, var, test_vector) |
| 576 #define FOR_INT64_INPUTS(var, test_vector) \ |
| 577 FOR_INPUTS(int64_t, int64, var, test_vector) |
| 578 #define FOR_UINT32_INPUTS(var, test_vector) \ |
| 579 FOR_INPUTS(uint32_t, uint32, var, test_vector) |
| 580 #define FOR_UINT64_INPUTS(var, test_vector) \ |
| 581 FOR_INPUTS(uint64_t, uint64, var, test_vector) |
574 | 582 |
575 template <typename RET_TYPE, typename IN_TYPE, typename Func> | 583 template <typename RET_TYPE, typename IN_TYPE, typename Func> |
576 RET_TYPE run_Cvt(IN_TYPE x, Func GenerateConvertInstructionFunc) { | 584 RET_TYPE run_Cvt(IN_TYPE x, Func GenerateConvertInstructionFunc) { |
577 typedef RET_TYPE (*F_CVT)(IN_TYPE x0, int x1, int x2, int x3, int x4); | 585 typedef RET_TYPE (*F_CVT)(IN_TYPE x0, int x1, int x2, int x3, int x4); |
578 | 586 |
579 Isolate* isolate = CcTest::i_isolate(); | 587 Isolate* isolate = CcTest::i_isolate(); |
580 HandleScope scope(isolate); | 588 HandleScope scope(isolate); |
581 MacroAssembler assm(isolate, nullptr, 0, | 589 MacroAssembler assm(isolate, nullptr, 0, |
582 v8::internal::CodeObjectRequired::kYes); | 590 v8::internal::CodeObjectRequired::kYes); |
583 MacroAssembler* masm = &assm; | 591 MacroAssembler* masm = &assm; |
584 | 592 |
585 GenerateConvertInstructionFunc(masm); | 593 GenerateConvertInstructionFunc(masm); |
586 __ dmfc1(v0, f2); | 594 __ dmfc1(v0, f2); |
587 __ jr(ra); | 595 __ jr(ra); |
588 __ nop(); | 596 __ nop(); |
589 | 597 |
590 CodeDesc desc; | 598 CodeDesc desc; |
591 assm.GetCode(&desc); | 599 assm.GetCode(&desc); |
592 Handle<Code> code = isolate->factory()->NewCode( | 600 Handle<Code> code = isolate->factory()->NewCode( |
593 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); | 601 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
594 | 602 |
595 F_CVT f = FUNCTION_CAST<F_CVT>(code->entry()); | 603 F_CVT f = FUNCTION_CAST<F_CVT>(code->entry()); |
596 | 604 |
597 return reinterpret_cast<RET_TYPE>( | 605 return reinterpret_cast<RET_TYPE>( |
598 CALL_GENERATED_CODE(isolate, f, x, 0, 0, 0, 0)); | 606 CALL_GENERATED_CODE(isolate, f, x, 0, 0, 0, 0)); |
599 } | 607 } |
600 | 608 |
601 TEST(Cvt_s_uw_Trunc_uw_s) { | 609 TEST(Cvt_s_uw_Trunc_uw_s) { |
602 CcTest::InitializeVM(); | 610 CcTest::InitializeVM(); |
603 FOR_UINT32_INPUTS(i) { | 611 FOR_UINT32_INPUTS(i, cvt_trunc_uint32_test_values) { |
604 uint32_t input = *i; | 612 uint32_t input = *i; |
605 CHECK_EQ(static_cast<float>(input), | 613 CHECK_EQ(static_cast<float>(input), |
606 run_Cvt<uint64_t>(input, [](MacroAssembler* masm) { | 614 run_Cvt<uint64_t>(input, [](MacroAssembler* masm) { |
607 __ Cvt_s_uw(f0, a0); | 615 __ Cvt_s_uw(f0, a0); |
608 __ mthc1(zero_reg, f2); | 616 __ mthc1(zero_reg, f2); |
609 __ Trunc_uw_s(f2, f0, f1); | 617 __ Trunc_uw_s(f2, f0, f1); |
610 })); | 618 })); |
611 } | 619 } |
612 } | 620 } |
613 | 621 |
614 TEST(Cvt_s_ul_Trunc_ul_s) { | 622 TEST(Cvt_s_ul_Trunc_ul_s) { |
615 CcTest::InitializeVM(); | 623 CcTest::InitializeVM(); |
616 FOR_UINT64_INPUTS(i) { | 624 FOR_UINT64_INPUTS(i, cvt_trunc_uint64_test_values) { |
617 uint64_t input = *i; | 625 uint64_t input = *i; |
618 CHECK_EQ(static_cast<float>(input), | 626 CHECK_EQ(static_cast<float>(input), |
619 run_Cvt<uint64_t>(input, [](MacroAssembler* masm) { | 627 run_Cvt<uint64_t>(input, [](MacroAssembler* masm) { |
620 __ Cvt_s_ul(f0, a0); | 628 __ Cvt_s_ul(f0, a0); |
621 __ Trunc_ul_s(f2, f0, f1, v0); | 629 __ Trunc_ul_s(f2, f0, f1, v0); |
622 })); | 630 })); |
623 } | 631 } |
624 } | 632 } |
625 | 633 |
626 TEST(Cvt_d_ul_Trunc_ul_d) { | 634 TEST(Cvt_d_ul_Trunc_ul_d) { |
627 CcTest::InitializeVM(); | 635 CcTest::InitializeVM(); |
628 FOR_UINT64_INPUTS(i) { | 636 FOR_UINT64_INPUTS(i, cvt_trunc_uint64_test_values) { |
629 uint64_t input = *i; | 637 uint64_t input = *i; |
630 CHECK_EQ(static_cast<double>(input), | 638 CHECK_EQ(static_cast<double>(input), |
631 run_Cvt<uint64_t>(input, [](MacroAssembler* masm) { | 639 run_Cvt<uint64_t>(input, [](MacroAssembler* masm) { |
632 __ Cvt_d_ul(f0, a0); | 640 __ Cvt_d_ul(f0, a0); |
633 __ Trunc_ul_d(f2, f0, f1, v0); | 641 __ Trunc_ul_d(f2, f0, f1, v0); |
634 })); | 642 })); |
635 } | 643 } |
636 } | 644 } |
637 | 645 |
638 TEST(cvt_d_l_Trunc_l_d) { | 646 TEST(cvt_d_l_Trunc_l_d) { |
639 CcTest::InitializeVM(); | 647 CcTest::InitializeVM(); |
640 FOR_INT64_INPUTS(i) { | 648 FOR_INT64_INPUTS(i, cvt_trunc_int64_test_values) { |
641 int64_t input = *i; | 649 int64_t input = *i; |
642 CHECK_EQ(static_cast<double>(input), | 650 CHECK_EQ(static_cast<double>(input), |
643 run_Cvt<int64_t>(input, [](MacroAssembler* masm) { | 651 run_Cvt<int64_t>(input, [](MacroAssembler* masm) { |
644 __ dmtc1(a0, f4); | 652 __ dmtc1(a0, f4); |
645 __ cvt_d_l(f0, f4); | 653 __ cvt_d_l(f0, f4); |
646 __ Trunc_l_d(f2, f0); | 654 __ Trunc_l_d(f2, f0); |
647 })); | 655 })); |
648 } | 656 } |
649 } | 657 } |
650 | 658 |
651 TEST(cvt_d_l_Trunc_l_ud) { | 659 TEST(cvt_d_l_Trunc_l_ud) { |
652 CcTest::InitializeVM(); | 660 CcTest::InitializeVM(); |
653 FOR_INT64_INPUTS(i) { | 661 FOR_INT64_INPUTS(i, cvt_trunc_int64_test_values) { |
654 int64_t input = *i; | 662 int64_t input = *i; |
655 uint64_t abs_input = (input < 0) ? -input : input; | 663 uint64_t abs_input = (input < 0) ? -input : input; |
656 CHECK_EQ(static_cast<double>(abs_input), | 664 CHECK_EQ(static_cast<double>(abs_input), |
657 run_Cvt<uint64_t>(input, [](MacroAssembler* masm) { | 665 run_Cvt<uint64_t>(input, [](MacroAssembler* masm) { |
658 __ dmtc1(a0, f4); | 666 __ dmtc1(a0, f4); |
659 __ cvt_d_l(f0, f4); | 667 __ cvt_d_l(f0, f4); |
660 __ Trunc_l_ud(f2, f0, f6); | 668 __ Trunc_l_ud(f2, f0, f6); |
661 })); | 669 })); |
662 } | 670 } |
663 } | 671 } |
664 | 672 |
665 TEST(cvt_d_w_Trunc_w_d) { | 673 TEST(cvt_d_w_Trunc_w_d) { |
666 CcTest::InitializeVM(); | 674 CcTest::InitializeVM(); |
667 FOR_INT32_INPUTS(i) { | 675 FOR_INT32_INPUTS(i, cvt_trunc_int32_test_values) { |
668 int32_t input = *i; | 676 int32_t input = *i; |
669 CHECK_EQ(static_cast<double>(input), | 677 CHECK_EQ(static_cast<double>(input), |
670 run_Cvt<int64_t>(input, [](MacroAssembler* masm) { | 678 run_Cvt<int64_t>(input, [](MacroAssembler* masm) { |
671 __ mtc1(a0, f4); | 679 __ mtc1(a0, f4); |
672 __ cvt_d_w(f0, f4); | 680 __ cvt_d_w(f0, f4); |
673 __ Trunc_w_d(f2, f0); | 681 __ Trunc_w_d(f2, f0); |
674 __ mfc1(v1, f2); | 682 __ mfc1(v1, f2); |
675 __ dmtc1(v1, f2); | 683 __ dmtc1(v1, f2); |
676 })); | 684 })); |
677 } | 685 } |
678 } | 686 } |
679 | 687 |
| 688 static const std::vector<int32_t> overflow_int32_test_values() { |
| 689 static const int32_t kValues[] = { |
| 690 static_cast<int32_t>(0xf0000000), static_cast<int32_t>(0x00000001), |
| 691 static_cast<int32_t>(0xff000000), static_cast<int32_t>(0x0000f000), |
| 692 static_cast<int32_t>(0x0f000000), static_cast<int32_t>(0x991234ab), |
| 693 static_cast<int32_t>(0xb0ffff01), static_cast<int32_t>(0x00006fff), |
| 694 static_cast<int32_t>(0xffffffff)}; |
| 695 return std::vector<int32_t>(&kValues[0], &kValues[arraysize(kValues)]); |
| 696 } |
| 697 |
| 698 static const std::vector<int64_t> overflow_int64_test_values() { |
| 699 static const int64_t kValues[] = {static_cast<int64_t>(0xf000000000000000), |
| 700 static_cast<int64_t>(0x0000000000000001), |
| 701 static_cast<int64_t>(0xff00000000000000), |
| 702 static_cast<int64_t>(0x0000f00111111110), |
| 703 static_cast<int64_t>(0x0f00001000000000), |
| 704 static_cast<int64_t>(0x991234ab12a96731), |
| 705 static_cast<int64_t>(0xb0ffff0f0f0f0f01), |
| 706 static_cast<int64_t>(0x00006fffffffffff), |
| 707 static_cast<int64_t>(0xffffffffffffffff)}; |
| 708 return std::vector<int64_t>(&kValues[0], &kValues[arraysize(kValues)]); |
| 709 } |
| 710 |
| 711 enum OverflowBranchType { |
| 712 kAddBranchOverflow, |
| 713 kSubBranchOverflow, |
| 714 }; |
| 715 |
| 716 struct OverflowRegisterCombination { |
| 717 Register dst; |
| 718 Register left; |
| 719 Register right; |
| 720 Register scratch; |
| 721 }; |
| 722 |
| 723 static const std::vector<enum OverflowBranchType> overflow_branch_type() { |
| 724 static const enum OverflowBranchType kValues[] = {kAddBranchOverflow, |
| 725 kSubBranchOverflow}; |
| 726 return std::vector<enum OverflowBranchType>(&kValues[0], |
| 727 &kValues[arraysize(kValues)]); |
| 728 } |
| 729 |
| 730 static const std::vector<struct OverflowRegisterCombination> |
| 731 overflow_register_combination() { |
| 732 static const struct OverflowRegisterCombination kValues[] = { |
| 733 {t0, t1, t2, t3}, {t0, t0, t2, t3}, {t0, t1, t0, t3}, {t0, t1, t1, t3}}; |
| 734 return std::vector<struct OverflowRegisterCombination>( |
| 735 &kValues[0], &kValues[arraysize(kValues)]); |
| 736 } |
| 737 |
| 738 template <typename T> |
| 739 static bool IsAddOverflow(T x, T y) { |
| 740 DCHECK(std::numeric_limits<T>::is_integer); |
| 741 T max = std::numeric_limits<T>::max(); |
| 742 T min = std::numeric_limits<T>::min(); |
| 743 |
| 744 return (x > 0 && y > (max - x)) || (x < 0 && y < (min - x)); |
| 745 } |
| 746 |
| 747 template <typename T> |
| 748 static bool IsSubOverflow(T x, T y) { |
| 749 DCHECK(std::numeric_limits<T>::is_integer); |
| 750 T max = std::numeric_limits<T>::max(); |
| 751 T min = std::numeric_limits<T>::min(); |
| 752 |
| 753 return (y > 0 && x < (min + y)) || (y < 0 && x > (max + y)); |
| 754 } |
| 755 |
| 756 template <typename IN_TYPE, typename Func> |
| 757 static bool runOverflow(IN_TYPE valLeft, IN_TYPE valRight, |
| 758 Func GenerateOverflowInstructions) { |
| 759 typedef int64_t (*F_CVT)(char* x0, int x1, int x2, int x3, int x4); |
| 760 |
| 761 Isolate* isolate = CcTest::i_isolate(); |
| 762 HandleScope scope(isolate); |
| 763 MacroAssembler assm(isolate, nullptr, 0, |
| 764 v8::internal::CodeObjectRequired::kYes); |
| 765 MacroAssembler* masm = &assm; |
| 766 |
| 767 GenerateOverflowInstructions(masm, valLeft, valRight); |
| 768 __ jr(ra); |
| 769 __ nop(); |
| 770 |
| 771 CodeDesc desc; |
| 772 assm.GetCode(&desc); |
| 773 Handle<Code> code = isolate->factory()->NewCode( |
| 774 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 775 |
| 776 F_CVT f = FUNCTION_CAST<F_CVT>(code->entry()); |
| 777 |
| 778 int64_t r = |
| 779 reinterpret_cast<int64_t>(CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); |
| 780 |
| 781 DCHECK(r == 0 || r == 1); |
| 782 return r; |
| 783 } |
| 784 |
| 785 TEST(BranchOverflowInt32BothLabels) { |
| 786 FOR_INT32_INPUTS(i, overflow_int32_test_values) { |
| 787 FOR_INT32_INPUTS(j, overflow_int32_test_values) { |
| 788 FOR_ENUM_INPUTS(br, OverflowBranchType, overflow_branch_type) { |
| 789 FOR_STRUCT_INPUTS(regComb, OverflowRegisterCombination, |
| 790 overflow_register_combination) { |
| 791 int32_t ii = *i; |
| 792 int32_t jj = *j; |
| 793 enum OverflowBranchType branchType = *br; |
| 794 struct OverflowRegisterCombination rc = *regComb; |
| 795 |
| 796 // If left and right register are same then left and right |
| 797 // test values must also be same, otherwise we skip the test |
| 798 if (rc.left.code() == rc.right.code()) { |
| 799 if (ii != jj) { |
| 800 continue; |
| 801 } |
| 802 } |
| 803 |
| 804 bool res1 = runOverflow<int32_t>( |
| 805 ii, jj, [branchType, rc](MacroAssembler* masm, int32_t valLeft, |
| 806 int32_t valRight) { |
| 807 Label overflow, no_overflow, end; |
| 808 __ li(rc.left, valLeft); |
| 809 __ li(rc.right, valRight); |
| 810 switch (branchType) { |
| 811 case kAddBranchOverflow: |
| 812 __ AddBranchOvf(rc.dst, rc.left, rc.right, &overflow, |
| 813 &no_overflow, rc.scratch); |
| 814 break; |
| 815 case kSubBranchOverflow: |
| 816 __ SubBranchOvf(rc.dst, rc.left, rc.right, &overflow, |
| 817 &no_overflow, rc.scratch); |
| 818 break; |
| 819 } |
| 820 __ li(v0, 2); |
| 821 __ Branch(&end); |
| 822 __ bind(&overflow); |
| 823 __ li(v0, 1); |
| 824 __ Branch(&end); |
| 825 __ bind(&no_overflow); |
| 826 __ li(v0, 0); |
| 827 __ bind(&end); |
| 828 }); |
| 829 |
| 830 bool res2 = runOverflow<int32_t>( |
| 831 ii, jj, [branchType, rc](MacroAssembler* masm, int32_t valLeft, |
| 832 int32_t valRight) { |
| 833 Label overflow, no_overflow, end; |
| 834 __ li(rc.left, valLeft); |
| 835 switch (branchType) { |
| 836 case kAddBranchOverflow: |
| 837 __ AddBranchOvf(rc.dst, rc.left, Operand(valRight), |
| 838 &overflow, &no_overflow, rc.scratch); |
| 839 break; |
| 840 case kSubBranchOverflow: |
| 841 __ SubBranchOvf(rc.dst, rc.left, Operand(valRight), |
| 842 &overflow, &no_overflow, rc.scratch); |
| 843 break; |
| 844 } |
| 845 __ li(v0, 2); |
| 846 __ Branch(&end); |
| 847 __ bind(&overflow); |
| 848 __ li(v0, 1); |
| 849 __ Branch(&end); |
| 850 __ bind(&no_overflow); |
| 851 __ li(v0, 0); |
| 852 __ bind(&end); |
| 853 }); |
| 854 |
| 855 switch (branchType) { |
| 856 case kAddBranchOverflow: |
| 857 CHECK_EQ(IsAddOverflow<int32_t>(ii, jj), res1); |
| 858 CHECK_EQ(IsAddOverflow<int32_t>(ii, jj), res2); |
| 859 break; |
| 860 case kSubBranchOverflow: |
| 861 CHECK_EQ(IsSubOverflow<int32_t>(ii, jj), res1); |
| 862 CHECK_EQ(IsSubOverflow<int32_t>(ii, jj), res2); |
| 863 break; |
| 864 default: |
| 865 UNREACHABLE(); |
| 866 } |
| 867 } |
| 868 } |
| 869 } |
| 870 } |
| 871 } |
| 872 |
| 873 TEST(BranchOverflowInt32LeftLabel) { |
| 874 FOR_INT32_INPUTS(i, overflow_int32_test_values) { |
| 875 FOR_INT32_INPUTS(j, overflow_int32_test_values) { |
| 876 FOR_ENUM_INPUTS(br, OverflowBranchType, overflow_branch_type) { |
| 877 FOR_STRUCT_INPUTS(regComb, OverflowRegisterCombination, |
| 878 overflow_register_combination) { |
| 879 int32_t ii = *i; |
| 880 int32_t jj = *j; |
| 881 enum OverflowBranchType branchType = *br; |
| 882 struct OverflowRegisterCombination rc = *regComb; |
| 883 |
| 884 // If left and right register are same then left and right |
| 885 // test values must also be same, otherwise we skip the test |
| 886 if (rc.left.code() == rc.right.code()) { |
| 887 if (ii != jj) { |
| 888 continue; |
| 889 } |
| 890 } |
| 891 |
| 892 bool res1 = runOverflow<int32_t>( |
| 893 ii, jj, [branchType, rc](MacroAssembler* masm, int32_t valLeft, |
| 894 int32_t valRight) { |
| 895 Label overflow, end; |
| 896 __ li(rc.left, valLeft); |
| 897 __ li(rc.right, valRight); |
| 898 switch (branchType) { |
| 899 case kAddBranchOverflow: |
| 900 __ AddBranchOvf(rc.dst, rc.left, rc.right, &overflow, NULL, |
| 901 rc.scratch); |
| 902 break; |
| 903 case kSubBranchOverflow: |
| 904 __ SubBranchOvf(rc.dst, rc.left, rc.right, &overflow, NULL, |
| 905 rc.scratch); |
| 906 break; |
| 907 } |
| 908 __ li(v0, 0); |
| 909 __ Branch(&end); |
| 910 __ bind(&overflow); |
| 911 __ li(v0, 1); |
| 912 __ bind(&end); |
| 913 }); |
| 914 |
| 915 bool res2 = runOverflow<int32_t>( |
| 916 ii, jj, [branchType, rc](MacroAssembler* masm, int32_t valLeft, |
| 917 int32_t valRight) { |
| 918 Label overflow, end; |
| 919 __ li(rc.left, valLeft); |
| 920 switch (branchType) { |
| 921 case kAddBranchOverflow: |
| 922 __ AddBranchOvf(rc.dst, rc.left, Operand(valRight), |
| 923 &overflow, NULL, rc.scratch); |
| 924 break; |
| 925 case kSubBranchOverflow: |
| 926 __ SubBranchOvf(rc.dst, rc.left, Operand(valRight), |
| 927 &overflow, NULL, rc.scratch); |
| 928 break; |
| 929 } |
| 930 __ li(v0, 0); |
| 931 __ Branch(&end); |
| 932 __ bind(&overflow); |
| 933 __ li(v0, 1); |
| 934 __ bind(&end); |
| 935 }); |
| 936 |
| 937 switch (branchType) { |
| 938 case kAddBranchOverflow: |
| 939 CHECK_EQ(IsAddOverflow<int32_t>(ii, jj), res1); |
| 940 CHECK_EQ(IsAddOverflow<int32_t>(ii, jj), res2); |
| 941 break; |
| 942 case kSubBranchOverflow: |
| 943 CHECK_EQ(IsSubOverflow<int32_t>(ii, jj), res1); |
| 944 CHECK_EQ(IsSubOverflow<int32_t>(ii, jj), res2); |
| 945 break; |
| 946 default: |
| 947 UNREACHABLE(); |
| 948 } |
| 949 } |
| 950 } |
| 951 } |
| 952 } |
| 953 } |
| 954 |
| 955 TEST(BranchOverflowInt32RightLabel) { |
| 956 FOR_INT32_INPUTS(i, overflow_int32_test_values) { |
| 957 FOR_INT32_INPUTS(j, overflow_int32_test_values) { |
| 958 FOR_ENUM_INPUTS(br, OverflowBranchType, overflow_branch_type) { |
| 959 FOR_STRUCT_INPUTS(regComb, OverflowRegisterCombination, |
| 960 overflow_register_combination) { |
| 961 int32_t ii = *i; |
| 962 int32_t jj = *j; |
| 963 enum OverflowBranchType branchType = *br; |
| 964 struct OverflowRegisterCombination rc = *regComb; |
| 965 |
| 966 // If left and right register are same then left and right |
| 967 // test values must also be same, otherwise we skip the test |
| 968 if (rc.left.code() == rc.right.code()) { |
| 969 if (ii != jj) { |
| 970 continue; |
| 971 } |
| 972 } |
| 973 |
| 974 bool res1 = runOverflow<int32_t>( |
| 975 ii, jj, [branchType, rc](MacroAssembler* masm, int32_t valLeft, |
| 976 int32_t valRight) { |
| 977 Label no_overflow, end; |
| 978 __ li(rc.left, valLeft); |
| 979 __ li(rc.right, valRight); |
| 980 switch (branchType) { |
| 981 case kAddBranchOverflow: |
| 982 __ AddBranchOvf(rc.dst, rc.left, rc.right, NULL, |
| 983 &no_overflow, rc.scratch); |
| 984 break; |
| 985 case kSubBranchOverflow: |
| 986 __ SubBranchOvf(rc.dst, rc.left, rc.right, NULL, |
| 987 &no_overflow, rc.scratch); |
| 988 break; |
| 989 } |
| 990 __ li(v0, 1); |
| 991 __ Branch(&end); |
| 992 __ bind(&no_overflow); |
| 993 __ li(v0, 0); |
| 994 __ bind(&end); |
| 995 }); |
| 996 |
| 997 bool res2 = runOverflow<int32_t>( |
| 998 ii, jj, [branchType, rc](MacroAssembler* masm, int32_t valLeft, |
| 999 int32_t valRight) { |
| 1000 Label no_overflow, end; |
| 1001 __ li(rc.left, valLeft); |
| 1002 switch (branchType) { |
| 1003 case kAddBranchOverflow: |
| 1004 __ AddBranchOvf(rc.dst, rc.left, Operand(valRight), NULL, |
| 1005 &no_overflow, rc.scratch); |
| 1006 break; |
| 1007 case kSubBranchOverflow: |
| 1008 __ SubBranchOvf(rc.dst, rc.left, Operand(valRight), NULL, |
| 1009 &no_overflow, rc.scratch); |
| 1010 break; |
| 1011 } |
| 1012 __ li(v0, 1); |
| 1013 __ Branch(&end); |
| 1014 __ bind(&no_overflow); |
| 1015 __ li(v0, 0); |
| 1016 __ bind(&end); |
| 1017 }); |
| 1018 |
| 1019 switch (branchType) { |
| 1020 case kAddBranchOverflow: |
| 1021 CHECK_EQ(IsAddOverflow<int32_t>(ii, jj), res1); |
| 1022 CHECK_EQ(IsAddOverflow<int32_t>(ii, jj), res2); |
| 1023 break; |
| 1024 case kSubBranchOverflow: |
| 1025 CHECK_EQ(IsSubOverflow<int32_t>(ii, jj), res1); |
| 1026 CHECK_EQ(IsSubOverflow<int32_t>(ii, jj), res2); |
| 1027 break; |
| 1028 default: |
| 1029 UNREACHABLE(); |
| 1030 } |
| 1031 } |
| 1032 } |
| 1033 } |
| 1034 } |
| 1035 } |
| 1036 |
| 1037 TEST(BranchOverflowInt64BothLabels) { |
| 1038 FOR_INT64_INPUTS(i, overflow_int64_test_values) { |
| 1039 FOR_INT64_INPUTS(j, overflow_int64_test_values) { |
| 1040 FOR_ENUM_INPUTS(br, OverflowBranchType, overflow_branch_type) { |
| 1041 FOR_STRUCT_INPUTS(regComb, OverflowRegisterCombination, |
| 1042 overflow_register_combination) { |
| 1043 int64_t ii = *i; |
| 1044 int64_t jj = *j; |
| 1045 enum OverflowBranchType branchType = *br; |
| 1046 struct OverflowRegisterCombination rc = *regComb; |
| 1047 |
| 1048 // If left and right register are same then left and right |
| 1049 // test values must also be same, otherwise we skip the test |
| 1050 if (rc.left.code() == rc.right.code()) { |
| 1051 if (ii != jj) { |
| 1052 continue; |
| 1053 } |
| 1054 } |
| 1055 |
| 1056 bool res1 = runOverflow<int64_t>( |
| 1057 ii, jj, [branchType, rc](MacroAssembler* masm, int64_t valLeft, |
| 1058 int64_t valRight) { |
| 1059 Label overflow, no_overflow, end; |
| 1060 __ li(rc.left, valLeft); |
| 1061 __ li(rc.right, valRight); |
| 1062 switch (branchType) { |
| 1063 case kAddBranchOverflow: |
| 1064 __ DaddBranchOvf(rc.dst, rc.left, rc.right, &overflow, |
| 1065 &no_overflow, rc.scratch); |
| 1066 break; |
| 1067 case kSubBranchOverflow: |
| 1068 __ DsubBranchOvf(rc.dst, rc.left, rc.right, &overflow, |
| 1069 &no_overflow, rc.scratch); |
| 1070 break; |
| 1071 } |
| 1072 __ li(v0, 2); |
| 1073 __ Branch(&end); |
| 1074 __ bind(&overflow); |
| 1075 __ li(v0, 1); |
| 1076 __ Branch(&end); |
| 1077 __ bind(&no_overflow); |
| 1078 __ li(v0, 0); |
| 1079 __ bind(&end); |
| 1080 }); |
| 1081 |
| 1082 bool res2 = runOverflow<int64_t>( |
| 1083 ii, jj, [branchType, rc](MacroAssembler* masm, int64_t valLeft, |
| 1084 int64_t valRight) { |
| 1085 Label overflow, no_overflow, end; |
| 1086 __ li(rc.left, valLeft); |
| 1087 switch (branchType) { |
| 1088 case kAddBranchOverflow: |
| 1089 __ DaddBranchOvf(rc.dst, rc.left, Operand(valRight), |
| 1090 &overflow, &no_overflow, rc.scratch); |
| 1091 break; |
| 1092 case kSubBranchOverflow: |
| 1093 __ DsubBranchOvf(rc.dst, rc.left, Operand(valRight), |
| 1094 &overflow, &no_overflow, rc.scratch); |
| 1095 break; |
| 1096 } |
| 1097 __ li(v0, 2); |
| 1098 __ Branch(&end); |
| 1099 __ bind(&overflow); |
| 1100 __ li(v0, 1); |
| 1101 __ Branch(&end); |
| 1102 __ bind(&no_overflow); |
| 1103 __ li(v0, 0); |
| 1104 __ bind(&end); |
| 1105 }); |
| 1106 |
| 1107 switch (branchType) { |
| 1108 case kAddBranchOverflow: |
| 1109 CHECK_EQ(IsAddOverflow<int64_t>(ii, jj), res1); |
| 1110 CHECK_EQ(IsAddOverflow<int64_t>(ii, jj), res2); |
| 1111 break; |
| 1112 case kSubBranchOverflow: |
| 1113 CHECK_EQ(IsSubOverflow<int64_t>(ii, jj), res1); |
| 1114 CHECK_EQ(IsSubOverflow<int64_t>(ii, jj), res2); |
| 1115 break; |
| 1116 default: |
| 1117 UNREACHABLE(); |
| 1118 } |
| 1119 } |
| 1120 } |
| 1121 } |
| 1122 } |
| 1123 } |
| 1124 |
| 1125 TEST(BranchOverflowInt64LeftLabel) { |
| 1126 FOR_INT64_INPUTS(i, overflow_int64_test_values) { |
| 1127 FOR_INT64_INPUTS(j, overflow_int64_test_values) { |
| 1128 FOR_ENUM_INPUTS(br, OverflowBranchType, overflow_branch_type) { |
| 1129 FOR_STRUCT_INPUTS(regComb, OverflowRegisterCombination, |
| 1130 overflow_register_combination) { |
| 1131 int64_t ii = *i; |
| 1132 int64_t jj = *j; |
| 1133 enum OverflowBranchType branchType = *br; |
| 1134 struct OverflowRegisterCombination rc = *regComb; |
| 1135 |
| 1136 // If left and right register are same then left and right |
| 1137 // test values must also be same, otherwise we skip the test |
| 1138 if (rc.left.code() == rc.right.code()) { |
| 1139 if (ii != jj) { |
| 1140 continue; |
| 1141 } |
| 1142 } |
| 1143 |
| 1144 bool res1 = runOverflow<int64_t>( |
| 1145 ii, jj, [branchType, rc](MacroAssembler* masm, int64_t valLeft, |
| 1146 int64_t valRight) { |
| 1147 Label overflow, end; |
| 1148 __ li(rc.left, valLeft); |
| 1149 __ li(rc.right, valRight); |
| 1150 switch (branchType) { |
| 1151 case kAddBranchOverflow: |
| 1152 __ DaddBranchOvf(rc.dst, rc.left, rc.right, &overflow, NULL, |
| 1153 rc.scratch); |
| 1154 break; |
| 1155 case kSubBranchOverflow: |
| 1156 __ DsubBranchOvf(rc.dst, rc.left, rc.right, &overflow, NULL, |
| 1157 rc.scratch); |
| 1158 break; |
| 1159 } |
| 1160 __ li(v0, 0); |
| 1161 __ Branch(&end); |
| 1162 __ bind(&overflow); |
| 1163 __ li(v0, 1); |
| 1164 __ bind(&end); |
| 1165 }); |
| 1166 |
| 1167 bool res2 = runOverflow<int64_t>( |
| 1168 ii, jj, [branchType, rc](MacroAssembler* masm, int64_t valLeft, |
| 1169 int64_t valRight) { |
| 1170 Label overflow, end; |
| 1171 __ li(rc.left, valLeft); |
| 1172 switch (branchType) { |
| 1173 case kAddBranchOverflow: |
| 1174 __ DaddBranchOvf(rc.dst, rc.left, Operand(valRight), |
| 1175 &overflow, NULL, rc.scratch); |
| 1176 break; |
| 1177 case kSubBranchOverflow: |
| 1178 __ DsubBranchOvf(rc.dst, rc.left, Operand(valRight), |
| 1179 &overflow, NULL, rc.scratch); |
| 1180 break; |
| 1181 } |
| 1182 __ li(v0, 0); |
| 1183 __ Branch(&end); |
| 1184 __ bind(&overflow); |
| 1185 __ li(v0, 1); |
| 1186 __ bind(&end); |
| 1187 }); |
| 1188 |
| 1189 switch (branchType) { |
| 1190 case kAddBranchOverflow: |
| 1191 CHECK_EQ(IsAddOverflow<int64_t>(ii, jj), res1); |
| 1192 CHECK_EQ(IsAddOverflow<int64_t>(ii, jj), res2); |
| 1193 break; |
| 1194 case kSubBranchOverflow: |
| 1195 CHECK_EQ(IsSubOverflow<int64_t>(ii, jj), res1); |
| 1196 CHECK_EQ(IsSubOverflow<int64_t>(ii, jj), res2); |
| 1197 break; |
| 1198 default: |
| 1199 UNREACHABLE(); |
| 1200 } |
| 1201 } |
| 1202 } |
| 1203 } |
| 1204 } |
| 1205 } |
| 1206 |
| 1207 TEST(BranchOverflowInt64RightLabel) { |
| 1208 FOR_INT64_INPUTS(i, overflow_int64_test_values) { |
| 1209 FOR_INT64_INPUTS(j, overflow_int64_test_values) { |
| 1210 FOR_ENUM_INPUTS(br, OverflowBranchType, overflow_branch_type) { |
| 1211 FOR_STRUCT_INPUTS(regComb, OverflowRegisterCombination, |
| 1212 overflow_register_combination) { |
| 1213 int64_t ii = *i; |
| 1214 int64_t jj = *j; |
| 1215 enum OverflowBranchType branchType = *br; |
| 1216 struct OverflowRegisterCombination rc = *regComb; |
| 1217 |
| 1218 // If left and right register are same then left and right |
| 1219 // test values must also be same, otherwise we skip the test |
| 1220 if (rc.left.code() == rc.right.code()) { |
| 1221 if (ii != jj) { |
| 1222 continue; |
| 1223 } |
| 1224 } |
| 1225 |
| 1226 bool res1 = runOverflow<int64_t>( |
| 1227 ii, jj, [branchType, rc](MacroAssembler* masm, int64_t valLeft, |
| 1228 int64_t valRight) { |
| 1229 Label no_overflow, end; |
| 1230 __ li(rc.left, valLeft); |
| 1231 __ li(rc.right, valRight); |
| 1232 switch (branchType) { |
| 1233 case kAddBranchOverflow: |
| 1234 __ DaddBranchOvf(rc.dst, rc.left, rc.right, NULL, |
| 1235 &no_overflow, rc.scratch); |
| 1236 break; |
| 1237 case kSubBranchOverflow: |
| 1238 __ DsubBranchOvf(rc.dst, rc.left, rc.right, NULL, |
| 1239 &no_overflow, rc.scratch); |
| 1240 break; |
| 1241 } |
| 1242 __ li(v0, 1); |
| 1243 __ Branch(&end); |
| 1244 __ bind(&no_overflow); |
| 1245 __ li(v0, 0); |
| 1246 __ bind(&end); |
| 1247 }); |
| 1248 |
| 1249 bool res2 = runOverflow<int64_t>( |
| 1250 ii, jj, [branchType, rc](MacroAssembler* masm, int64_t valLeft, |
| 1251 int64_t valRight) { |
| 1252 Label no_overflow, end; |
| 1253 __ li(rc.left, valLeft); |
| 1254 switch (branchType) { |
| 1255 case kAddBranchOverflow: |
| 1256 __ DaddBranchOvf(rc.dst, rc.left, Operand(valRight), NULL, |
| 1257 &no_overflow, rc.scratch); |
| 1258 break; |
| 1259 case kSubBranchOverflow: |
| 1260 __ DsubBranchOvf(rc.dst, rc.left, Operand(valRight), NULL, |
| 1261 &no_overflow, rc.scratch); |
| 1262 break; |
| 1263 } |
| 1264 __ li(v0, 1); |
| 1265 __ Branch(&end); |
| 1266 __ bind(&no_overflow); |
| 1267 __ li(v0, 0); |
| 1268 __ bind(&end); |
| 1269 }); |
| 1270 |
| 1271 switch (branchType) { |
| 1272 case kAddBranchOverflow: |
| 1273 CHECK_EQ(IsAddOverflow<int64_t>(ii, jj), res1); |
| 1274 CHECK_EQ(IsAddOverflow<int64_t>(ii, jj), res2); |
| 1275 break; |
| 1276 case kSubBranchOverflow: |
| 1277 CHECK_EQ(IsSubOverflow<int64_t>(ii, jj), res1); |
| 1278 CHECK_EQ(IsSubOverflow<int64_t>(ii, jj), res2); |
| 1279 break; |
| 1280 default: |
| 1281 UNREACHABLE(); |
| 1282 } |
| 1283 } |
| 1284 } |
| 1285 } |
| 1286 } |
| 1287 } |
| 1288 |
680 TEST(min_max_nan) { | 1289 TEST(min_max_nan) { |
681 CcTest::InitializeVM(); | 1290 CcTest::InitializeVM(); |
682 Isolate* isolate = CcTest::i_isolate(); | 1291 Isolate* isolate = CcTest::i_isolate(); |
683 HandleScope scope(isolate); | 1292 HandleScope scope(isolate); |
684 MacroAssembler assembler(isolate, nullptr, 0, | 1293 MacroAssembler assembler(isolate, nullptr, 0, |
685 v8::internal::CodeObjectRequired::kYes); | 1294 v8::internal::CodeObjectRequired::kYes); |
686 MacroAssembler* masm = &assembler; | 1295 MacroAssembler* masm = &assembler; |
687 | 1296 |
688 struct TestFloat { | 1297 struct TestFloat { |
689 double a; | 1298 double a; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0); | 1390 CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0); |
782 | 1391 |
783 CHECK_EQ(0, memcmp(&test.c, &outputsdmin[i], sizeof(test.c))); | 1392 CHECK_EQ(0, memcmp(&test.c, &outputsdmin[i], sizeof(test.c))); |
784 CHECK_EQ(0, memcmp(&test.d, &outputsdmax[i], sizeof(test.d))); | 1393 CHECK_EQ(0, memcmp(&test.d, &outputsdmax[i], sizeof(test.d))); |
785 CHECK_EQ(0, memcmp(&test.g, &outputsfmin[i], sizeof(test.g))); | 1394 CHECK_EQ(0, memcmp(&test.g, &outputsfmin[i], sizeof(test.g))); |
786 CHECK_EQ(0, memcmp(&test.h, &outputsfmax[i], sizeof(test.h))); | 1395 CHECK_EQ(0, memcmp(&test.h, &outputsfmax[i], sizeof(test.h))); |
787 } | 1396 } |
788 } | 1397 } |
789 | 1398 |
790 #undef __ | 1399 #undef __ |
OLD | NEW |