Index: test/cctest/test-assembler-arm.cc |
diff --git a/test/cctest/test-assembler-arm.cc b/test/cctest/test-assembler-arm.cc |
index 26f3ef98b5c827a27f8fc6aca7bed0458e5befb9..89153c7444335d1b5dc3543103edf9365609902b 100644 |
--- a/test/cctest/test-assembler-arm.cc |
+++ b/test/cctest/test-assembler-arm.cc |
@@ -1,4 +1,4 @@ |
-// Copyright 2010 the V8 project authors. All rights reserved. |
+// Copyright 2011 the V8 project authors. All rights reserved. |
// Redistribution and use in source and binary forms, with or without |
// modification, are permitted provided that the following conditions are |
// met: |
@@ -39,7 +39,8 @@ using namespace v8::internal; |
// Define these function prototypes to match JSEntryFunction in execution.cc. |
typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); |
typedef Object* (*F2)(int x, int y, int p2, int p3, int p4); |
-typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4); |
+typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4); |
+typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4); |
static v8::Persistent<v8::Context> env; |
@@ -608,4 +609,340 @@ TEST(7) { |
TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true); |
} |
+TEST(8) { |
+ // Test VFP multi load/store with ia_w. |
+ InitializeVM(); |
+ v8::HandleScope scope; |
+ |
+ typedef struct { |
+ double a; |
+ double b; |
+ double c; |
+ double d; |
+ double e; |
+ double f; |
+ double g; |
+ double h; |
+ } D; |
+ D d; |
+ |
+ typedef struct { |
+ float a; |
+ float b; |
+ float c; |
+ float d; |
+ float e; |
+ float f; |
+ float g; |
+ float h; |
+ } F; |
+ F f; |
+ |
+ // Create a function that uses vldm/vstm to move some double and |
+ // single precision values around in memory. |
+ Assembler assm(Isolate::Current(), NULL, 0); |
+ |
+ if (CpuFeatures::IsSupported(VFP3)) { |
+ CpuFeatures::Scope scope(VFP3); |
+ |
+ __ mov(ip, Operand(sp)); |
+ __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
+ __ sub(fp, ip, Operand(4)); |
+ |
+ __ add(r4, r0, Operand(OFFSET_OF(D, a))); |
+ __ vldm(ia_w, r4, d0, d3); |
+ __ vldm(ia_w, r4, d4, d7); |
+ |
+ __ add(r4, r0, Operand(OFFSET_OF(D, a))); |
+ __ vstm(ia_w, r4, d6, d7); |
+ __ vstm(ia_w, r4, d0, d5); |
+ |
+ __ add(r4, r1, Operand(OFFSET_OF(F, a))); |
+ __ vldm(ia_w, r4, s0, s3); |
+ __ vldm(ia_w, r4, s4, s7); |
+ |
+ __ add(r4, r1, Operand(OFFSET_OF(F, a))); |
+ __ vstm(ia_w, r4, s6, s7); |
+ __ vstm(ia_w, r4, s0, s5); |
+ |
+ __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
+ |
+ CodeDesc desc; |
+ assm.GetCode(&desc); |
+ Object* code = HEAP->CreateCode( |
+ desc, |
+ Code::ComputeFlags(Code::STUB), |
+ Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); |
+ CHECK(code->IsCode()); |
+#ifdef DEBUG |
+ Code::cast(code)->Print(); |
+#endif |
+ F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry()); |
+ d.a = 1.1; |
+ d.b = 2.2; |
+ d.c = 3.3; |
+ d.d = 4.4; |
+ d.e = 5.5; |
+ d.f = 6.6; |
+ d.g = 7.7; |
+ d.h = 8.8; |
+ |
+ f.a = 1.0; |
+ f.b = 2.0; |
+ f.c = 3.0; |
+ f.d = 4.0; |
+ f.e = 5.0; |
+ f.f = 6.0; |
+ f.g = 7.0; |
+ f.h = 8.0; |
+ |
+ Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0); |
+ USE(dummy); |
+ |
+ CHECK_EQ(7.7, d.a); |
+ CHECK_EQ(8.8, d.b); |
+ CHECK_EQ(1.1, d.c); |
+ CHECK_EQ(2.2, d.d); |
+ CHECK_EQ(3.3, d.e); |
+ CHECK_EQ(4.4, d.f); |
+ CHECK_EQ(5.5, d.g); |
+ CHECK_EQ(6.6, d.h); |
+ |
+ CHECK_EQ(7.0, f.a); |
+ CHECK_EQ(8.0, f.b); |
+ CHECK_EQ(1.0, f.c); |
+ CHECK_EQ(2.0, f.d); |
+ CHECK_EQ(3.0, f.e); |
+ CHECK_EQ(4.0, f.f); |
+ CHECK_EQ(5.0, f.g); |
+ CHECK_EQ(6.0, f.h); |
+ } |
+} |
+ |
+ |
+TEST(9) { |
+ // Test VFP multi load/store with ia. |
+ InitializeVM(); |
+ v8::HandleScope scope; |
+ |
+ typedef struct { |
+ double a; |
+ double b; |
+ double c; |
+ double d; |
+ double e; |
+ double f; |
+ double g; |
+ double h; |
+ } D; |
+ D d; |
+ |
+ typedef struct { |
+ float a; |
+ float b; |
+ float c; |
+ float d; |
+ float e; |
+ float f; |
+ float g; |
+ float h; |
+ } F; |
+ F f; |
+ |
+ // Create a function that uses vldm/vstm to move some double and |
+ // single precision values around in memory. |
+ Assembler assm(Isolate::Current(), NULL, 0); |
+ |
+ if (CpuFeatures::IsSupported(VFP3)) { |
+ CpuFeatures::Scope scope(VFP3); |
+ |
+ __ mov(ip, Operand(sp)); |
+ __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
+ __ sub(fp, ip, Operand(4)); |
+ |
+ __ add(r4, r0, Operand(OFFSET_OF(D, a))); |
+ __ vldm(ia, r4, d0, d3); |
+ __ add(r4, r4, Operand(4 * 8)); |
+ __ vldm(ia, r4, d4, d7); |
+ |
+ __ add(r4, r0, Operand(OFFSET_OF(D, a))); |
+ __ vstm(ia, r4, d6, d7); |
+ __ add(r4, r4, Operand(2 * 8)); |
+ __ vstm(ia, r4, d0, d5); |
+ |
+ __ add(r4, r1, Operand(OFFSET_OF(F, a))); |
+ __ vldm(ia, r4, s0, s3); |
+ __ add(r4, r4, Operand(4 * 4)); |
+ __ vldm(ia, r4, s4, s7); |
+ |
+ __ add(r4, r1, Operand(OFFSET_OF(F, a))); |
+ __ vstm(ia, r4, s6, s7); |
+ __ add(r4, r4, Operand(2 * 4)); |
+ __ vstm(ia, r4, s0, s5); |
+ |
+ __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
+ |
+ CodeDesc desc; |
+ assm.GetCode(&desc); |
+ Object* code = HEAP->CreateCode( |
+ desc, |
+ Code::ComputeFlags(Code::STUB), |
+ Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); |
+ CHECK(code->IsCode()); |
+#ifdef DEBUG |
+ Code::cast(code)->Print(); |
+#endif |
+ F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry()); |
+ d.a = 1.1; |
+ d.b = 2.2; |
+ d.c = 3.3; |
+ d.d = 4.4; |
+ d.e = 5.5; |
+ d.f = 6.6; |
+ d.g = 7.7; |
+ d.h = 8.8; |
+ |
+ f.a = 1.0; |
+ f.b = 2.0; |
+ f.c = 3.0; |
+ f.d = 4.0; |
+ f.e = 5.0; |
+ f.f = 6.0; |
+ f.g = 7.0; |
+ f.h = 8.0; |
+ |
+ Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0); |
+ USE(dummy); |
+ |
+ CHECK_EQ(7.7, d.a); |
+ CHECK_EQ(8.8, d.b); |
+ CHECK_EQ(1.1, d.c); |
+ CHECK_EQ(2.2, d.d); |
+ CHECK_EQ(3.3, d.e); |
+ CHECK_EQ(4.4, d.f); |
+ CHECK_EQ(5.5, d.g); |
+ CHECK_EQ(6.6, d.h); |
+ |
+ CHECK_EQ(7.0, f.a); |
+ CHECK_EQ(8.0, f.b); |
+ CHECK_EQ(1.0, f.c); |
+ CHECK_EQ(2.0, f.d); |
+ CHECK_EQ(3.0, f.e); |
+ CHECK_EQ(4.0, f.f); |
+ CHECK_EQ(5.0, f.g); |
+ CHECK_EQ(6.0, f.h); |
+ } |
+} |
+ |
+ |
+TEST(10) { |
+ // Test VFP multi load/store with db_w. |
+ InitializeVM(); |
+ v8::HandleScope scope; |
+ |
+ typedef struct { |
+ double a; |
+ double b; |
+ double c; |
+ double d; |
+ double e; |
+ double f; |
+ double g; |
+ double h; |
+ } D; |
+ D d; |
+ |
+ typedef struct { |
+ float a; |
+ float b; |
+ float c; |
+ float d; |
+ float e; |
+ float f; |
+ float g; |
+ float h; |
+ } F; |
+ F f; |
+ |
+ // Create a function that uses vldm/vstm to move some double and |
+ // single precision values around in memory. |
+ Assembler assm(Isolate::Current(), NULL, 0); |
+ |
+ if (CpuFeatures::IsSupported(VFP3)) { |
+ CpuFeatures::Scope scope(VFP3); |
+ |
+ __ mov(ip, Operand(sp)); |
+ __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
+ __ sub(fp, ip, Operand(4)); |
+ |
+ __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8)); |
+ __ vldm(db_w, r4, d4, d7); |
+ __ vldm(db_w, r4, d0, d3); |
+ |
+ __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8)); |
+ __ vstm(db_w, r4, d0, d5); |
+ __ vstm(db_w, r4, d6, d7); |
+ |
+ __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4)); |
+ __ vldm(db_w, r4, s4, s7); |
+ __ vldm(db_w, r4, s0, s3); |
+ |
+ __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4)); |
+ __ vstm(db_w, r4, s0, s5); |
+ __ vstm(db_w, r4, s6, s7); |
+ |
+ __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
+ |
+ CodeDesc desc; |
+ assm.GetCode(&desc); |
+ Object* code = HEAP->CreateCode( |
+ desc, |
+ Code::ComputeFlags(Code::STUB), |
+ Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); |
+ CHECK(code->IsCode()); |
+#ifdef DEBUG |
+ Code::cast(code)->Print(); |
+#endif |
+ F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry()); |
+ d.a = 1.1; |
+ d.b = 2.2; |
+ d.c = 3.3; |
+ d.d = 4.4; |
+ d.e = 5.5; |
+ d.f = 6.6; |
+ d.g = 7.7; |
+ d.h = 8.8; |
+ |
+ f.a = 1.0; |
+ f.b = 2.0; |
+ f.c = 3.0; |
+ f.d = 4.0; |
+ f.e = 5.0; |
+ f.f = 6.0; |
+ f.g = 7.0; |
+ f.h = 8.0; |
+ |
+ Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0); |
+ USE(dummy); |
+ |
+ CHECK_EQ(7.7, d.a); |
+ CHECK_EQ(8.8, d.b); |
+ CHECK_EQ(1.1, d.c); |
+ CHECK_EQ(2.2, d.d); |
+ CHECK_EQ(3.3, d.e); |
+ CHECK_EQ(4.4, d.f); |
+ CHECK_EQ(5.5, d.g); |
+ CHECK_EQ(6.6, d.h); |
+ |
+ CHECK_EQ(7.0, f.a); |
+ CHECK_EQ(8.0, f.b); |
+ CHECK_EQ(1.0, f.c); |
+ CHECK_EQ(2.0, f.d); |
+ CHECK_EQ(3.0, f.e); |
+ CHECK_EQ(4.0, f.f); |
+ CHECK_EQ(5.0, f.g); |
+ CHECK_EQ(6.0, f.h); |
+ } |
+} |
+ |
#undef __ |