blob: 8cce08465eeaca318c0965fd4a962f81f293c685 [file] [log] [blame]
verwaest@chromium.orgb6d052d2012-07-27 08:03:27 +00001// Copyright 2012 the V8 project authors. All rights reserved.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
27
ulan@chromium.org57ff8812013-05-10 08:16:55 +000028// TODO(dcarney): remove
29#define V8_ALLOW_ACCESS_TO_PERSISTENT_IMPLICIT
30#define V8_ALLOW_ACCESS_TO_PERSISTENT_ARROW
31
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000032#include "v8.h"
33
34#include "disassembler.h"
35#include "factory.h"
ager@chromium.org3a37e9b2009-04-27 09:26:21 +000036#include "arm/simulator-arm.h"
37#include "arm/assembler-arm-inl.h"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000038#include "cctest.h"
39
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000040using namespace v8::internal;
41
42
43// Define these function prototypes to match JSEntryFunction in execution.cc.
ager@chromium.orga1645e22009-09-09 19:27:10 +000044typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
45typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +000046typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4);
47typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000048
49
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000050#define __ assm.
51
52TEST(0) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000053 CcTest::InitializeVM();
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000054 Isolate* isolate = Isolate::Current();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000055 HandleScope scope(isolate);
56
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000057 Assembler assm(isolate, NULL, 0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000058
59 __ add(r0, r0, Operand(r1));
60 __ mov(pc, Operand(lr));
61
62 CodeDesc desc;
63 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000064 Object* code = isolate->heap()->CreateCode(
lrn@chromium.org303ada72010-10-27 09:33:13 +000065 desc,
66 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000067 Handle<Code>())->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000068 CHECK(code->IsCode());
69#ifdef DEBUG
70 Code::cast(code)->Print();
71#endif
72 F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
73 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 3, 4, 0, 0, 0));
74 ::printf("f() = %d\n", res);
75 CHECK_EQ(7, res);
76}
77
78
79TEST(1) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000080 CcTest::InitializeVM();
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000081 Isolate* isolate = Isolate::Current();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000082 HandleScope scope(isolate);
83
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000084 Assembler assm(isolate, NULL, 0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000085 Label L, C;
86
87 __ mov(r1, Operand(r0));
jkummerow@chromium.org59297c72013-01-09 16:32:23 +000088 __ mov(r0, Operand::Zero());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000089 __ b(&C);
90
91 __ bind(&L);
92 __ add(r0, r0, Operand(r1));
93 __ sub(r1, r1, Operand(1));
94
95 __ bind(&C);
jkummerow@chromium.org59297c72013-01-09 16:32:23 +000096 __ teq(r1, Operand::Zero());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000097 __ b(ne, &L);
98 __ mov(pc, Operand(lr));
99
100 CodeDesc desc;
101 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000102 Object* code = isolate->heap()->CreateCode(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000103 desc,
104 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000105 Handle<Code>())->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000106 CHECK(code->IsCode());
107#ifdef DEBUG
108 Code::cast(code)->Print();
109#endif
110 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
111 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 100, 0, 0, 0, 0));
112 ::printf("f() = %d\n", res);
113 CHECK_EQ(5050, res);
114}
115
116
117TEST(2) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000118 CcTest::InitializeVM();
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000119 Isolate* isolate = Isolate::Current();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000120 HandleScope scope(isolate);
121
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000122 Assembler assm(isolate, NULL, 0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000123 Label L, C;
124
125 __ mov(r1, Operand(r0));
126 __ mov(r0, Operand(1));
127 __ b(&C);
128
129 __ bind(&L);
130 __ mul(r0, r1, r0);
131 __ sub(r1, r1, Operand(1));
132
133 __ bind(&C);
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000134 __ teq(r1, Operand::Zero());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000135 __ b(ne, &L);
136 __ mov(pc, Operand(lr));
137
138 // some relocated stuff here, not executed
139 __ RecordComment("dead code, just testing relocations");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000140 __ mov(r0, Operand(FACTORY->true_value()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000141 __ RecordComment("dead code, just testing immediate operands");
142 __ mov(r0, Operand(-1));
143 __ mov(r0, Operand(0xFF000000));
144 __ mov(r0, Operand(0xF0F0F0F0));
145 __ mov(r0, Operand(0xFFF0FFFF));
146
147 CodeDesc desc;
148 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000149 Object* code = isolate->heap()->CreateCode(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000150 desc,
151 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000152 Handle<Code>())->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000153 CHECK(code->IsCode());
154#ifdef DEBUG
155 Code::cast(code)->Print();
156#endif
157 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
158 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 10, 0, 0, 0, 0));
159 ::printf("f() = %d\n", res);
160 CHECK_EQ(3628800, res);
161}
162
163
164TEST(3) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000165 CcTest::InitializeVM();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000166 Isolate* isolate = Isolate::Current();
167 HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000168
169 typedef struct {
170 int i;
171 char c;
172 int16_t s;
173 } T;
174 T t;
175
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000176 Assembler assm(isolate, NULL, 0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000177 Label L, C;
178
179 __ mov(ip, Operand(sp));
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000180 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000181 __ sub(fp, ip, Operand(4));
182 __ mov(r4, Operand(r0));
183 __ ldr(r0, MemOperand(r4, OFFSET_OF(T, i)));
184 __ mov(r2, Operand(r0, ASR, 1));
185 __ str(r2, MemOperand(r4, OFFSET_OF(T, i)));
186 __ ldrsb(r2, MemOperand(r4, OFFSET_OF(T, c)));
187 __ add(r0, r2, Operand(r0));
188 __ mov(r2, Operand(r2, LSL, 2));
189 __ strb(r2, MemOperand(r4, OFFSET_OF(T, c)));
190 __ ldrsh(r2, MemOperand(r4, OFFSET_OF(T, s)));
191 __ add(r0, r2, Operand(r0));
192 __ mov(r2, Operand(r2, ASR, 3));
193 __ strh(r2, MemOperand(r4, OFFSET_OF(T, s)));
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000194 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000195
196 CodeDesc desc;
197 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000198 Object* code = isolate->heap()->CreateCode(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000199 desc,
200 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000201 Handle<Code>())->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000202 CHECK(code->IsCode());
203#ifdef DEBUG
204 Code::cast(code)->Print();
205#endif
206 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
207 t.i = 100000;
208 t.c = 10;
209 t.s = 1000;
210 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0));
211 ::printf("f() = %d\n", res);
212 CHECK_EQ(101010, res);
213 CHECK_EQ(100000/2, t.i);
214 CHECK_EQ(10*4, t.c);
215 CHECK_EQ(1000/8, t.s);
216}
217
218
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000219TEST(4) {
220 // Test the VFP floating point instructions.
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000221 CcTest::InitializeVM();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000222 Isolate* isolate = Isolate::Current();
223 HandleScope scope(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000224
225 typedef struct {
226 double a;
227 double b;
228 double c;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000229 double d;
230 double e;
231 double f;
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000232 double g;
233 double h;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000234 int i;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000235 double m;
236 double n;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000237 float x;
238 float y;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000239 } T;
240 T t;
241
242 // Create a function that accepts &t, and loads, manipulates, and stores
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000243 // the doubles and floats.
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000244 Assembler assm(isolate, NULL, 0);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000245 Label L, C;
246
247
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000248 if (CpuFeatures::IsSupported(VFP3)) {
ulan@chromium.org750145a2013-03-07 15:14:13 +0000249 CpuFeatureScope scope(&assm, VFP3);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000250
251 __ mov(ip, Operand(sp));
252 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
253 __ sub(fp, ip, Operand(4));
254
255 __ mov(r4, Operand(r0));
256 __ vldr(d6, r4, OFFSET_OF(T, a));
257 __ vldr(d7, r4, OFFSET_OF(T, b));
258 __ vadd(d5, d6, d7);
259 __ vstr(d5, r4, OFFSET_OF(T, c));
260
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000261 __ vmla(d5, d6, d7);
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000262 __ vmls(d5, d5, d6);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000263
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000264 __ vmov(r2, r3, d5);
265 __ vmov(d4, r2, r3);
266 __ vstr(d4, r4, OFFSET_OF(T, b));
267
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000268 // Load t.x and t.y, switch values, and store back to the struct.
269 __ vldr(s0, r4, OFFSET_OF(T, x));
270 __ vldr(s31, r4, OFFSET_OF(T, y));
271 __ vmov(s16, s0);
272 __ vmov(s0, s31);
273 __ vmov(s31, s16);
274 __ vstr(s0, r4, OFFSET_OF(T, x));
275 __ vstr(s31, r4, OFFSET_OF(T, y));
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000276
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000277 // Move a literal into a register that can be encoded in the instruction.
278 __ vmov(d4, 1.0);
279 __ vstr(d4, r4, OFFSET_OF(T, e));
280
281 // Move a literal into a register that requires 64 bits to encode.
282 // 0x3ff0000010000000 = 1.000000059604644775390625
283 __ vmov(d4, 1.000000059604644775390625);
284 __ vstr(d4, r4, OFFSET_OF(T, d));
285
286 // Convert from floating point to integer.
287 __ vmov(d4, 2.0);
288 __ vcvt_s32_f64(s31, d4);
289 __ vstr(s31, r4, OFFSET_OF(T, i));
290
291 // Convert from integer to floating point.
292 __ mov(lr, Operand(42));
293 __ vmov(s31, lr);
294 __ vcvt_f64_s32(d4, s31);
295 __ vstr(d4, r4, OFFSET_OF(T, f));
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000296
297 // Test vabs.
298 __ vldr(d1, r4, OFFSET_OF(T, g));
299 __ vabs(d0, d1);
300 __ vstr(d0, r4, OFFSET_OF(T, g));
301 __ vldr(d2, r4, OFFSET_OF(T, h));
302 __ vabs(d0, d2);
303 __ vstr(d0, r4, OFFSET_OF(T, h));
304
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000305 // Test vneg.
306 __ vldr(d1, r4, OFFSET_OF(T, m));
307 __ vneg(d0, d1);
308 __ vstr(d0, r4, OFFSET_OF(T, m));
309 __ vldr(d1, r4, OFFSET_OF(T, n));
310 __ vneg(d0, d1);
311 __ vstr(d0, r4, OFFSET_OF(T, n));
312
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000313 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
314
315 CodeDesc desc;
316 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000317 Object* code = isolate->heap()->CreateCode(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000318 desc,
319 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000320 Handle<Code>())->ToObjectChecked();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000321 CHECK(code->IsCode());
322#ifdef DEBUG
323 Code::cast(code)->Print();
324#endif
325 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
326 t.a = 1.5;
327 t.b = 2.75;
328 t.c = 17.17;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000329 t.d = 0.0;
330 t.e = 0.0;
331 t.f = 0.0;
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000332 t.g = -2718.2818;
333 t.h = 31415926.5;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000334 t.i = 0;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000335 t.m = -2718.2818;
336 t.n = 123.456;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000337 t.x = 4.5;
338 t.y = 9.0;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000339 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
340 USE(dummy);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000341 CHECK_EQ(4.5, t.y);
342 CHECK_EQ(9.0, t.x);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000343 CHECK_EQ(-123.456, t.n);
344 CHECK_EQ(2718.2818, t.m);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000345 CHECK_EQ(2, t.i);
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000346 CHECK_EQ(2718.2818, t.g);
347 CHECK_EQ(31415926.5, t.h);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000348 CHECK_EQ(42.0, t.f);
349 CHECK_EQ(1.0, t.e);
350 CHECK_EQ(1.000000059604644775390625, t.d);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000351 CHECK_EQ(4.25, t.c);
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000352 CHECK_EQ(-4.1875, t.b);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000353 CHECK_EQ(1.5, t.a);
354 }
355}
356
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000357
358TEST(5) {
359 // Test the ARMv7 bitfield instructions.
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000360 CcTest::InitializeVM();
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000361 Isolate* isolate = Isolate::Current();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000362 HandleScope scope(isolate);
363
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000364 Assembler assm(isolate, NULL, 0);
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000365
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000366 if (CpuFeatures::IsSupported(ARMv7)) {
ulan@chromium.org750145a2013-03-07 15:14:13 +0000367 CpuFeatureScope scope(&assm, ARMv7);
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000368 // On entry, r0 = 0xAAAAAAAA = 0b10..10101010.
369 __ ubfx(r0, r0, 1, 12); // 0b00..010101010101 = 0x555
370 __ sbfx(r0, r0, 0, 5); // 0b11..111111110101 = -11
371 __ bfc(r0, 1, 3); // 0b11..111111110001 = -15
372 __ mov(r1, Operand(7));
373 __ bfi(r0, r1, 3, 3); // 0b11..111111111001 = -7
374 __ mov(pc, Operand(lr));
375
376 CodeDesc desc;
377 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000378 Object* code = isolate->heap()->CreateCode(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000379 desc,
380 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000381 Handle<Code>())->ToObjectChecked();
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000382 CHECK(code->IsCode());
383#ifdef DEBUG
384 Code::cast(code)->Print();
385#endif
386 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
387 int res = reinterpret_cast<int>(
388 CALL_GENERATED_CODE(f, 0xAAAAAAAA, 0, 0, 0, 0));
389 ::printf("f() = %d\n", res);
390 CHECK_EQ(-7, res);
391 }
392}
393
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000394
395TEST(6) {
396 // Test saturating instructions.
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000397 CcTest::InitializeVM();
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000398 Isolate* isolate = Isolate::Current();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000399 HandleScope scope(isolate);
400
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000401 Assembler assm(isolate, NULL, 0);
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000402
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000403 if (CpuFeatures::IsSupported(ARMv7)) {
ulan@chromium.org750145a2013-03-07 15:14:13 +0000404 CpuFeatureScope scope(&assm, ARMv7);
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000405 __ usat(r1, 8, Operand(r0)); // Sat 0xFFFF to 0-255 = 0xFF.
406 __ usat(r2, 12, Operand(r0, ASR, 9)); // Sat (0xFFFF>>9) to 0-4095 = 0x7F.
407 __ usat(r3, 1, Operand(r0, LSL, 16)); // Sat (0xFFFF<<16) to 0-1 = 0x0.
408 __ add(r0, r1, Operand(r2));
409 __ add(r0, r0, Operand(r3));
410 __ mov(pc, Operand(lr));
411
412 CodeDesc desc;
413 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000414 Object* code = isolate->heap()->CreateCode(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000415 desc,
416 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000417 Handle<Code>())->ToObjectChecked();
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000418 CHECK(code->IsCode());
419#ifdef DEBUG
420 Code::cast(code)->Print();
421#endif
422 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
423 int res = reinterpret_cast<int>(
424 CALL_GENERATED_CODE(f, 0xFFFF, 0, 0, 0, 0));
425 ::printf("f() = %d\n", res);
426 CHECK_EQ(382, res);
427 }
428}
429
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000430
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000431enum VCVTTypes {
432 s32_f64,
433 u32_f64
434};
435
436static void TestRoundingMode(VCVTTypes types,
437 VFPRoundingMode mode,
438 double value,
439 int expected,
440 bool expected_exception = false) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000441 CcTest::InitializeVM();
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000442 Isolate* isolate = Isolate::Current();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000443 HandleScope scope(isolate);
444
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000445 Assembler assm(isolate, NULL, 0);
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000446
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000447 if (CpuFeatures::IsSupported(VFP3)) {
ulan@chromium.org750145a2013-03-07 15:14:13 +0000448 CpuFeatureScope scope(&assm, VFP3);
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000449
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000450 Label wrong_exception;
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000451
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000452 __ vmrs(r1);
453 // Set custom FPSCR.
454 __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask));
455 __ orr(r2, r2, Operand(mode));
456 __ vmsr(r2);
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000457
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000458 // Load value, convert, and move back result to r0 if everything went well.
459 __ vmov(d1, value);
460 switch (types) {
461 case s32_f64:
462 __ vcvt_s32_f64(s0, d1, kFPSCRRounding);
463 break;
464
465 case u32_f64:
466 __ vcvt_u32_f64(s0, d1, kFPSCRRounding);
467 break;
468
469 default:
470 UNREACHABLE();
471 break;
472 }
473 // Check for vfp exceptions
474 __ vmrs(r2);
475 __ tst(r2, Operand(kVFPExceptionMask));
476 // Check that we behaved as expected.
477 __ b(&wrong_exception,
478 expected_exception ? eq : ne);
479 // There was no exception. Retrieve the result and return.
480 __ vmov(r0, s0);
481 __ mov(pc, Operand(lr));
482
483 // The exception behaviour is not what we expected.
484 // Load a special value and return.
485 __ bind(&wrong_exception);
486 __ mov(r0, Operand(11223344));
487 __ mov(pc, Operand(lr));
488
489 CodeDesc desc;
490 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000491 Object* code = isolate->heap()->CreateCode(
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000492 desc,
493 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000494 Handle<Code>())->ToObjectChecked();
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000495 CHECK(code->IsCode());
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000496#ifdef DEBUG
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000497 Code::cast(code)->Print();
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000498#endif
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000499 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
500 int res = reinterpret_cast<int>(
501 CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
502 ::printf("res = %d\n", res);
503 CHECK_EQ(expected, res);
504 }
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000505}
506
507
508TEST(7) {
509 // Test vfp rounding modes.
510
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000511 // s32_f64 (double to integer).
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000512
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000513 TestRoundingMode(s32_f64, RN, 0, 0);
514 TestRoundingMode(s32_f64, RN, 0.5, 0);
515 TestRoundingMode(s32_f64, RN, -0.5, 0);
516 TestRoundingMode(s32_f64, RN, 1.5, 2);
517 TestRoundingMode(s32_f64, RN, -1.5, -2);
518 TestRoundingMode(s32_f64, RN, 123.7, 124);
519 TestRoundingMode(s32_f64, RN, -123.7, -124);
520 TestRoundingMode(s32_f64, RN, 123456.2, 123456);
521 TestRoundingMode(s32_f64, RN, -123456.2, -123456);
522 TestRoundingMode(s32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
523 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.49), kMaxInt);
524 TestRoundingMode(s32_f64, RN, (kMaxInt + 1.0), kMaxInt, true);
525 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.5), kMaxInt, true);
526 TestRoundingMode(s32_f64, RN, static_cast<double>(kMinInt), kMinInt);
527 TestRoundingMode(s32_f64, RN, (kMinInt - 0.5), kMinInt);
528 TestRoundingMode(s32_f64, RN, (kMinInt - 1.0), kMinInt, true);
529 TestRoundingMode(s32_f64, RN, (kMinInt - 0.51), kMinInt, true);
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000530
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000531 TestRoundingMode(s32_f64, RM, 0, 0);
532 TestRoundingMode(s32_f64, RM, 0.5, 0);
533 TestRoundingMode(s32_f64, RM, -0.5, -1);
534 TestRoundingMode(s32_f64, RM, 123.7, 123);
535 TestRoundingMode(s32_f64, RM, -123.7, -124);
536 TestRoundingMode(s32_f64, RM, 123456.2, 123456);
537 TestRoundingMode(s32_f64, RM, -123456.2, -123457);
538 TestRoundingMode(s32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
539 TestRoundingMode(s32_f64, RM, (kMaxInt + 0.5), kMaxInt);
540 TestRoundingMode(s32_f64, RM, (kMaxInt + 1.0), kMaxInt, true);
541 TestRoundingMode(s32_f64, RM, static_cast<double>(kMinInt), kMinInt);
542 TestRoundingMode(s32_f64, RM, (kMinInt - 0.5), kMinInt, true);
543 TestRoundingMode(s32_f64, RM, (kMinInt + 0.5), kMinInt);
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000544
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000545 TestRoundingMode(s32_f64, RZ, 0, 0);
546 TestRoundingMode(s32_f64, RZ, 0.5, 0);
547 TestRoundingMode(s32_f64, RZ, -0.5, 0);
548 TestRoundingMode(s32_f64, RZ, 123.7, 123);
549 TestRoundingMode(s32_f64, RZ, -123.7, -123);
550 TestRoundingMode(s32_f64, RZ, 123456.2, 123456);
551 TestRoundingMode(s32_f64, RZ, -123456.2, -123456);
552 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
553 TestRoundingMode(s32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
554 TestRoundingMode(s32_f64, RZ, (kMaxInt + 1.0), kMaxInt, true);
555 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMinInt), kMinInt);
556 TestRoundingMode(s32_f64, RZ, (kMinInt - 0.5), kMinInt);
557 TestRoundingMode(s32_f64, RZ, (kMinInt - 1.0), kMinInt, true);
558
559
560 // u32_f64 (double to integer).
561
562 // Negative values.
563 TestRoundingMode(u32_f64, RN, -0.5, 0);
564 TestRoundingMode(u32_f64, RN, -123456.7, 0, true);
565 TestRoundingMode(u32_f64, RN, static_cast<double>(kMinInt), 0, true);
566 TestRoundingMode(u32_f64, RN, kMinInt - 1.0, 0, true);
567
568 TestRoundingMode(u32_f64, RM, -0.5, 0, true);
569 TestRoundingMode(u32_f64, RM, -123456.7, 0, true);
570 TestRoundingMode(u32_f64, RM, static_cast<double>(kMinInt), 0, true);
571 TestRoundingMode(u32_f64, RM, kMinInt - 1.0, 0, true);
572
573 TestRoundingMode(u32_f64, RZ, -0.5, 0);
574 TestRoundingMode(u32_f64, RZ, -123456.7, 0, true);
575 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMinInt), 0, true);
576 TestRoundingMode(u32_f64, RZ, kMinInt - 1.0, 0, true);
577
578 // Positive values.
579 // kMaxInt is the maximum *signed* integer: 0x7fffffff.
580 static const uint32_t kMaxUInt = 0xffffffffu;
581 TestRoundingMode(u32_f64, RZ, 0, 0);
582 TestRoundingMode(u32_f64, RZ, 0.5, 0);
583 TestRoundingMode(u32_f64, RZ, 123.7, 123);
584 TestRoundingMode(u32_f64, RZ, 123456.2, 123456);
585 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
586 TestRoundingMode(u32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
587 TestRoundingMode(u32_f64, RZ, (kMaxInt + 1.0),
588 static_cast<uint32_t>(kMaxInt) + 1);
589 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 0.5), kMaxUInt);
590 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 1.0), kMaxUInt, true);
591
592 TestRoundingMode(u32_f64, RM, 0, 0);
593 TestRoundingMode(u32_f64, RM, 0.5, 0);
594 TestRoundingMode(u32_f64, RM, 123.7, 123);
595 TestRoundingMode(u32_f64, RM, 123456.2, 123456);
596 TestRoundingMode(u32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
597 TestRoundingMode(u32_f64, RM, (kMaxInt + 0.5), kMaxInt);
598 TestRoundingMode(u32_f64, RM, (kMaxInt + 1.0),
599 static_cast<uint32_t>(kMaxInt) + 1);
600 TestRoundingMode(u32_f64, RM, (kMaxUInt + 0.5), kMaxUInt);
601 TestRoundingMode(u32_f64, RM, (kMaxUInt + 1.0), kMaxUInt, true);
602
603 TestRoundingMode(u32_f64, RN, 0, 0);
604 TestRoundingMode(u32_f64, RN, 0.5, 0);
605 TestRoundingMode(u32_f64, RN, 1.5, 2);
606 TestRoundingMode(u32_f64, RN, 123.7, 124);
607 TestRoundingMode(u32_f64, RN, 123456.2, 123456);
608 TestRoundingMode(u32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
609 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.49), kMaxInt);
610 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.5),
611 static_cast<uint32_t>(kMaxInt) + 1);
612 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.49), kMaxUInt);
613 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.5), kMaxUInt, true);
614 TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true);
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000615}
616
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000617TEST(8) {
618 // Test VFP multi load/store with ia_w.
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000619 CcTest::InitializeVM();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000620 Isolate* isolate = Isolate::Current();
621 HandleScope scope(isolate);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000622
623 typedef struct {
624 double a;
625 double b;
626 double c;
627 double d;
628 double e;
629 double f;
630 double g;
631 double h;
632 } D;
633 D d;
634
635 typedef struct {
636 float a;
637 float b;
638 float c;
639 float d;
640 float e;
641 float f;
642 float g;
643 float h;
644 } F;
645 F f;
646
647 // Create a function that uses vldm/vstm to move some double and
648 // single precision values around in memory.
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000649 Assembler assm(isolate, NULL, 0);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000650
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000651 __ mov(ip, Operand(sp));
652 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
653 __ sub(fp, ip, Operand(4));
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000654
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000655 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
656 __ vldm(ia_w, r4, d0, d3);
657 __ vldm(ia_w, r4, d4, d7);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000658
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000659 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
660 __ vstm(ia_w, r4, d6, d7);
661 __ vstm(ia_w, r4, d0, d5);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000662
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000663 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
664 __ vldm(ia_w, r4, s0, s3);
665 __ vldm(ia_w, r4, s4, s7);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000666
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000667 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
668 __ vstm(ia_w, r4, s6, s7);
669 __ vstm(ia_w, r4, s0, s5);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000670
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000671 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000672
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000673 CodeDesc desc;
674 assm.GetCode(&desc);
675 Object* code = isolate->heap()->CreateCode(
676 desc,
677 Code::ComputeFlags(Code::STUB),
678 Handle<Code>())->ToObjectChecked();
679 CHECK(code->IsCode());
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000680#ifdef DEBUG
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000681 Code::cast(code)->Print();
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000682#endif
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000683 F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
684 d.a = 1.1;
685 d.b = 2.2;
686 d.c = 3.3;
687 d.d = 4.4;
688 d.e = 5.5;
689 d.f = 6.6;
690 d.g = 7.7;
691 d.h = 8.8;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000692
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000693 f.a = 1.0;
694 f.b = 2.0;
695 f.c = 3.0;
696 f.d = 4.0;
697 f.e = 5.0;
698 f.f = 6.0;
699 f.g = 7.0;
700 f.h = 8.0;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000701
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000702 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
703 USE(dummy);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000704
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000705 CHECK_EQ(7.7, d.a);
706 CHECK_EQ(8.8, d.b);
707 CHECK_EQ(1.1, d.c);
708 CHECK_EQ(2.2, d.d);
709 CHECK_EQ(3.3, d.e);
710 CHECK_EQ(4.4, d.f);
711 CHECK_EQ(5.5, d.g);
712 CHECK_EQ(6.6, d.h);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000713
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000714 CHECK_EQ(7.0, f.a);
715 CHECK_EQ(8.0, f.b);
716 CHECK_EQ(1.0, f.c);
717 CHECK_EQ(2.0, f.d);
718 CHECK_EQ(3.0, f.e);
719 CHECK_EQ(4.0, f.f);
720 CHECK_EQ(5.0, f.g);
721 CHECK_EQ(6.0, f.h);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000722}
723
724
725TEST(9) {
726 // Test VFP multi load/store with ia.
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000727 CcTest::InitializeVM();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000728 Isolate* isolate = Isolate::Current();
729 HandleScope scope(isolate);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000730
731 typedef struct {
732 double a;
733 double b;
734 double c;
735 double d;
736 double e;
737 double f;
738 double g;
739 double h;
740 } D;
741 D d;
742
743 typedef struct {
744 float a;
745 float b;
746 float c;
747 float d;
748 float e;
749 float f;
750 float g;
751 float h;
752 } F;
753 F f;
754
755 // Create a function that uses vldm/vstm to move some double and
756 // single precision values around in memory.
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000757 Assembler assm(isolate, NULL, 0);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000758
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000759 __ mov(ip, Operand(sp));
760 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
761 __ sub(fp, ip, Operand(4));
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000762
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000763 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
764 __ vldm(ia, r4, d0, d3);
765 __ add(r4, r4, Operand(4 * 8));
766 __ vldm(ia, r4, d4, d7);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000767
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000768 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
769 __ vstm(ia, r4, d6, d7);
770 __ add(r4, r4, Operand(2 * 8));
771 __ vstm(ia, r4, d0, d5);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000772
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000773 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
774 __ vldm(ia, r4, s0, s3);
775 __ add(r4, r4, Operand(4 * 4));
776 __ vldm(ia, r4, s4, s7);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000777
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000778 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
779 __ vstm(ia, r4, s6, s7);
780 __ add(r4, r4, Operand(2 * 4));
781 __ vstm(ia, r4, s0, s5);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000782
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000783 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000784
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000785 CodeDesc desc;
786 assm.GetCode(&desc);
787 Object* code = isolate->heap()->CreateCode(
788 desc,
789 Code::ComputeFlags(Code::STUB),
790 Handle<Code>())->ToObjectChecked();
791 CHECK(code->IsCode());
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000792#ifdef DEBUG
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000793 Code::cast(code)->Print();
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000794#endif
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000795 F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
796 d.a = 1.1;
797 d.b = 2.2;
798 d.c = 3.3;
799 d.d = 4.4;
800 d.e = 5.5;
801 d.f = 6.6;
802 d.g = 7.7;
803 d.h = 8.8;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000804
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000805 f.a = 1.0;
806 f.b = 2.0;
807 f.c = 3.0;
808 f.d = 4.0;
809 f.e = 5.0;
810 f.f = 6.0;
811 f.g = 7.0;
812 f.h = 8.0;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000813
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000814 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
815 USE(dummy);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000816
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000817 CHECK_EQ(7.7, d.a);
818 CHECK_EQ(8.8, d.b);
819 CHECK_EQ(1.1, d.c);
820 CHECK_EQ(2.2, d.d);
821 CHECK_EQ(3.3, d.e);
822 CHECK_EQ(4.4, d.f);
823 CHECK_EQ(5.5, d.g);
824 CHECK_EQ(6.6, d.h);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000825
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000826 CHECK_EQ(7.0, f.a);
827 CHECK_EQ(8.0, f.b);
828 CHECK_EQ(1.0, f.c);
829 CHECK_EQ(2.0, f.d);
830 CHECK_EQ(3.0, f.e);
831 CHECK_EQ(4.0, f.f);
832 CHECK_EQ(5.0, f.g);
833 CHECK_EQ(6.0, f.h);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000834}
835
836
837TEST(10) {
838 // Test VFP multi load/store with db_w.
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000839 CcTest::InitializeVM();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000840 Isolate* isolate = Isolate::Current();
841 HandleScope scope(isolate);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000842
843 typedef struct {
844 double a;
845 double b;
846 double c;
847 double d;
848 double e;
849 double f;
850 double g;
851 double h;
852 } D;
853 D d;
854
855 typedef struct {
856 float a;
857 float b;
858 float c;
859 float d;
860 float e;
861 float f;
862 float g;
863 float h;
864 } F;
865 F f;
866
867 // Create a function that uses vldm/vstm to move some double and
868 // single precision values around in memory.
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000869 Assembler assm(isolate, NULL, 0);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000870
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000871 __ mov(ip, Operand(sp));
872 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
873 __ sub(fp, ip, Operand(4));
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000874
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000875 __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8));
876 __ vldm(db_w, r4, d4, d7);
877 __ vldm(db_w, r4, d0, d3);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000878
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000879 __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8));
880 __ vstm(db_w, r4, d0, d5);
881 __ vstm(db_w, r4, d6, d7);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000882
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000883 __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4));
884 __ vldm(db_w, r4, s4, s7);
885 __ vldm(db_w, r4, s0, s3);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000886
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000887 __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4));
888 __ vstm(db_w, r4, s0, s5);
889 __ vstm(db_w, r4, s6, s7);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000890
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000891 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000892
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000893 CodeDesc desc;
894 assm.GetCode(&desc);
895 Object* code = isolate->heap()->CreateCode(
896 desc,
897 Code::ComputeFlags(Code::STUB),
898 Handle<Code>())->ToObjectChecked();
899 CHECK(code->IsCode());
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000900#ifdef DEBUG
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000901 Code::cast(code)->Print();
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000902#endif
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000903 F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
904 d.a = 1.1;
905 d.b = 2.2;
906 d.c = 3.3;
907 d.d = 4.4;
908 d.e = 5.5;
909 d.f = 6.6;
910 d.g = 7.7;
911 d.h = 8.8;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000912
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000913 f.a = 1.0;
914 f.b = 2.0;
915 f.c = 3.0;
916 f.d = 4.0;
917 f.e = 5.0;
918 f.f = 6.0;
919 f.g = 7.0;
920 f.h = 8.0;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000921
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000922 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
923 USE(dummy);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000924
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000925 CHECK_EQ(7.7, d.a);
926 CHECK_EQ(8.8, d.b);
927 CHECK_EQ(1.1, d.c);
928 CHECK_EQ(2.2, d.d);
929 CHECK_EQ(3.3, d.e);
930 CHECK_EQ(4.4, d.f);
931 CHECK_EQ(5.5, d.g);
932 CHECK_EQ(6.6, d.h);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000933
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000934 CHECK_EQ(7.0, f.a);
935 CHECK_EQ(8.0, f.b);
936 CHECK_EQ(1.0, f.c);
937 CHECK_EQ(2.0, f.d);
938 CHECK_EQ(3.0, f.e);
939 CHECK_EQ(4.0, f.f);
940 CHECK_EQ(5.0, f.g);
941 CHECK_EQ(6.0, f.h);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000942}
943
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000944
945TEST(11) {
946 // Test instructions using the carry flag.
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000947 CcTest::InitializeVM();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000948 Isolate* isolate = Isolate::Current();
949 HandleScope scope(isolate);
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000950
951 typedef struct {
952 int32_t a;
953 int32_t b;
954 int32_t c;
955 int32_t d;
956 } I;
957 I i;
958
959 i.a = 0xabcd0001;
960 i.b = 0xabcd0000;
961
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000962 Assembler assm(isolate, NULL, 0);
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000963
964 // Test HeapObject untagging.
965 __ ldr(r1, MemOperand(r0, OFFSET_OF(I, a)));
966 __ mov(r1, Operand(r1, ASR, 1), SetCC);
967 __ adc(r1, r1, Operand(r1), LeaveCC, cs);
968 __ str(r1, MemOperand(r0, OFFSET_OF(I, a)));
969
970 __ ldr(r2, MemOperand(r0, OFFSET_OF(I, b)));
971 __ mov(r2, Operand(r2, ASR, 1), SetCC);
972 __ adc(r2, r2, Operand(r2), LeaveCC, cs);
973 __ str(r2, MemOperand(r0, OFFSET_OF(I, b)));
974
975 // Test corner cases.
976 __ mov(r1, Operand(0xffffffff));
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000977 __ mov(r2, Operand::Zero());
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000978 __ mov(r3, Operand(r1, ASR, 1), SetCC); // Set the carry.
979 __ adc(r3, r1, Operand(r2));
980 __ str(r3, MemOperand(r0, OFFSET_OF(I, c)));
981
982 __ mov(r1, Operand(0xffffffff));
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000983 __ mov(r2, Operand::Zero());
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000984 __ mov(r3, Operand(r2, ASR, 1), SetCC); // Unset the carry.
985 __ adc(r3, r1, Operand(r2));
986 __ str(r3, MemOperand(r0, OFFSET_OF(I, d)));
987
988 __ mov(pc, Operand(lr));
989
990 CodeDesc desc;
991 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000992 Object* code = isolate->heap()->CreateCode(
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000993 desc,
994 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000995 Handle<Code>())->ToObjectChecked();
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000996 CHECK(code->IsCode());
997#ifdef DEBUG
998 Code::cast(code)->Print();
999#endif
1000 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1001 Object* dummy = CALL_GENERATED_CODE(f, &i, 0, 0, 0, 0);
1002 USE(dummy);
1003
1004 CHECK_EQ(0xabcd0001, i.a);
1005 CHECK_EQ(static_cast<int32_t>(0xabcd0000) >> 1, i.b);
1006 CHECK_EQ(0x00000000, i.c);
1007 CHECK_EQ(0xffffffff, i.d);
1008}
1009
yangguo@chromium.org80c42ed2011-08-31 09:03:56 +00001010
1011TEST(12) {
1012 // Test chaining of label usages within instructions (issue 1644).
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001013 CcTest::InitializeVM();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001014 Isolate* isolate = Isolate::Current();
1015 HandleScope scope(isolate);
yangguo@chromium.org80c42ed2011-08-31 09:03:56 +00001016
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001017 Assembler assm(isolate, NULL, 0);
yangguo@chromium.org80c42ed2011-08-31 09:03:56 +00001018 Label target;
1019 __ b(eq, &target);
1020 __ b(ne, &target);
1021 __ bind(&target);
1022 __ nop();
1023}
1024
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001025
1026TEST(13) {
1027 // Test VFP instructions using registers d16-d31.
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001028 CcTest::InitializeVM();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001029 Isolate* isolate = Isolate::Current();
1030 HandleScope scope(isolate);
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001031
1032 if (!CpuFeatures::IsSupported(VFP32DREGS)) {
1033 return;
1034 }
1035
1036 typedef struct {
1037 double a;
1038 double b;
1039 double c;
1040 double x;
1041 double y;
1042 double z;
1043 double i;
1044 double j;
1045 double k;
1046 } T;
1047 T t;
1048
1049 // Create a function that accepts &t, and loads, manipulates, and stores
1050 // the doubles and floats.
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00001051 Assembler assm(isolate, NULL, 0);
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001052 Label L, C;
1053
1054
1055 if (CpuFeatures::IsSupported(VFP3)) {
ulan@chromium.org750145a2013-03-07 15:14:13 +00001056 CpuFeatureScope scope(&assm, VFP3);
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001057
1058 __ stm(db_w, sp, r4.bit() | lr.bit());
1059
1060 // Load a, b, c into d16, d17, d18.
1061 __ mov(r4, Operand(r0));
1062 __ vldr(d16, r4, OFFSET_OF(T, a));
1063 __ vldr(d17, r4, OFFSET_OF(T, b));
1064 __ vldr(d18, r4, OFFSET_OF(T, c));
1065
1066 __ vneg(d25, d16);
1067 __ vadd(d25, d25, d17);
1068 __ vsub(d25, d25, d18);
1069 __ vmul(d25, d25, d25);
1070 __ vdiv(d25, d25, d18);
1071
1072 __ vmov(d16, d25);
1073 __ vsqrt(d17, d25);
1074 __ vneg(d17, d17);
1075 __ vabs(d17, d17);
1076 __ vmla(d18, d16, d17);
1077
1078 // Store d16, d17, d18 into a, b, c.
1079 __ mov(r4, Operand(r0));
1080 __ vstr(d16, r4, OFFSET_OF(T, a));
1081 __ vstr(d17, r4, OFFSET_OF(T, b));
1082 __ vstr(d18, r4, OFFSET_OF(T, c));
1083
1084 // Load x, y, z into d29-d31.
1085 __ add(r4, r0, Operand(OFFSET_OF(T, x)));
1086 __ vldm(ia_w, r4, d29, d31);
1087
1088 // Swap d29 and d30 via r registers.
1089 __ vmov(r1, r2, d29);
1090 __ vmov(d29, d30);
1091 __ vmov(d30, r1, r2);
1092
1093 // Convert to and from integer.
1094 __ vcvt_s32_f64(s1, d31);
1095 __ vcvt_f64_u32(d31, s1);
1096
1097 // Store d29-d31 into x, y, z.
1098 __ add(r4, r0, Operand(OFFSET_OF(T, x)));
1099 __ vstm(ia_w, r4, d29, d31);
1100
1101 // Move constants into d20, d21, d22 and store into i, j, k.
1102 __ vmov(d20, 14.7610017472335499);
1103 __ vmov(d21, 16.0);
1104 __ mov(r1, Operand(372106121));
1105 __ mov(r2, Operand(1079146608));
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +00001106 __ vmov(d22, VmovIndexLo, r1);
1107 __ vmov(d22, VmovIndexHi, r2);
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001108 __ add(r4, r0, Operand(OFFSET_OF(T, i)));
1109 __ vstm(ia_w, r4, d20, d22);
1110
1111 __ ldm(ia_w, sp, r4.bit() | pc.bit());
1112
1113 CodeDesc desc;
1114 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00001115 Object* code = isolate->heap()->CreateCode(
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001116 desc,
1117 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00001118 Handle<Code>())->ToObjectChecked();
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001119 CHECK(code->IsCode());
1120#ifdef DEBUG
1121 Code::cast(code)->Print();
1122#endif
1123 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1124 t.a = 1.5;
1125 t.b = 2.75;
1126 t.c = 17.17;
1127 t.x = 1.5;
1128 t.y = 2.75;
1129 t.z = 17.17;
1130 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1131 USE(dummy);
1132 CHECK_EQ(14.7610017472335499, t.a);
1133 CHECK_EQ(3.84200491244266251, t.b);
1134 CHECK_EQ(73.8818412254460241, t.c);
1135 CHECK_EQ(2.75, t.x);
1136 CHECK_EQ(1.5, t.y);
1137 CHECK_EQ(17.0, t.z);
1138 CHECK_EQ(14.7610017472335499, t.i);
1139 CHECK_EQ(16.0, t.j);
1140 CHECK_EQ(73.8818412254460241, t.k);
1141 }
1142}
1143
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001144
1145TEST(14) {
1146 // Test the VFP Canonicalized Nan mode.
1147 CcTest::InitializeVM();
1148 Isolate* isolate = Isolate::Current();
1149 HandleScope scope(isolate);
1150
1151 typedef struct {
1152 double left;
1153 double right;
1154 double add_result;
1155 double sub_result;
1156 double mul_result;
1157 double div_result;
1158 } T;
1159 T t;
1160
1161 // Create a function that makes the four basic operations.
1162 Assembler assm(isolate, NULL, 0);
1163
1164 // Ensure FPSCR state (as JSEntryStub does).
1165 Label fpscr_done;
1166 __ vmrs(r1);
1167 __ tst(r1, Operand(kVFPDefaultNaNModeControlBit));
1168 __ b(ne, &fpscr_done);
1169 __ orr(r1, r1, Operand(kVFPDefaultNaNModeControlBit));
1170 __ vmsr(r1);
1171 __ bind(&fpscr_done);
1172
1173 __ vldr(d0, r0, OFFSET_OF(T, left));
1174 __ vldr(d1, r0, OFFSET_OF(T, right));
1175 __ vadd(d2, d0, d1);
1176 __ vstr(d2, r0, OFFSET_OF(T, add_result));
1177 __ vsub(d2, d0, d1);
1178 __ vstr(d2, r0, OFFSET_OF(T, sub_result));
1179 __ vmul(d2, d0, d1);
1180 __ vstr(d2, r0, OFFSET_OF(T, mul_result));
1181 __ vdiv(d2, d0, d1);
1182 __ vstr(d2, r0, OFFSET_OF(T, div_result));
1183
1184 __ mov(pc, Operand(lr));
1185
1186 CodeDesc desc;
1187 assm.GetCode(&desc);
1188 Object* code = isolate->heap()->CreateCode(
1189 desc,
1190 Code::ComputeFlags(Code::STUB),
1191 Handle<Code>())->ToObjectChecked();
1192 CHECK(code->IsCode());
1193#ifdef DEBUG
1194 Code::cast(code)->Print();
1195#endif
1196 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1197 t.left = BitCast<double>(kHoleNanInt64);
1198 t.right = 1;
1199 t.add_result = 0;
1200 t.sub_result = 0;
1201 t.mul_result = 0;
1202 t.div_result = 0;
1203 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1204 USE(dummy);
1205 const uint32_t kArmNanUpper32 = 0x7ff80000;
1206 const uint32_t kArmNanLower32 = 0x00000000;
1207#ifdef DEBUG
1208 const uint64_t kArmNanInt64 =
1209 (static_cast<uint64_t>(kArmNanUpper32) << 32) | kArmNanLower32;
1210 ASSERT(kArmNanInt64 != kHoleNanInt64);
1211#endif
1212 // With VFP2 the sign of the canonicalized Nan is undefined. So
1213 // we remove the sign bit for the upper tests.
1214 CHECK_EQ(kArmNanUpper32, (BitCast<int64_t>(t.add_result) >> 32) & 0x7fffffff);
1215 CHECK_EQ(kArmNanLower32, BitCast<int64_t>(t.add_result) & 0xffffffffu);
1216 CHECK_EQ(kArmNanUpper32, (BitCast<int64_t>(t.sub_result) >> 32) & 0x7fffffff);
1217 CHECK_EQ(kArmNanLower32, BitCast<int64_t>(t.sub_result) & 0xffffffffu);
1218 CHECK_EQ(kArmNanUpper32, (BitCast<int64_t>(t.mul_result) >> 32) & 0x7fffffff);
1219 CHECK_EQ(kArmNanLower32, BitCast<int64_t>(t.mul_result) & 0xffffffffu);
1220 CHECK_EQ(kArmNanUpper32, (BitCast<int64_t>(t.div_result) >> 32) & 0x7fffffff);
1221 CHECK_EQ(kArmNanLower32, BitCast<int64_t>(t.div_result) & 0xffffffffu);
1222}
1223
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001224#undef __