diff options
author | Michaël Zasso <targos@protonmail.com> | 2016-12-23 16:30:57 +0100 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2017-01-26 22:46:17 +0100 |
commit | 2739185b790e040c3b044c577327f5d44bffad4a (patch) | |
tree | 29a466999212f4c85958379d9d400eec8a185ba5 /deps/v8/test/cctest/test-assembler-arm.cc | |
parent | a67a04d7654faaa04c8da00e42981ebc9fd0911c (diff) | |
download | android-node-v8-2739185b790e040c3b044c577327f5d44bffad4a.tar.gz android-node-v8-2739185b790e040c3b044c577327f5d44bffad4a.tar.bz2 android-node-v8-2739185b790e040c3b044c577327f5d44bffad4a.zip |
deps: update V8 to 5.5.372.40
PR-URL: https://github.com/nodejs/node/pull/9618
Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/test/cctest/test-assembler-arm.cc')
-rw-r--r-- | deps/v8/test/cctest/test-assembler-arm.cc | 572 |
1 files changed, 504 insertions, 68 deletions
diff --git a/deps/v8/test/cctest/test-assembler-arm.cc b/deps/v8/test/cctest/test-assembler-arm.cc index 93a19c1a14..de024f8869 100644 --- a/deps/v8/test/cctest/test-assembler-arm.cc +++ b/deps/v8/test/cctest/test-assembler-arm.cc @@ -30,11 +30,11 @@ #include "src/v8.h" #include "test/cctest/cctest.h" -#include "src/arm/assembler-arm-inl.h" #include "src/arm/simulator-arm.h" #include "src/base/utils/random-number-generator.h" #include "src/disassembler.h" #include "src/factory.h" +#include "src/macro-assembler.h" #include "src/ostreams.h" using namespace v8::base; @@ -244,9 +244,8 @@ TEST(4) { Assembler assm(isolate, NULL, 0); Label L, C; - - if (CpuFeatures::IsSupported(VFP3)) { - CpuFeatureScope scope(&assm, VFP3); + if (CpuFeatures::IsSupported(VFPv3)) { + CpuFeatureScope scope(&assm, VFPv3); __ mov(ip, Operand(sp)); __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); @@ -267,12 +266,12 @@ TEST(4) { // Load t.x and t.y, switch values, and store back to the struct. __ vldr(s0, r4, offsetof(T, x)); - __ vldr(s31, r4, offsetof(T, y)); - __ vmov(s16, s0); - __ vmov(s0, s31); - __ vmov(s31, s16); + __ vldr(s1, r4, offsetof(T, y)); + __ vmov(s2, s0); + __ vmov(s0, s1); + __ vmov(s1, s2); __ vstr(s0, r4, offsetof(T, x)); - __ vstr(s31, r4, offsetof(T, y)); + __ vstr(s1, r4, offsetof(T, y)); // Move a literal into a register that can be encoded in the instruction. __ vmov(d4, 1.0); @@ -285,13 +284,13 @@ TEST(4) { // Convert from floating point to integer. __ vmov(d4, 2.0); - __ vcvt_s32_f64(s31, d4); - __ vstr(s31, r4, offsetof(T, i)); + __ vcvt_s32_f64(s1, d4); + __ vstr(s1, r4, offsetof(T, i)); // Convert from integer to floating point. __ mov(lr, Operand(42)); - __ vmov(s31, lr); - __ vcvt_f64_s32(d4, s31); + __ vmov(s1, lr); + __ vcvt_f64_s32(d4, s1); __ vstr(d4, r4, offsetof(T, f)); // Convert from fixed point to floating point. @@ -450,62 +449,57 @@ static void TestRoundingMode(VCVTTypes types, Assembler assm(isolate, NULL, 0); - if (CpuFeatures::IsSupported(VFP3)) { - CpuFeatureScope scope(&assm, VFP3); - - Label wrong_exception; - - __ vmrs(r1); - // Set custom FPSCR. - __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask)); - __ orr(r2, r2, Operand(mode)); - __ vmsr(r2); - - // Load value, convert, and move back result to r0 if everything went well. - __ vmov(d1, value); - switch (types) { - case s32_f64: - __ vcvt_s32_f64(s0, d1, kFPSCRRounding); - break; - - case u32_f64: - __ vcvt_u32_f64(s0, d1, kFPSCRRounding); - break; - - default: - UNREACHABLE(); - break; - } - // Check for vfp exceptions - __ vmrs(r2); - __ tst(r2, Operand(kVFPExceptionMask)); - // Check that we behaved as expected. - __ b(&wrong_exception, - expected_exception ? eq : ne); - // There was no exception. Retrieve the result and return. - __ vmov(r0, s0); - __ mov(pc, Operand(lr)); + Label wrong_exception; - // The exception behaviour is not what we expected. - // Load a special value and return. - __ bind(&wrong_exception); - __ mov(r0, Operand(11223344)); - __ mov(pc, Operand(lr)); + __ vmrs(r1); + // Set custom FPSCR. + __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask)); + __ orr(r2, r2, Operand(mode)); + __ vmsr(r2); + + // Load value, convert, and move back result to r0 if everything went well. + __ vmov(d1, value); + switch (types) { + case s32_f64: + __ vcvt_s32_f64(s0, d1, kFPSCRRounding); + break; + + case u32_f64: + __ vcvt_u32_f64(s0, d1, kFPSCRRounding); + break; + + default: + UNREACHABLE(); + break; + } + // Check for vfp exceptions + __ vmrs(r2); + __ tst(r2, Operand(kVFPExceptionMask)); + // Check that we behaved as expected. + __ b(&wrong_exception, expected_exception ? eq : ne); + // There was no exception. Retrieve the result and return. + __ vmov(r0, s0); + __ mov(pc, Operand(lr)); - CodeDesc desc; - assm.GetCode(&desc); - Handle<Code> code = isolate->factory()->NewCode( - desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + // The exception behaviour is not what we expected. + // Load a special value and return. + __ bind(&wrong_exception); + __ mov(r0, Operand(11223344)); + __ mov(pc, Operand(lr)); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); #ifdef DEBUG - OFStream os(stdout); - code->Print(os); + OFStream os(stdout); + code->Print(os); #endif - F1 f = FUNCTION_CAST<F1>(code->entry()); - int res = - reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); - ::printf("res = %d\n", res); - CHECK_EQ(expected, res); - } + F1 f = FUNCTION_CAST<F1>(code->entry()); + int res = + reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); + ::printf("res = %d\n", res); + CHECK_EQ(expected, res); } @@ -1051,9 +1045,8 @@ TEST(13) { Assembler assm(isolate, NULL, 0); Label L, C; - - if (CpuFeatures::IsSupported(VFP3)) { - CpuFeatureScope scope(&assm, VFP3); + if (CpuFeatures::IsSupported(VFPv3)) { + CpuFeatureScope scope(&assm, VFPv3); __ stm(db_w, sp, r4.bit() | lr.bit()); @@ -2381,6 +2374,400 @@ TEST(ARMv8_vsel) { } } +TEST(ARMv8_vminmax_f64) { + // Test the vminnm and vmaxnm floating point instructions. + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + Assembler assm(isolate, NULL, 0); + + struct Inputs { + double left_; + double right_; + }; + + struct Results { + double vminnm_; + double vmaxnm_; + }; + + if (CpuFeatures::IsSupported(ARMv8)) { + CpuFeatureScope scope(&assm, ARMv8); + + // Create a helper function: + // void TestVminmax(const Inputs* inputs, + // Results* results); + __ vldr(d1, r0, offsetof(Inputs, left_)); + __ vldr(d2, r0, offsetof(Inputs, right_)); + + __ vminnm(d0, d1, d2); + __ vstr(d0, r1, offsetof(Results, vminnm_)); + __ vmaxnm(d0, d1, d2); + __ vstr(d0, r1, offsetof(Results, vmaxnm_)); + + __ bx(lr); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); +#ifdef DEBUG + OFStream os(stdout); + code->Print(os); +#endif + F4 f = FUNCTION_CAST<F4>(code->entry()); + Object* dummy = nullptr; + USE(dummy); + +#define CHECK_VMINMAX(left, right, vminnm, vmaxnm) \ + do { \ + Inputs inputs = {left, right}; \ + Results results; \ + dummy = CALL_GENERATED_CODE(isolate, f, &inputs, &results, 0, 0, 0); \ + /* Use a bit_cast to correctly identify -0.0 and NaNs. */ \ + CHECK_EQ(bit_cast<uint64_t>(vminnm), bit_cast<uint64_t>(results.vminnm_)); \ + CHECK_EQ(bit_cast<uint64_t>(vmaxnm), bit_cast<uint64_t>(results.vmaxnm_)); \ + } while (0); + + double nan_a = bit_cast<double>(UINT64_C(0x7ff8000000000001)); + double nan_b = bit_cast<double>(UINT64_C(0x7ff8000000000002)); + + CHECK_VMINMAX(1.0, -1.0, -1.0, 1.0); + CHECK_VMINMAX(-1.0, 1.0, -1.0, 1.0); + CHECK_VMINMAX(0.0, -1.0, -1.0, 0.0); + CHECK_VMINMAX(-1.0, 0.0, -1.0, 0.0); + CHECK_VMINMAX(-0.0, -1.0, -1.0, -0.0); + CHECK_VMINMAX(-1.0, -0.0, -1.0, -0.0); + CHECK_VMINMAX(0.0, 1.0, 0.0, 1.0); + CHECK_VMINMAX(1.0, 0.0, 0.0, 1.0); + + CHECK_VMINMAX(0.0, 0.0, 0.0, 0.0); + CHECK_VMINMAX(-0.0, -0.0, -0.0, -0.0); + CHECK_VMINMAX(-0.0, 0.0, -0.0, 0.0); + CHECK_VMINMAX(0.0, -0.0, -0.0, 0.0); + + CHECK_VMINMAX(0.0, nan_a, 0.0, 0.0); + CHECK_VMINMAX(nan_a, 0.0, 0.0, 0.0); + CHECK_VMINMAX(nan_a, nan_b, nan_a, nan_a); + CHECK_VMINMAX(nan_b, nan_a, nan_b, nan_b); + +#undef CHECK_VMINMAX + } +} + +TEST(ARMv8_vminmax_f32) { + // Test the vminnm and vmaxnm floating point instructions. + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + Assembler assm(isolate, NULL, 0); + + struct Inputs { + float left_; + float right_; + }; + + struct Results { + float vminnm_; + float vmaxnm_; + }; + + if (CpuFeatures::IsSupported(ARMv8)) { + CpuFeatureScope scope(&assm, ARMv8); + + // Create a helper function: + // void TestVminmax(const Inputs* inputs, + // Results* results); + __ vldr(s1, r0, offsetof(Inputs, left_)); + __ vldr(s2, r0, offsetof(Inputs, right_)); + + __ vminnm(s0, s1, s2); + __ vstr(s0, r1, offsetof(Results, vminnm_)); + __ vmaxnm(s0, s1, s2); + __ vstr(s0, r1, offsetof(Results, vmaxnm_)); + + __ bx(lr); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); +#ifdef DEBUG + OFStream os(stdout); + code->Print(os); +#endif + F4 f = FUNCTION_CAST<F4>(code->entry()); + Object* dummy = nullptr; + USE(dummy); + +#define CHECK_VMINMAX(left, right, vminnm, vmaxnm) \ + do { \ + Inputs inputs = {left, right}; \ + Results results; \ + dummy = CALL_GENERATED_CODE(isolate, f, &inputs, &results, 0, 0, 0); \ + /* Use a bit_cast to correctly identify -0.0 and NaNs. */ \ + CHECK_EQ(bit_cast<uint32_t>(vminnm), bit_cast<uint32_t>(results.vminnm_)); \ + CHECK_EQ(bit_cast<uint32_t>(vmaxnm), bit_cast<uint32_t>(results.vmaxnm_)); \ + } while (0); + + float nan_a = bit_cast<float>(UINT32_C(0x7fc00001)); + float nan_b = bit_cast<float>(UINT32_C(0x7fc00002)); + + CHECK_VMINMAX(1.0f, -1.0f, -1.0f, 1.0f); + CHECK_VMINMAX(-1.0f, 1.0f, -1.0f, 1.0f); + CHECK_VMINMAX(0.0f, -1.0f, -1.0f, 0.0f); + CHECK_VMINMAX(-1.0f, 0.0f, -1.0f, 0.0f); + CHECK_VMINMAX(-0.0f, -1.0f, -1.0f, -0.0f); + CHECK_VMINMAX(-1.0f, -0.0f, -1.0f, -0.0f); + CHECK_VMINMAX(0.0f, 1.0f, 0.0f, 1.0f); + CHECK_VMINMAX(1.0f, 0.0f, 0.0f, 1.0f); + + CHECK_VMINMAX(0.0f, 0.0f, 0.0f, 0.0f); + CHECK_VMINMAX(-0.0f, -0.0f, -0.0f, -0.0f); + CHECK_VMINMAX(-0.0f, 0.0f, -0.0f, 0.0f); + CHECK_VMINMAX(0.0f, -0.0f, -0.0f, 0.0f); + + CHECK_VMINMAX(0.0f, nan_a, 0.0f, 0.0f); + CHECK_VMINMAX(nan_a, 0.0f, 0.0f, 0.0f); + CHECK_VMINMAX(nan_a, nan_b, nan_a, nan_a); + CHECK_VMINMAX(nan_b, nan_a, nan_b, nan_b); + +#undef CHECK_VMINMAX + } +} + +template <typename T, typename Inputs, typename Results> +static F4 GenerateMacroFloatMinMax(MacroAssembler& assm) { + T a = T::from_code(0); // d0/s0 + T b = T::from_code(1); // d1/s1 + T c = T::from_code(2); // d2/s2 + + // Create a helper function: + // void TestFloatMinMax(const Inputs* inputs, + // Results* results); + Label ool_min_abc, ool_min_aab, ool_min_aba; + Label ool_max_abc, ool_max_aab, ool_max_aba; + + Label done_min_abc, done_min_aab, done_min_aba; + Label done_max_abc, done_max_aab, done_max_aba; + + // a = min(b, c); + __ vldr(b, r0, offsetof(Inputs, left_)); + __ vldr(c, r0, offsetof(Inputs, right_)); + __ FloatMin(a, b, c, &ool_min_abc); + __ bind(&done_min_abc); + __ vstr(a, r1, offsetof(Results, min_abc_)); + + // a = min(a, b); + __ vldr(a, r0, offsetof(Inputs, left_)); + __ vldr(b, r0, offsetof(Inputs, right_)); + __ FloatMin(a, a, b, &ool_min_aab); + __ bind(&done_min_aab); + __ vstr(a, r1, offsetof(Results, min_aab_)); + + // a = min(b, a); + __ vldr(b, r0, offsetof(Inputs, left_)); + __ vldr(a, r0, offsetof(Inputs, right_)); + __ FloatMin(a, b, a, &ool_min_aba); + __ bind(&done_min_aba); + __ vstr(a, r1, offsetof(Results, min_aba_)); + + // a = max(b, c); + __ vldr(b, r0, offsetof(Inputs, left_)); + __ vldr(c, r0, offsetof(Inputs, right_)); + __ FloatMax(a, b, c, &ool_max_abc); + __ bind(&done_max_abc); + __ vstr(a, r1, offsetof(Results, max_abc_)); + + // a = max(a, b); + __ vldr(a, r0, offsetof(Inputs, left_)); + __ vldr(b, r0, offsetof(Inputs, right_)); + __ FloatMax(a, a, b, &ool_max_aab); + __ bind(&done_max_aab); + __ vstr(a, r1, offsetof(Results, max_aab_)); + + // a = max(b, a); + __ vldr(b, r0, offsetof(Inputs, left_)); + __ vldr(a, r0, offsetof(Inputs, right_)); + __ FloatMax(a, b, a, &ool_max_aba); + __ bind(&done_max_aba); + __ vstr(a, r1, offsetof(Results, max_aba_)); + + __ bx(lr); + + // Generate out-of-line cases. + __ bind(&ool_min_abc); + __ FloatMinOutOfLine(a, b, c); + __ b(&done_min_abc); + + __ bind(&ool_min_aab); + __ FloatMinOutOfLine(a, a, b); + __ b(&done_min_aab); + + __ bind(&ool_min_aba); + __ FloatMinOutOfLine(a, b, a); + __ b(&done_min_aba); + + __ bind(&ool_max_abc); + __ FloatMaxOutOfLine(a, b, c); + __ b(&done_max_abc); + + __ bind(&ool_max_aab); + __ FloatMaxOutOfLine(a, a, b); + __ b(&done_max_aab); + + __ bind(&ool_max_aba); + __ FloatMaxOutOfLine(a, b, a); + __ b(&done_max_aba); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = assm.isolate()->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); +#ifdef DEBUG + OFStream os(stdout); + code->Print(os); +#endif + return FUNCTION_CAST<F4>(code->entry()); +} + +TEST(macro_float_minmax_f64) { + // Test the FloatMin and FloatMax macros. + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0, CodeObjectRequired::kYes); + + struct Inputs { + double left_; + double right_; + }; + + struct Results { + // Check all register aliasing possibilities in order to exercise all + // code-paths in the macro assembler. + double min_abc_; + double min_aab_; + double min_aba_; + double max_abc_; + double max_aab_; + double max_aba_; + }; + + F4 f = GenerateMacroFloatMinMax<DwVfpRegister, Inputs, Results>(assm); + + Object* dummy = nullptr; + USE(dummy); + +#define CHECK_MINMAX(left, right, min, max) \ + do { \ + Inputs inputs = {left, right}; \ + Results results; \ + dummy = CALL_GENERATED_CODE(isolate, f, &inputs, &results, 0, 0, 0); \ + /* Use a bit_cast to correctly identify -0.0 and NaNs. */ \ + CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_abc_)); \ + CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_aab_)); \ + CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_aba_)); \ + CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_abc_)); \ + CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_aab_)); \ + CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_aba_)); \ + } while (0) + + double nan_a = bit_cast<double>(UINT64_C(0x7ff8000000000001)); + double nan_b = bit_cast<double>(UINT64_C(0x7ff8000000000002)); + + CHECK_MINMAX(1.0, -1.0, -1.0, 1.0); + CHECK_MINMAX(-1.0, 1.0, -1.0, 1.0); + CHECK_MINMAX(0.0, -1.0, -1.0, 0.0); + CHECK_MINMAX(-1.0, 0.0, -1.0, 0.0); + CHECK_MINMAX(-0.0, -1.0, -1.0, -0.0); + CHECK_MINMAX(-1.0, -0.0, -1.0, -0.0); + CHECK_MINMAX(0.0, 1.0, 0.0, 1.0); + CHECK_MINMAX(1.0, 0.0, 0.0, 1.0); + + CHECK_MINMAX(0.0, 0.0, 0.0, 0.0); + CHECK_MINMAX(-0.0, -0.0, -0.0, -0.0); + CHECK_MINMAX(-0.0, 0.0, -0.0, 0.0); + CHECK_MINMAX(0.0, -0.0, -0.0, 0.0); + + CHECK_MINMAX(0.0, nan_a, nan_a, nan_a); + CHECK_MINMAX(nan_a, 0.0, nan_a, nan_a); + CHECK_MINMAX(nan_a, nan_b, nan_a, nan_a); + CHECK_MINMAX(nan_b, nan_a, nan_b, nan_b); + +#undef CHECK_MINMAX +} + +TEST(macro_float_minmax_f32) { + // Test the FloatMin and FloatMax macros. + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0, CodeObjectRequired::kYes); + + struct Inputs { + float left_; + float right_; + }; + + struct Results { + // Check all register aliasing possibilities in order to exercise all + // code-paths in the macro assembler. + float min_abc_; + float min_aab_; + float min_aba_; + float max_abc_; + float max_aab_; + float max_aba_; + }; + + F4 f = GenerateMacroFloatMinMax<SwVfpRegister, Inputs, Results>(assm); + Object* dummy = nullptr; + USE(dummy); + +#define CHECK_MINMAX(left, right, min, max) \ + do { \ + Inputs inputs = {left, right}; \ + Results results; \ + dummy = CALL_GENERATED_CODE(isolate, f, &inputs, &results, 0, 0, 0); \ + /* Use a bit_cast to correctly identify -0.0 and NaNs. */ \ + CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_abc_)); \ + CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_aab_)); \ + CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_aba_)); \ + CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_abc_)); \ + CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_aab_)); \ + CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_aba_)); \ + } while (0) + + float nan_a = bit_cast<float>(UINT32_C(0x7fc00001)); + float nan_b = bit_cast<float>(UINT32_C(0x7fc00002)); + + CHECK_MINMAX(1.0f, -1.0f, -1.0f, 1.0f); + CHECK_MINMAX(-1.0f, 1.0f, -1.0f, 1.0f); + CHECK_MINMAX(0.0f, -1.0f, -1.0f, 0.0f); + CHECK_MINMAX(-1.0f, 0.0f, -1.0f, 0.0f); + CHECK_MINMAX(-0.0f, -1.0f, -1.0f, -0.0f); + CHECK_MINMAX(-1.0f, -0.0f, -1.0f, -0.0f); + CHECK_MINMAX(0.0f, 1.0f, 0.0f, 1.0f); + CHECK_MINMAX(1.0f, 0.0f, 0.0f, 1.0f); + + CHECK_MINMAX(0.0f, 0.0f, 0.0f, 0.0f); + CHECK_MINMAX(-0.0f, -0.0f, -0.0f, -0.0f); + CHECK_MINMAX(-0.0f, 0.0f, -0.0f, 0.0f); + CHECK_MINMAX(0.0f, -0.0f, -0.0f, 0.0f); + + CHECK_MINMAX(0.0f, nan_a, nan_a, nan_a); + CHECK_MINMAX(nan_a, 0.0f, nan_a, nan_a); + CHECK_MINMAX(nan_a, nan_b, nan_a, nan_a); + CHECK_MINMAX(nan_b, nan_a, nan_b, nan_b); + +#undef CHECK_MINMAX +} + TEST(unaligned_loads) { // All supported ARM targets allow unaligned accesses. CcTest::InitializeVM(); @@ -2495,6 +2882,55 @@ TEST(unaligned_stores) { } } +TEST(vswp) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + Assembler assm(isolate, NULL, 0); + + typedef struct { + double result0; + double result1; + double result2; + double result3; + } T; + T t; + + __ vmov(d0, 1.0); + __ vmov(d1, -1.0); + __ vswp(d0, d1); + __ vstr(d0, r0, offsetof(T, result0)); + __ vstr(d1, r0, offsetof(T, result1)); + + if (CpuFeatures::IsSupported(VFP32DREGS)) { + __ vmov(d30, 1.0); + __ vmov(d31, -1.0); + __ vswp(d30, d31); + __ vstr(d30, r0, offsetof(T, result2)); + __ vstr(d31, r0, offsetof(T, result3)); + } + + __ bx(lr); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); +#ifdef DEBUG + OFStream os(stdout); + code->Print(os); +#endif + F3 f = FUNCTION_CAST<F3>(code->entry()); + Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); + USE(dummy); + CHECK_EQ(-1.0, t.result0); + CHECK_EQ(1.0, t.result1); + if (CpuFeatures::IsSupported(VFP32DREGS)) { + CHECK_EQ(-1.0, t.result2); + CHECK_EQ(1.0, t.result3); + } +} + TEST(regress4292_b) { CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); |