diff options
Diffstat (limited to 'deps/v8/test/cctest/test-assembler-arm.cc')
-rw-r--r-- | deps/v8/test/cctest/test-assembler-arm.cc | 303 |
1 files changed, 283 insertions, 20 deletions
diff --git a/deps/v8/test/cctest/test-assembler-arm.cc b/deps/v8/test/cctest/test-assembler-arm.cc index 3763f06493..93a19c1a14 100644 --- a/deps/v8/test/cctest/test-assembler-arm.cc +++ b/deps/v8/test/cctest/test-assembler-arm.cc @@ -412,29 +412,26 @@ TEST(6) { Assembler assm(isolate, NULL, 0); - if (CpuFeatures::IsSupported(ARMv7)) { - CpuFeatureScope scope(&assm, ARMv7); - __ usat(r1, 8, Operand(r0)); // Sat 0xFFFF to 0-255 = 0xFF. - __ usat(r2, 12, Operand(r0, ASR, 9)); // Sat (0xFFFF>>9) to 0-4095 = 0x7F. - __ usat(r3, 1, Operand(r0, LSL, 16)); // Sat (0xFFFF<<16) to 0-1 = 0x0. - __ add(r0, r1, Operand(r2)); - __ add(r0, r0, Operand(r3)); - __ mov(pc, Operand(lr)); + __ usat(r1, 8, Operand(r0)); // Sat 0xFFFF to 0-255 = 0xFF. + __ usat(r2, 12, Operand(r0, ASR, 9)); // Sat (0xFFFF>>9) to 0-4095 = 0x7F. + __ usat(r3, 1, Operand(r0, LSL, 16)); // Sat (0xFFFF<<16) to 0-1 = 0x0. + __ add(r0, r1, Operand(r2)); + __ add(r0, r0, Operand(r3)); + __ mov(pc, Operand(lr)); - CodeDesc desc; - assm.GetCode(&desc); - Handle<Code> code = isolate->factory()->NewCode( - desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + 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, 0xFFFF, 0, 0, 0, 0)); - ::printf("f() = %d\n", res); - CHECK_EQ(382, res); - } + F1 f = FUNCTION_CAST<F1>(code->entry()); + int res = reinterpret_cast<int>( + CALL_GENERATED_CODE(isolate, f, 0xFFFF, 0, 0, 0, 0)); + ::printf("f() = %d\n", res); + CHECK_EQ(382, res); } @@ -2231,6 +2228,272 @@ TEST(ARMv8_vrintX) { } } +TEST(ARMv8_vsel) { + // Test the vsel floating point instructions. + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + Assembler assm(isolate, NULL, 0); + + // Used to indicate whether a condition passed or failed. + static constexpr float kResultPass = 1.0f; + static constexpr float kResultFail = -kResultPass; + + struct ResultsF32 { + float vseleq_; + float vselge_; + float vselgt_; + float vselvs_; + + // The following conditions aren't architecturally supported, but the + // assembler implements them by swapping the inputs. + float vselne_; + float vsellt_; + float vselle_; + float vselvc_; + }; + + struct ResultsF64 { + double vseleq_; + double vselge_; + double vselgt_; + double vselvs_; + + // The following conditions aren't architecturally supported, but the + // assembler implements them by swapping the inputs. + double vselne_; + double vsellt_; + double vselle_; + double vselvc_; + }; + + if (CpuFeatures::IsSupported(ARMv8)) { + CpuFeatureScope scope(&assm, ARMv8); + + // Create a helper function: + // void TestVsel(uint32_t nzcv, + // ResultsF32* results_f32, + // ResultsF64* results_f64); + __ msr(CPSR_f, Operand(r0)); + + __ vmov(s1, kResultPass); + __ vmov(s2, kResultFail); + + __ vsel(eq, s0, s1, s2); + __ vstr(s0, r1, offsetof(ResultsF32, vseleq_)); + __ vsel(ge, s0, s1, s2); + __ vstr(s0, r1, offsetof(ResultsF32, vselge_)); + __ vsel(gt, s0, s1, s2); + __ vstr(s0, r1, offsetof(ResultsF32, vselgt_)); + __ vsel(vs, s0, s1, s2); + __ vstr(s0, r1, offsetof(ResultsF32, vselvs_)); + + __ vsel(ne, s0, s1, s2); + __ vstr(s0, r1, offsetof(ResultsF32, vselne_)); + __ vsel(lt, s0, s1, s2); + __ vstr(s0, r1, offsetof(ResultsF32, vsellt_)); + __ vsel(le, s0, s1, s2); + __ vstr(s0, r1, offsetof(ResultsF32, vselle_)); + __ vsel(vc, s0, s1, s2); + __ vstr(s0, r1, offsetof(ResultsF32, vselvc_)); + + __ vmov(d1, kResultPass); + __ vmov(d2, kResultFail); + + __ vsel(eq, d0, d1, d2); + __ vstr(d0, r2, offsetof(ResultsF64, vseleq_)); + __ vsel(ge, d0, d1, d2); + __ vstr(d0, r2, offsetof(ResultsF64, vselge_)); + __ vsel(gt, d0, d1, d2); + __ vstr(d0, r2, offsetof(ResultsF64, vselgt_)); + __ vsel(vs, d0, d1, d2); + __ vstr(d0, r2, offsetof(ResultsF64, vselvs_)); + + __ vsel(ne, d0, d1, d2); + __ vstr(d0, r2, offsetof(ResultsF64, vselne_)); + __ vsel(lt, d0, d1, d2); + __ vstr(d0, r2, offsetof(ResultsF64, vsellt_)); + __ vsel(le, d0, d1, d2); + __ vstr(d0, r2, offsetof(ResultsF64, vselle_)); + __ vsel(vc, d0, d1, d2); + __ vstr(d0, r2, offsetof(ResultsF64, vselvc_)); + + __ 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 + F5 f = FUNCTION_CAST<F5>(code->entry()); + Object* dummy = nullptr; + USE(dummy); + + STATIC_ASSERT(kResultPass == -kResultFail); +#define CHECK_VSEL(n, z, c, v, vseleq, vselge, vselgt, vselvs) \ + do { \ + ResultsF32 results_f32; \ + ResultsF64 results_f64; \ + uint32_t nzcv = (n << 31) | (z << 30) | (c << 29) | (v << 28); \ + dummy = CALL_GENERATED_CODE(isolate, f, nzcv, &results_f32, &results_f64, \ + 0, 0); \ + CHECK_EQ(vseleq, results_f32.vseleq_); \ + CHECK_EQ(vselge, results_f32.vselge_); \ + CHECK_EQ(vselgt, results_f32.vselgt_); \ + CHECK_EQ(vselvs, results_f32.vselvs_); \ + CHECK_EQ(-vseleq, results_f32.vselne_); \ + CHECK_EQ(-vselge, results_f32.vsellt_); \ + CHECK_EQ(-vselgt, results_f32.vselle_); \ + CHECK_EQ(-vselvs, results_f32.vselvc_); \ + CHECK_EQ(vseleq, results_f64.vseleq_); \ + CHECK_EQ(vselge, results_f64.vselge_); \ + CHECK_EQ(vselgt, results_f64.vselgt_); \ + CHECK_EQ(vselvs, results_f64.vselvs_); \ + CHECK_EQ(-vseleq, results_f64.vselne_); \ + CHECK_EQ(-vselge, results_f64.vsellt_); \ + CHECK_EQ(-vselgt, results_f64.vselle_); \ + CHECK_EQ(-vselvs, results_f64.vselvc_); \ + } while (0); + + // N Z C V vseleq vselge vselgt vselvs + CHECK_VSEL(0, 0, 0, 0, kResultFail, kResultPass, kResultPass, kResultFail); + CHECK_VSEL(0, 0, 0, 1, kResultFail, kResultFail, kResultFail, kResultPass); + CHECK_VSEL(0, 0, 1, 0, kResultFail, kResultPass, kResultPass, kResultFail); + CHECK_VSEL(0, 0, 1, 1, kResultFail, kResultFail, kResultFail, kResultPass); + CHECK_VSEL(0, 1, 0, 0, kResultPass, kResultPass, kResultFail, kResultFail); + CHECK_VSEL(0, 1, 0, 1, kResultPass, kResultFail, kResultFail, kResultPass); + CHECK_VSEL(0, 1, 1, 0, kResultPass, kResultPass, kResultFail, kResultFail); + CHECK_VSEL(0, 1, 1, 1, kResultPass, kResultFail, kResultFail, kResultPass); + CHECK_VSEL(1, 0, 0, 0, kResultFail, kResultFail, kResultFail, kResultFail); + CHECK_VSEL(1, 0, 0, 1, kResultFail, kResultPass, kResultPass, kResultPass); + CHECK_VSEL(1, 0, 1, 0, kResultFail, kResultFail, kResultFail, kResultFail); + CHECK_VSEL(1, 0, 1, 1, kResultFail, kResultPass, kResultPass, kResultPass); + CHECK_VSEL(1, 1, 0, 0, kResultPass, kResultFail, kResultFail, kResultFail); + CHECK_VSEL(1, 1, 0, 1, kResultPass, kResultPass, kResultFail, kResultPass); + CHECK_VSEL(1, 1, 1, 0, kResultPass, kResultFail, kResultFail, kResultFail); + CHECK_VSEL(1, 1, 1, 1, kResultPass, kResultPass, kResultFail, kResultPass); + +#undef CHECK_VSEL + } +} + +TEST(unaligned_loads) { + // All supported ARM targets allow unaligned accesses. + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + typedef struct { + uint32_t ldrh; + uint32_t ldrsh; + uint32_t ldr; + } T; + T t; + + Assembler assm(isolate, NULL, 0); + __ ldrh(ip, MemOperand(r1, r2)); + __ str(ip, MemOperand(r0, offsetof(T, ldrh))); + __ ldrsh(ip, MemOperand(r1, r2)); + __ str(ip, MemOperand(r0, offsetof(T, ldrsh))); + __ ldr(ip, MemOperand(r1, r2)); + __ str(ip, MemOperand(r0, offsetof(T, ldr))); + __ 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); + +#ifndef V8_TARGET_LITTLE_ENDIAN +#error This test assumes a little-endian layout. +#endif + uint64_t data = UINT64_C(0x84838281807f7e7d); + dummy = CALL_GENERATED_CODE(isolate, f, &t, &data, 0, 0, 0); + CHECK_EQ(0x00007e7d, t.ldrh); + CHECK_EQ(0x00007e7d, t.ldrsh); + CHECK_EQ(0x807f7e7d, t.ldr); + dummy = CALL_GENERATED_CODE(isolate, f, &t, &data, 1, 0, 0); + CHECK_EQ(0x00007f7e, t.ldrh); + CHECK_EQ(0x00007f7e, t.ldrsh); + CHECK_EQ(0x81807f7e, t.ldr); + dummy = CALL_GENERATED_CODE(isolate, f, &t, &data, 2, 0, 0); + CHECK_EQ(0x0000807f, t.ldrh); + CHECK_EQ(0xffff807f, t.ldrsh); + CHECK_EQ(0x8281807f, t.ldr); + dummy = CALL_GENERATED_CODE(isolate, f, &t, &data, 3, 0, 0); + CHECK_EQ(0x00008180, t.ldrh); + CHECK_EQ(0xffff8180, t.ldrsh); + CHECK_EQ(0x83828180, t.ldr); +} + +TEST(unaligned_stores) { + // All supported ARM targets allow unaligned accesses. + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + Assembler assm(isolate, NULL, 0); + __ strh(r3, MemOperand(r0, r2)); + __ str(r3, MemOperand(r1, r2)); + __ 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); + +#ifndef V8_TARGET_LITTLE_ENDIAN +#error This test assumes a little-endian layout. +#endif + { + uint64_t strh = 0; + uint64_t str = 0; + dummy = CALL_GENERATED_CODE(isolate, f, &strh, &str, 0, 0xfedcba98, 0); + CHECK_EQ(UINT64_C(0x000000000000ba98), strh); + CHECK_EQ(UINT64_C(0x00000000fedcba98), str); + } + { + uint64_t strh = 0; + uint64_t str = 0; + dummy = CALL_GENERATED_CODE(isolate, f, &strh, &str, 1, 0xfedcba98, 0); + CHECK_EQ(UINT64_C(0x0000000000ba9800), strh); + CHECK_EQ(UINT64_C(0x000000fedcba9800), str); + } + { + uint64_t strh = 0; + uint64_t str = 0; + dummy = CALL_GENERATED_CODE(isolate, f, &strh, &str, 2, 0xfedcba98, 0); + CHECK_EQ(UINT64_C(0x00000000ba980000), strh); + CHECK_EQ(UINT64_C(0x0000fedcba980000), str); + } + { + uint64_t strh = 0; + uint64_t str = 0; + dummy = CALL_GENERATED_CODE(isolate, f, &strh, &str, 3, 0xfedcba98, 0); + CHECK_EQ(UINT64_C(0x000000ba98000000), strh); + CHECK_EQ(UINT64_C(0x00fedcba98000000), str); + } +} TEST(regress4292_b) { CcTest::InitializeVM(); |