Index: test/cctest/test-assembler-arm.cc |
diff --git a/test/cctest/test-assembler-arm.cc b/test/cctest/test-assembler-arm.cc |
index 232f846be0fa1085c61895754e654ffaff7ec31e..80c415d58dfb654b7a57872ea53643fee9c6882c 100644 |
--- a/test/cctest/test-assembler-arm.cc |
+++ b/test/cctest/test-assembler-arm.cc |
@@ -1226,4 +1226,185 @@ TEST(14) { |
CHECK_EQ(kArmNanLower32, BitCast<int64_t>(t.div_result) & 0xffffffffu); |
} |
+ |
+TEST(15) { |
+ // Test the Neon instructions. |
+ CcTest::InitializeVM(); |
+ Isolate* isolate = Isolate::Current(); |
+ HandleScope scope(isolate); |
+ |
+ typedef struct { |
+ uint32_t src0; |
+ uint32_t src1; |
+ uint32_t src2; |
+ uint32_t src3; |
+ uint32_t src4; |
+ uint32_t src5; |
+ uint32_t src6; |
+ uint32_t src7; |
+ uint32_t dst0; |
+ uint32_t dst1; |
+ uint32_t dst2; |
+ uint32_t dst3; |
+ uint32_t dst4; |
+ uint32_t dst5; |
+ uint32_t dst6; |
+ uint32_t dst7; |
+ uint32_t srcA0; |
+ uint32_t srcA1; |
+ uint32_t dstA0; |
+ uint32_t dstA1; |
+ uint32_t dstA2; |
+ uint32_t dstA3; |
+ } T; |
+ T t; |
+ |
+ // Create a function that accepts &t, and loads, manipulates, and stores |
+ // the doubles and floats. |
+ Assembler assm(isolate, NULL, 0); |
+ |
+ |
+ if (CpuFeatures::IsSupported(NEON)) { |
+ CpuFeatureScope scope(&assm, NEON); |
+ |
+ __ stm(db_w, sp, r4.bit() | lr.bit()); |
+ // Move 32 bytes with neon. |
+ __ add(r4, r0, Operand(OFFSET_OF(T, src0))); |
+ __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4)); |
+ __ add(r4, r0, Operand(OFFSET_OF(T, dst0))); |
+ __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4)); |
+ |
+ // Expand 8 bytes into 8 words(16 bits). |
+ __ add(r4, r0, Operand(OFFSET_OF(T, srcA0))); |
+ __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(r4)); |
+ __ vmovl(NeonU8, q0, d0); |
+ __ add(r4, r0, Operand(OFFSET_OF(T, dstA0))); |
+ __ vst1(Neon8, NeonListOperand(d0, 2), NeonMemOperand(r4)); |
+ |
+ __ ldm(ia_w, sp, r4.bit() | pc.bit()); |
+ |
+ CodeDesc desc; |
+ assm.GetCode(&desc); |
+ Object* code = isolate->heap()->CreateCode( |
+ desc, |
+ Code::ComputeFlags(Code::STUB), |
+ Handle<Code>())->ToObjectChecked(); |
+ CHECK(code->IsCode()); |
+#ifdef DEBUG |
+ Code::cast(code)->Print(); |
+#endif |
+ F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); |
+ t.src0 = 0x01020304; |
+ t.src1 = 0x11121314; |
+ t.src2 = 0x21222324; |
+ t.src3 = 0x31323334; |
+ t.src4 = 0x41424344; |
+ t.src5 = 0x51525354; |
+ t.src6 = 0x61626364; |
+ t.src7 = 0x71727374; |
+ t.dst0 = 0; |
+ t.dst1 = 0; |
+ t.dst2 = 0; |
+ t.dst3 = 0; |
+ t.dst4 = 0; |
+ t.dst5 = 0; |
+ t.dst6 = 0; |
+ t.dst7 = 0; |
+ t.srcA0 = 0x41424344; |
+ t.srcA1 = 0x81828384; |
+ t.dstA0 = 0; |
+ t.dstA1 = 0; |
+ t.dstA2 = 0; |
+ t.dstA3 = 0; |
+ Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
+ USE(dummy); |
+ CHECK_EQ(0x01020304, t.dst0); |
+ CHECK_EQ(0x11121314, t.dst1); |
+ CHECK_EQ(0x21222324, t.dst2); |
+ CHECK_EQ(0x31323334, t.dst3); |
+ CHECK_EQ(0x41424344, t.dst4); |
+ CHECK_EQ(0x51525354, t.dst5); |
+ CHECK_EQ(0x61626364, t.dst6); |
+ CHECK_EQ(0x71727374, t.dst7); |
+ CHECK_EQ(0x00430044, t.dstA0); |
+ CHECK_EQ(0x00410042, t.dstA1); |
+ CHECK_EQ(0x00830084, t.dstA2); |
+ CHECK_EQ(0x00810082, t.dstA3); |
+ } |
+} |
+ |
+TEST(16) { |
+ // Test the pkh, uxtb, uxtab and uxtb16 instructions. |
+ CcTest::InitializeVM(); |
+ Isolate* isolate = Isolate::Current(); |
+ HandleScope scope(isolate); |
+ |
+ typedef struct { |
+ uint32_t src0; |
+ uint32_t src1; |
+ uint32_t src2; |
+ uint32_t dst0; |
+ uint32_t dst1; |
+ uint32_t dst2; |
+ uint32_t dst3; |
+ uint32_t dst4; |
+ } T; |
+ T t; |
+ |
+ // Create a function that accepts &t, and loads, manipulates, and stores |
+ // the doubles and floats. |
+ Assembler assm(isolate, NULL, 0); |
+ |
+ __ stm(db_w, sp, r4.bit() | lr.bit()); |
+ |
+ __ mov(r4, Operand(r0)); |
+ __ ldr(r0, MemOperand(r4, OFFSET_OF(T, src0))); |
+ __ ldr(r1, MemOperand(r4, OFFSET_OF(T, src1))); |
+ |
+ __ pkhbt(r2, r0, Operand(r1, LSL, 8)); |
+ __ str(r2, MemOperand(r4, OFFSET_OF(T, dst0))); |
+ |
+ __ pkhtb(r2, r0, Operand(r1, ASR, 8)); |
+ __ str(r2, MemOperand(r4, OFFSET_OF(T, dst1))); |
+ |
+ __ uxtb16(r2, Operand(r0, ROR, 8)); |
+ __ str(r2, MemOperand(r4, OFFSET_OF(T, dst2))); |
+ |
+ __ uxtb(r2, Operand(r0, ROR, 8)); |
+ __ str(r2, MemOperand(r4, OFFSET_OF(T, dst3))); |
+ |
+ __ ldr(r0, MemOperand(r4, OFFSET_OF(T, src2))); |
+ __ uxtab(r2, r0, Operand(r1, ROR, 8)); |
+ __ str(r2, MemOperand(r4, OFFSET_OF(T, dst4))); |
+ |
+ __ ldm(ia_w, sp, r4.bit() | pc.bit()); |
+ |
+ CodeDesc desc; |
+ assm.GetCode(&desc); |
+ Object* code = isolate->heap()->CreateCode( |
+ desc, |
+ Code::ComputeFlags(Code::STUB), |
+ Handle<Code>())->ToObjectChecked(); |
+ CHECK(code->IsCode()); |
+#ifdef DEBUG |
+ Code::cast(code)->Print(); |
+#endif |
+ F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); |
+ t.src0 = 0x01020304; |
+ t.src1 = 0x11121314; |
+ t.src2 = 0x11121300; |
+ t.dst0 = 0; |
+ t.dst1 = 0; |
+ t.dst2 = 0; |
+ t.dst3 = 0; |
+ t.dst4 = 0; |
+ Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
+ USE(dummy); |
+ CHECK_EQ(0x12130304, t.dst0); |
+ CHECK_EQ(0x01021213, t.dst1); |
+ CHECK_EQ(0x00010003, t.dst2); |
+ CHECK_EQ(0x00000003, t.dst3); |
+ CHECK_EQ(0x11121313, t.dst4); |
+} |
+ |
#undef __ |