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 12 matching lines...) Expand all Loading... |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include <iostream> // NOLINT(readability/streams) | 28 #include <iostream> // NOLINT(readability/streams) |
29 | 29 |
30 #include "src/v8.h" | 30 #include "src/v8.h" |
31 #include "test/cctest/cctest.h" | 31 #include "test/cctest/cctest.h" |
32 | 32 |
33 #include "src/arm/assembler-arm-inl.h" | |
34 #include "src/arm/simulator-arm.h" | 33 #include "src/arm/simulator-arm.h" |
35 #include "src/base/utils/random-number-generator.h" | 34 #include "src/base/utils/random-number-generator.h" |
36 #include "src/disassembler.h" | 35 #include "src/disassembler.h" |
37 #include "src/factory.h" | 36 #include "src/factory.h" |
| 37 #include "src/macro-assembler.h" |
38 #include "src/ostreams.h" | 38 #include "src/ostreams.h" |
39 | 39 |
40 using namespace v8::base; | 40 using namespace v8::base; |
41 using namespace v8::internal; | 41 using namespace v8::internal; |
42 | 42 |
43 | 43 |
44 // Define these function prototypes to match JSEntryFunction in execution.cc. | 44 // Define these function prototypes to match JSEntryFunction in execution.cc. |
45 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); | 45 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); |
46 typedef Object* (*F2)(int x, int y, int p2, int p3, int p4); | 46 typedef Object* (*F2)(int x, int y, int p2, int p3, int p4); |
47 typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4); | 47 typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4); |
(...skipping 2327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2375 CHECK_VSEL(1, 1, 0, 0, kResultPass, kResultFail, kResultFail, kResultFail); | 2375 CHECK_VSEL(1, 1, 0, 0, kResultPass, kResultFail, kResultFail, kResultFail); |
2376 CHECK_VSEL(1, 1, 0, 1, kResultPass, kResultPass, kResultFail, kResultPass); | 2376 CHECK_VSEL(1, 1, 0, 1, kResultPass, kResultPass, kResultFail, kResultPass); |
2377 CHECK_VSEL(1, 1, 1, 0, kResultPass, kResultFail, kResultFail, kResultFail); | 2377 CHECK_VSEL(1, 1, 1, 0, kResultPass, kResultFail, kResultFail, kResultFail); |
2378 CHECK_VSEL(1, 1, 1, 1, kResultPass, kResultPass, kResultFail, kResultPass); | 2378 CHECK_VSEL(1, 1, 1, 1, kResultPass, kResultPass, kResultFail, kResultPass); |
2379 | 2379 |
2380 #undef CHECK_VSEL | 2380 #undef CHECK_VSEL |
2381 } | 2381 } |
2382 } | 2382 } |
2383 | 2383 |
2384 TEST(ARMv8_vminmax_f64) { | 2384 TEST(ARMv8_vminmax_f64) { |
2385 // Test the vsel floating point instructions. | 2385 // Test the vminnm and vmaxnm floating point instructions. |
2386 CcTest::InitializeVM(); | 2386 CcTest::InitializeVM(); |
2387 Isolate* isolate = CcTest::i_isolate(); | 2387 Isolate* isolate = CcTest::i_isolate(); |
2388 HandleScope scope(isolate); | 2388 HandleScope scope(isolate); |
2389 | 2389 |
2390 Assembler assm(isolate, NULL, 0); | 2390 Assembler assm(isolate, NULL, 0); |
2391 | 2391 |
2392 struct Inputs { | 2392 struct Inputs { |
2393 double left_; | 2393 double left_; |
2394 double right_; | 2394 double right_; |
2395 }; | 2395 }; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2457 CHECK_VMINMAX(0.0, nan_a, 0.0, 0.0); | 2457 CHECK_VMINMAX(0.0, nan_a, 0.0, 0.0); |
2458 CHECK_VMINMAX(nan_a, 0.0, 0.0, 0.0); | 2458 CHECK_VMINMAX(nan_a, 0.0, 0.0, 0.0); |
2459 CHECK_VMINMAX(nan_a, nan_b, nan_a, nan_a); | 2459 CHECK_VMINMAX(nan_a, nan_b, nan_a, nan_a); |
2460 CHECK_VMINMAX(nan_b, nan_a, nan_b, nan_b); | 2460 CHECK_VMINMAX(nan_b, nan_a, nan_b, nan_b); |
2461 | 2461 |
2462 #undef CHECK_VMINMAX | 2462 #undef CHECK_VMINMAX |
2463 } | 2463 } |
2464 } | 2464 } |
2465 | 2465 |
2466 TEST(ARMv8_vminmax_f32) { | 2466 TEST(ARMv8_vminmax_f32) { |
2467 // Test the vsel floating point instructions. | 2467 // Test the vminnm and vmaxnm floating point instructions. |
2468 CcTest::InitializeVM(); | 2468 CcTest::InitializeVM(); |
2469 Isolate* isolate = CcTest::i_isolate(); | 2469 Isolate* isolate = CcTest::i_isolate(); |
2470 HandleScope scope(isolate); | 2470 HandleScope scope(isolate); |
2471 | 2471 |
2472 Assembler assm(isolate, NULL, 0); | 2472 Assembler assm(isolate, NULL, 0); |
2473 | 2473 |
2474 struct Inputs { | 2474 struct Inputs { |
2475 float left_; | 2475 float left_; |
2476 float right_; | 2476 float right_; |
2477 }; | 2477 }; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2538 | 2538 |
2539 CHECK_VMINMAX(0.0f, nan_a, 0.0f, 0.0f); | 2539 CHECK_VMINMAX(0.0f, nan_a, 0.0f, 0.0f); |
2540 CHECK_VMINMAX(nan_a, 0.0f, 0.0f, 0.0f); | 2540 CHECK_VMINMAX(nan_a, 0.0f, 0.0f, 0.0f); |
2541 CHECK_VMINMAX(nan_a, nan_b, nan_a, nan_a); | 2541 CHECK_VMINMAX(nan_a, nan_b, nan_a, nan_a); |
2542 CHECK_VMINMAX(nan_b, nan_a, nan_b, nan_b); | 2542 CHECK_VMINMAX(nan_b, nan_a, nan_b, nan_b); |
2543 | 2543 |
2544 #undef CHECK_VMINMAX | 2544 #undef CHECK_VMINMAX |
2545 } | 2545 } |
2546 } | 2546 } |
2547 | 2547 |
| 2548 template <typename T, typename Inputs, typename Results> |
| 2549 static F4 GenerateMacroFloatMinMax(MacroAssembler& assm) { |
| 2550 T a = T::from_code(0); // d0/s0 |
| 2551 T b = T::from_code(1); // d1/s1 |
| 2552 T c = T::from_code(2); // d2/s2 |
| 2553 |
| 2554 // Create a helper function: |
| 2555 // void TestFloatMinMax(const Inputs* inputs, |
| 2556 // Results* results); |
| 2557 Label ool_min_abc, ool_min_aab, ool_min_aba; |
| 2558 Label ool_max_abc, ool_max_aab, ool_max_aba; |
| 2559 |
| 2560 Label done_min_abc, done_min_aab, done_min_aba; |
| 2561 Label done_max_abc, done_max_aab, done_max_aba; |
| 2562 |
| 2563 // a = min(b, c); |
| 2564 __ vldr(b, r0, offsetof(Inputs, left_)); |
| 2565 __ vldr(c, r0, offsetof(Inputs, right_)); |
| 2566 __ FloatMin(a, b, c, &ool_min_abc); |
| 2567 __ bind(&done_min_abc); |
| 2568 __ vstr(a, r1, offsetof(Results, min_abc_)); |
| 2569 |
| 2570 // a = min(a, b); |
| 2571 __ vldr(a, r0, offsetof(Inputs, left_)); |
| 2572 __ vldr(b, r0, offsetof(Inputs, right_)); |
| 2573 __ FloatMin(a, a, b, &ool_min_aab); |
| 2574 __ bind(&done_min_aab); |
| 2575 __ vstr(a, r1, offsetof(Results, min_aab_)); |
| 2576 |
| 2577 // a = min(b, a); |
| 2578 __ vldr(b, r0, offsetof(Inputs, left_)); |
| 2579 __ vldr(a, r0, offsetof(Inputs, right_)); |
| 2580 __ FloatMin(a, b, a, &ool_min_aba); |
| 2581 __ bind(&done_min_aba); |
| 2582 __ vstr(a, r1, offsetof(Results, min_aba_)); |
| 2583 |
| 2584 // a = max(b, c); |
| 2585 __ vldr(b, r0, offsetof(Inputs, left_)); |
| 2586 __ vldr(c, r0, offsetof(Inputs, right_)); |
| 2587 __ FloatMax(a, b, c, &ool_max_abc); |
| 2588 __ bind(&done_max_abc); |
| 2589 __ vstr(a, r1, offsetof(Results, max_abc_)); |
| 2590 |
| 2591 // a = max(a, b); |
| 2592 __ vldr(a, r0, offsetof(Inputs, left_)); |
| 2593 __ vldr(b, r0, offsetof(Inputs, right_)); |
| 2594 __ FloatMax(a, a, b, &ool_max_aab); |
| 2595 __ bind(&done_max_aab); |
| 2596 __ vstr(a, r1, offsetof(Results, max_aab_)); |
| 2597 |
| 2598 // a = max(b, a); |
| 2599 __ vldr(b, r0, offsetof(Inputs, left_)); |
| 2600 __ vldr(a, r0, offsetof(Inputs, right_)); |
| 2601 __ FloatMax(a, b, a, &ool_max_aba); |
| 2602 __ bind(&done_max_aba); |
| 2603 __ vstr(a, r1, offsetof(Results, max_aba_)); |
| 2604 |
| 2605 __ bx(lr); |
| 2606 |
| 2607 // Generate out-of-line cases. |
| 2608 __ bind(&ool_min_abc); |
| 2609 __ FloatMinOutOfLine(a, b, c); |
| 2610 __ b(&done_min_abc); |
| 2611 |
| 2612 __ bind(&ool_min_aab); |
| 2613 __ FloatMinOutOfLine(a, a, b); |
| 2614 __ b(&done_min_aab); |
| 2615 |
| 2616 __ bind(&ool_min_aba); |
| 2617 __ FloatMinOutOfLine(a, b, a); |
| 2618 __ b(&done_min_aba); |
| 2619 |
| 2620 __ bind(&ool_max_abc); |
| 2621 __ FloatMaxOutOfLine(a, b, c); |
| 2622 __ b(&done_max_abc); |
| 2623 |
| 2624 __ bind(&ool_max_aab); |
| 2625 __ FloatMaxOutOfLine(a, a, b); |
| 2626 __ b(&done_max_aab); |
| 2627 |
| 2628 __ bind(&ool_max_aba); |
| 2629 __ FloatMaxOutOfLine(a, b, a); |
| 2630 __ b(&done_max_aba); |
| 2631 |
| 2632 CodeDesc desc; |
| 2633 assm.GetCode(&desc); |
| 2634 Handle<Code> code = assm.isolate()->factory()->NewCode( |
| 2635 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 2636 #ifdef DEBUG |
| 2637 OFStream os(stdout); |
| 2638 code->Print(os); |
| 2639 #endif |
| 2640 return FUNCTION_CAST<F4>(code->entry()); |
| 2641 } |
| 2642 |
| 2643 TEST(macro_float_minmax_f64) { |
| 2644 // Test the FloatMin and FloatMax macros. |
| 2645 CcTest::InitializeVM(); |
| 2646 Isolate* isolate = CcTest::i_isolate(); |
| 2647 HandleScope scope(isolate); |
| 2648 |
| 2649 MacroAssembler assm(isolate, NULL, 0, CodeObjectRequired::kYes); |
| 2650 |
| 2651 struct Inputs { |
| 2652 double left_; |
| 2653 double right_; |
| 2654 }; |
| 2655 |
| 2656 struct Results { |
| 2657 // Check all register aliasing possibilities in order to exercise all |
| 2658 // code-paths in the macro assembler. |
| 2659 double min_abc_; |
| 2660 double min_aab_; |
| 2661 double min_aba_; |
| 2662 double max_abc_; |
| 2663 double max_aab_; |
| 2664 double max_aba_; |
| 2665 }; |
| 2666 |
| 2667 F4 f = GenerateMacroFloatMinMax<DwVfpRegister, Inputs, Results>(assm); |
| 2668 |
| 2669 Object* dummy = nullptr; |
| 2670 USE(dummy); |
| 2671 |
| 2672 #define CHECK_MINMAX(left, right, min, max) \ |
| 2673 do { \ |
| 2674 Inputs inputs = {left, right}; \ |
| 2675 Results results; \ |
| 2676 dummy = CALL_GENERATED_CODE(isolate, f, &inputs, &results, 0, 0, 0); \ |
| 2677 /* Use a bit_cast to correctly identify -0.0 and NaNs. */ \ |
| 2678 CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_abc_)); \ |
| 2679 CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_aab_)); \ |
| 2680 CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_aba_)); \ |
| 2681 CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_abc_)); \ |
| 2682 CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_aab_)); \ |
| 2683 CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_aba_)); \ |
| 2684 } while (0) |
| 2685 |
| 2686 double nan_a = bit_cast<double>(UINT64_C(0x7ff8000000000001)); |
| 2687 double nan_b = bit_cast<double>(UINT64_C(0x7ff8000000000002)); |
| 2688 |
| 2689 CHECK_MINMAX(1.0, -1.0, -1.0, 1.0); |
| 2690 CHECK_MINMAX(-1.0, 1.0, -1.0, 1.0); |
| 2691 CHECK_MINMAX(0.0, -1.0, -1.0, 0.0); |
| 2692 CHECK_MINMAX(-1.0, 0.0, -1.0, 0.0); |
| 2693 CHECK_MINMAX(-0.0, -1.0, -1.0, -0.0); |
| 2694 CHECK_MINMAX(-1.0, -0.0, -1.0, -0.0); |
| 2695 CHECK_MINMAX(0.0, 1.0, 0.0, 1.0); |
| 2696 CHECK_MINMAX(1.0, 0.0, 0.0, 1.0); |
| 2697 |
| 2698 CHECK_MINMAX(0.0, 0.0, 0.0, 0.0); |
| 2699 CHECK_MINMAX(-0.0, -0.0, -0.0, -0.0); |
| 2700 CHECK_MINMAX(-0.0, 0.0, -0.0, 0.0); |
| 2701 CHECK_MINMAX(0.0, -0.0, -0.0, 0.0); |
| 2702 |
| 2703 CHECK_MINMAX(0.0, nan_a, nan_a, nan_a); |
| 2704 CHECK_MINMAX(nan_a, 0.0, nan_a, nan_a); |
| 2705 CHECK_MINMAX(nan_a, nan_b, nan_a, nan_a); |
| 2706 CHECK_MINMAX(nan_b, nan_a, nan_b, nan_b); |
| 2707 |
| 2708 #undef CHECK_MINMAX |
| 2709 } |
| 2710 |
| 2711 TEST(macro_float_minmax_f32) { |
| 2712 // Test the FloatMin and FloatMax macros. |
| 2713 CcTest::InitializeVM(); |
| 2714 Isolate* isolate = CcTest::i_isolate(); |
| 2715 HandleScope scope(isolate); |
| 2716 |
| 2717 MacroAssembler assm(isolate, NULL, 0, CodeObjectRequired::kYes); |
| 2718 |
| 2719 struct Inputs { |
| 2720 float left_; |
| 2721 float right_; |
| 2722 }; |
| 2723 |
| 2724 struct Results { |
| 2725 // Check all register aliasing possibilities in order to exercise all |
| 2726 // code-paths in the macro assembler. |
| 2727 float min_abc_; |
| 2728 float min_aab_; |
| 2729 float min_aba_; |
| 2730 float max_abc_; |
| 2731 float max_aab_; |
| 2732 float max_aba_; |
| 2733 }; |
| 2734 |
| 2735 F4 f = GenerateMacroFloatMinMax<SwVfpRegister, Inputs, Results>(assm); |
| 2736 Object* dummy = nullptr; |
| 2737 USE(dummy); |
| 2738 |
| 2739 #define CHECK_MINMAX(left, right, min, max) \ |
| 2740 do { \ |
| 2741 Inputs inputs = {left, right}; \ |
| 2742 Results results; \ |
| 2743 dummy = CALL_GENERATED_CODE(isolate, f, &inputs, &results, 0, 0, 0); \ |
| 2744 /* Use a bit_cast to correctly identify -0.0 and NaNs. */ \ |
| 2745 CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_abc_)); \ |
| 2746 CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_aab_)); \ |
| 2747 CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_aba_)); \ |
| 2748 CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_abc_)); \ |
| 2749 CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_aab_)); \ |
| 2750 CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_aba_)); \ |
| 2751 } while (0) |
| 2752 |
| 2753 float nan_a = bit_cast<float>(UINT32_C(0x7fc00001)); |
| 2754 float nan_b = bit_cast<float>(UINT32_C(0x7fc00002)); |
| 2755 |
| 2756 CHECK_MINMAX(1.0f, -1.0f, -1.0f, 1.0f); |
| 2757 CHECK_MINMAX(-1.0f, 1.0f, -1.0f, 1.0f); |
| 2758 CHECK_MINMAX(0.0f, -1.0f, -1.0f, 0.0f); |
| 2759 CHECK_MINMAX(-1.0f, 0.0f, -1.0f, 0.0f); |
| 2760 CHECK_MINMAX(-0.0f, -1.0f, -1.0f, -0.0f); |
| 2761 CHECK_MINMAX(-1.0f, -0.0f, -1.0f, -0.0f); |
| 2762 CHECK_MINMAX(0.0f, 1.0f, 0.0f, 1.0f); |
| 2763 CHECK_MINMAX(1.0f, 0.0f, 0.0f, 1.0f); |
| 2764 |
| 2765 CHECK_MINMAX(0.0f, 0.0f, 0.0f, 0.0f); |
| 2766 CHECK_MINMAX(-0.0f, -0.0f, -0.0f, -0.0f); |
| 2767 CHECK_MINMAX(-0.0f, 0.0f, -0.0f, 0.0f); |
| 2768 CHECK_MINMAX(0.0f, -0.0f, -0.0f, 0.0f); |
| 2769 |
| 2770 CHECK_MINMAX(0.0f, nan_a, nan_a, nan_a); |
| 2771 CHECK_MINMAX(nan_a, 0.0f, nan_a, nan_a); |
| 2772 CHECK_MINMAX(nan_a, nan_b, nan_a, nan_a); |
| 2773 CHECK_MINMAX(nan_b, nan_a, nan_b, nan_b); |
| 2774 |
| 2775 #undef CHECK_MINMAX |
| 2776 } |
| 2777 |
2548 TEST(unaligned_loads) { | 2778 TEST(unaligned_loads) { |
2549 // All supported ARM targets allow unaligned accesses. | 2779 // All supported ARM targets allow unaligned accesses. |
2550 CcTest::InitializeVM(); | 2780 CcTest::InitializeVM(); |
2551 Isolate* isolate = CcTest::i_isolate(); | 2781 Isolate* isolate = CcTest::i_isolate(); |
2552 HandleScope scope(isolate); | 2782 HandleScope scope(isolate); |
2553 | 2783 |
2554 typedef struct { | 2784 typedef struct { |
2555 uint32_t ldrh; | 2785 uint32_t ldrh; |
2556 uint32_t ldrsh; | 2786 uint32_t ldrsh; |
2557 uint32_t ldr; | 2787 uint32_t ldr; |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2710 HandleScope scope(isolate); | 2940 HandleScope scope(isolate); |
2711 | 2941 |
2712 Assembler assm(isolate, NULL, 0); | 2942 Assembler assm(isolate, NULL, 0); |
2713 __ mov(r0, Operand(isolate->factory()->infinity_value())); | 2943 __ mov(r0, Operand(isolate->factory()->infinity_value())); |
2714 __ BlockConstPoolFor(1019); | 2944 __ BlockConstPoolFor(1019); |
2715 for (int i = 0; i < 1019; ++i) __ nop(); | 2945 for (int i = 0; i < 1019; ++i) __ nop(); |
2716 __ vldr(d0, MemOperand(r0, 0)); | 2946 __ vldr(d0, MemOperand(r0, 0)); |
2717 } | 2947 } |
2718 | 2948 |
2719 #undef __ | 2949 #undef __ |
OLD | NEW |