blob: 5cb4ab3238e6049b644e8521189487cadf975d60 [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
28#include "v8.h"
29
30#include "disassembler.h"
31#include "factory.h"
ager@chromium.org3a37e9b2009-04-27 09:26:21 +000032#include "arm/simulator-arm.h"
33#include "arm/assembler-arm-inl.h"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000034#include "cctest.h"
35
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000036using namespace v8::internal;
37
38
39// Define these function prototypes to match JSEntryFunction in execution.cc.
ager@chromium.orga1645e22009-09-09 19:27:10 +000040typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
41typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +000042typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4);
43typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000044
45
46static v8::Persistent<v8::Context> env;
47
48
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000049static void InitializeVM() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000050 if (env.IsEmpty()) {
51 env = v8::Context::New();
52 }
53}
54
55
56#define __ assm.
57
58TEST(0) {
59 InitializeVM();
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000060 Isolate* isolate = Isolate::Current();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000061 HandleScope scope(isolate);
62
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000063 Assembler assm(isolate, NULL, 0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000064
65 __ add(r0, r0, Operand(r1));
66 __ mov(pc, Operand(lr));
67
68 CodeDesc desc;
69 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000070 Object* code = isolate->heap()->CreateCode(
lrn@chromium.org303ada72010-10-27 09:33:13 +000071 desc,
72 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000073 Handle<Code>())->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000074 CHECK(code->IsCode());
75#ifdef DEBUG
76 Code::cast(code)->Print();
77#endif
78 F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
79 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 3, 4, 0, 0, 0));
80 ::printf("f() = %d\n", res);
81 CHECK_EQ(7, res);
82}
83
84
85TEST(1) {
86 InitializeVM();
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000087 Isolate* isolate = Isolate::Current();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000088 HandleScope scope(isolate);
89
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000090 Assembler assm(isolate, NULL, 0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000091 Label L, C;
92
93 __ mov(r1, Operand(r0));
jkummerow@chromium.org59297c72013-01-09 16:32:23 +000094 __ mov(r0, Operand::Zero());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000095 __ b(&C);
96
97 __ bind(&L);
98 __ add(r0, r0, Operand(r1));
99 __ sub(r1, r1, Operand(1));
100
101 __ bind(&C);
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000102 __ teq(r1, Operand::Zero());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000103 __ b(ne, &L);
104 __ mov(pc, Operand(lr));
105
106 CodeDesc desc;
107 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000108 Object* code = isolate->heap()->CreateCode(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000109 desc,
110 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000111 Handle<Code>())->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000112 CHECK(code->IsCode());
113#ifdef DEBUG
114 Code::cast(code)->Print();
115#endif
116 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
117 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 100, 0, 0, 0, 0));
118 ::printf("f() = %d\n", res);
119 CHECK_EQ(5050, res);
120}
121
122
123TEST(2) {
124 InitializeVM();
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000125 Isolate* isolate = Isolate::Current();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000126 HandleScope scope(isolate);
127
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000128 Assembler assm(isolate, NULL, 0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000129 Label L, C;
130
131 __ mov(r1, Operand(r0));
132 __ mov(r0, Operand(1));
133 __ b(&C);
134
135 __ bind(&L);
136 __ mul(r0, r1, r0);
137 __ sub(r1, r1, Operand(1));
138
139 __ bind(&C);
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000140 __ teq(r1, Operand::Zero());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000141 __ b(ne, &L);
142 __ mov(pc, Operand(lr));
143
144 // some relocated stuff here, not executed
145 __ RecordComment("dead code, just testing relocations");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000146 __ mov(r0, Operand(FACTORY->true_value()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000147 __ RecordComment("dead code, just testing immediate operands");
148 __ mov(r0, Operand(-1));
149 __ mov(r0, Operand(0xFF000000));
150 __ mov(r0, Operand(0xF0F0F0F0));
151 __ mov(r0, Operand(0xFFF0FFFF));
152
153 CodeDesc desc;
154 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000155 Object* code = isolate->heap()->CreateCode(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000156 desc,
157 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000158 Handle<Code>())->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000159 CHECK(code->IsCode());
160#ifdef DEBUG
161 Code::cast(code)->Print();
162#endif
163 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
164 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 10, 0, 0, 0, 0));
165 ::printf("f() = %d\n", res);
166 CHECK_EQ(3628800, res);
167}
168
169
170TEST(3) {
171 InitializeVM();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000172 Isolate* isolate = Isolate::Current();
173 HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000174
175 typedef struct {
176 int i;
177 char c;
178 int16_t s;
179 } T;
180 T t;
181
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000182 Assembler assm(isolate, NULL, 0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000183 Label L, C;
184
185 __ mov(ip, Operand(sp));
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000186 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000187 __ sub(fp, ip, Operand(4));
188 __ mov(r4, Operand(r0));
189 __ ldr(r0, MemOperand(r4, OFFSET_OF(T, i)));
190 __ mov(r2, Operand(r0, ASR, 1));
191 __ str(r2, MemOperand(r4, OFFSET_OF(T, i)));
192 __ ldrsb(r2, MemOperand(r4, OFFSET_OF(T, c)));
193 __ add(r0, r2, Operand(r0));
194 __ mov(r2, Operand(r2, LSL, 2));
195 __ strb(r2, MemOperand(r4, OFFSET_OF(T, c)));
196 __ ldrsh(r2, MemOperand(r4, OFFSET_OF(T, s)));
197 __ add(r0, r2, Operand(r0));
198 __ mov(r2, Operand(r2, ASR, 3));
199 __ strh(r2, MemOperand(r4, OFFSET_OF(T, s)));
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000200 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000201
202 CodeDesc desc;
203 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000204 Object* code = isolate->heap()->CreateCode(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000205 desc,
206 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000207 Handle<Code>())->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000208 CHECK(code->IsCode());
209#ifdef DEBUG
210 Code::cast(code)->Print();
211#endif
212 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
213 t.i = 100000;
214 t.c = 10;
215 t.s = 1000;
216 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0));
217 ::printf("f() = %d\n", res);
218 CHECK_EQ(101010, res);
219 CHECK_EQ(100000/2, t.i);
220 CHECK_EQ(10*4, t.c);
221 CHECK_EQ(1000/8, t.s);
222}
223
224
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000225TEST(4) {
226 // Test the VFP floating point instructions.
227 InitializeVM();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000228 Isolate* isolate = Isolate::Current();
229 HandleScope scope(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000230
231 typedef struct {
232 double a;
233 double b;
234 double c;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000235 double d;
236 double e;
237 double f;
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000238 double g;
239 double h;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000240 int i;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000241 double m;
242 double n;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000243 float x;
244 float y;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000245 } T;
246 T t;
247
248 // Create a function that accepts &t, and loads, manipulates, and stores
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000249 // the doubles and floats.
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000250 Assembler assm(isolate, NULL, 0);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000251 Label L, C;
252
253
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000254 if (CpuFeatures::IsSupported(VFP3)) {
ulan@chromium.org750145a2013-03-07 15:14:13 +0000255 CpuFeatureScope scope(&assm, VFP3);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000256
257 __ mov(ip, Operand(sp));
258 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
259 __ sub(fp, ip, Operand(4));
260
261 __ mov(r4, Operand(r0));
262 __ vldr(d6, r4, OFFSET_OF(T, a));
263 __ vldr(d7, r4, OFFSET_OF(T, b));
264 __ vadd(d5, d6, d7);
265 __ vstr(d5, r4, OFFSET_OF(T, c));
266
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000267 __ vmla(d5, d6, d7);
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000268 __ vmls(d5, d5, d6);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000269
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000270 __ vmov(r2, r3, d5);
271 __ vmov(d4, r2, r3);
272 __ vstr(d4, r4, OFFSET_OF(T, b));
273
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000274 // Load t.x and t.y, switch values, and store back to the struct.
275 __ vldr(s0, r4, OFFSET_OF(T, x));
276 __ vldr(s31, r4, OFFSET_OF(T, y));
277 __ vmov(s16, s0);
278 __ vmov(s0, s31);
279 __ vmov(s31, s16);
280 __ vstr(s0, r4, OFFSET_OF(T, x));
281 __ vstr(s31, r4, OFFSET_OF(T, y));
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000282
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000283 // Move a literal into a register that can be encoded in the instruction.
284 __ vmov(d4, 1.0);
285 __ vstr(d4, r4, OFFSET_OF(T, e));
286
287 // Move a literal into a register that requires 64 bits to encode.
288 // 0x3ff0000010000000 = 1.000000059604644775390625
289 __ vmov(d4, 1.000000059604644775390625);
290 __ vstr(d4, r4, OFFSET_OF(T, d));
291
292 // Convert from floating point to integer.
293 __ vmov(d4, 2.0);
294 __ vcvt_s32_f64(s31, d4);
295 __ vstr(s31, r4, OFFSET_OF(T, i));
296
297 // Convert from integer to floating point.
298 __ mov(lr, Operand(42));
299 __ vmov(s31, lr);
300 __ vcvt_f64_s32(d4, s31);
301 __ vstr(d4, r4, OFFSET_OF(T, f));
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000302
303 // Test vabs.
304 __ vldr(d1, r4, OFFSET_OF(T, g));
305 __ vabs(d0, d1);
306 __ vstr(d0, r4, OFFSET_OF(T, g));
307 __ vldr(d2, r4, OFFSET_OF(T, h));
308 __ vabs(d0, d2);
309 __ vstr(d0, r4, OFFSET_OF(T, h));
310
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000311 // Test vneg.
312 __ vldr(d1, r4, OFFSET_OF(T, m));
313 __ vneg(d0, d1);
314 __ vstr(d0, r4, OFFSET_OF(T, m));
315 __ vldr(d1, r4, OFFSET_OF(T, n));
316 __ vneg(d0, d1);
317 __ vstr(d0, r4, OFFSET_OF(T, n));
318
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000319 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
320
321 CodeDesc desc;
322 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000323 Object* code = isolate->heap()->CreateCode(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000324 desc,
325 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000326 Handle<Code>())->ToObjectChecked();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000327 CHECK(code->IsCode());
328#ifdef DEBUG
329 Code::cast(code)->Print();
330#endif
331 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
332 t.a = 1.5;
333 t.b = 2.75;
334 t.c = 17.17;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000335 t.d = 0.0;
336 t.e = 0.0;
337 t.f = 0.0;
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000338 t.g = -2718.2818;
339 t.h = 31415926.5;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000340 t.i = 0;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000341 t.m = -2718.2818;
342 t.n = 123.456;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000343 t.x = 4.5;
344 t.y = 9.0;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000345 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
346 USE(dummy);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000347 CHECK_EQ(4.5, t.y);
348 CHECK_EQ(9.0, t.x);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000349 CHECK_EQ(-123.456, t.n);
350 CHECK_EQ(2718.2818, t.m);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000351 CHECK_EQ(2, t.i);
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000352 CHECK_EQ(2718.2818, t.g);
353 CHECK_EQ(31415926.5, t.h);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000354 CHECK_EQ(42.0, t.f);
355 CHECK_EQ(1.0, t.e);
356 CHECK_EQ(1.000000059604644775390625, t.d);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000357 CHECK_EQ(4.25, t.c);
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000358 CHECK_EQ(-4.1875, t.b);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000359 CHECK_EQ(1.5, t.a);
360 }
361}
362
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000363
364TEST(5) {
365 // Test the ARMv7 bitfield instructions.
366 InitializeVM();
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000367 Isolate* isolate = Isolate::Current();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000368 HandleScope scope(isolate);
369
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000370 Assembler assm(isolate, NULL, 0);
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000371
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000372 if (CpuFeatures::IsSupported(ARMv7)) {
ulan@chromium.org750145a2013-03-07 15:14:13 +0000373 CpuFeatureScope scope(&assm, ARMv7);
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000374 // On entry, r0 = 0xAAAAAAAA = 0b10..10101010.
375 __ ubfx(r0, r0, 1, 12); // 0b00..010101010101 = 0x555
376 __ sbfx(r0, r0, 0, 5); // 0b11..111111110101 = -11
377 __ bfc(r0, 1, 3); // 0b11..111111110001 = -15
378 __ mov(r1, Operand(7));
379 __ bfi(r0, r1, 3, 3); // 0b11..111111111001 = -7
380 __ mov(pc, Operand(lr));
381
382 CodeDesc desc;
383 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000384 Object* code = isolate->heap()->CreateCode(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000385 desc,
386 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000387 Handle<Code>())->ToObjectChecked();
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000388 CHECK(code->IsCode());
389#ifdef DEBUG
390 Code::cast(code)->Print();
391#endif
392 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
393 int res = reinterpret_cast<int>(
394 CALL_GENERATED_CODE(f, 0xAAAAAAAA, 0, 0, 0, 0));
395 ::printf("f() = %d\n", res);
396 CHECK_EQ(-7, res);
397 }
398}
399
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000400
401TEST(6) {
402 // Test saturating instructions.
403 InitializeVM();
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000404 Isolate* isolate = Isolate::Current();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000405 HandleScope scope(isolate);
406
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000407 Assembler assm(isolate, NULL, 0);
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000408
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000409 if (CpuFeatures::IsSupported(ARMv7)) {
ulan@chromium.org750145a2013-03-07 15:14:13 +0000410 CpuFeatureScope scope(&assm, ARMv7);
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000411 __ usat(r1, 8, Operand(r0)); // Sat 0xFFFF to 0-255 = 0xFF.
412 __ usat(r2, 12, Operand(r0, ASR, 9)); // Sat (0xFFFF>>9) to 0-4095 = 0x7F.
413 __ usat(r3, 1, Operand(r0, LSL, 16)); // Sat (0xFFFF<<16) to 0-1 = 0x0.
414 __ add(r0, r1, Operand(r2));
415 __ add(r0, r0, Operand(r3));
416 __ mov(pc, Operand(lr));
417
418 CodeDesc desc;
419 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000420 Object* code = isolate->heap()->CreateCode(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000421 desc,
422 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000423 Handle<Code>())->ToObjectChecked();
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000424 CHECK(code->IsCode());
425#ifdef DEBUG
426 Code::cast(code)->Print();
427#endif
428 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
429 int res = reinterpret_cast<int>(
430 CALL_GENERATED_CODE(f, 0xFFFF, 0, 0, 0, 0));
431 ::printf("f() = %d\n", res);
432 CHECK_EQ(382, res);
433 }
434}
435
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000436
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000437enum VCVTTypes {
438 s32_f64,
439 u32_f64
440};
441
442static void TestRoundingMode(VCVTTypes types,
443 VFPRoundingMode mode,
444 double value,
445 int expected,
446 bool expected_exception = false) {
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000447 InitializeVM();
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000448 Isolate* isolate = Isolate::Current();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000449 HandleScope scope(isolate);
450
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000451 Assembler assm(isolate, NULL, 0);
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000452
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000453 if (CpuFeatures::IsSupported(VFP3)) {
ulan@chromium.org750145a2013-03-07 15:14:13 +0000454 CpuFeatureScope scope(&assm, VFP3);
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000455
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000456 Label wrong_exception;
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000457
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000458 __ vmrs(r1);
459 // Set custom FPSCR.
460 __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask));
461 __ orr(r2, r2, Operand(mode));
462 __ vmsr(r2);
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000463
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000464 // Load value, convert, and move back result to r0 if everything went well.
465 __ vmov(d1, value);
466 switch (types) {
467 case s32_f64:
468 __ vcvt_s32_f64(s0, d1, kFPSCRRounding);
469 break;
470
471 case u32_f64:
472 __ vcvt_u32_f64(s0, d1, kFPSCRRounding);
473 break;
474
475 default:
476 UNREACHABLE();
477 break;
478 }
479 // Check for vfp exceptions
480 __ vmrs(r2);
481 __ tst(r2, Operand(kVFPExceptionMask));
482 // Check that we behaved as expected.
483 __ b(&wrong_exception,
484 expected_exception ? eq : ne);
485 // There was no exception. Retrieve the result and return.
486 __ vmov(r0, s0);
487 __ mov(pc, Operand(lr));
488
489 // The exception behaviour is not what we expected.
490 // Load a special value and return.
491 __ bind(&wrong_exception);
492 __ mov(r0, Operand(11223344));
493 __ mov(pc, Operand(lr));
494
495 CodeDesc desc;
496 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000497 Object* code = isolate->heap()->CreateCode(
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000498 desc,
499 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000500 Handle<Code>())->ToObjectChecked();
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000501 CHECK(code->IsCode());
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000502#ifdef DEBUG
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000503 Code::cast(code)->Print();
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000504#endif
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000505 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
506 int res = reinterpret_cast<int>(
507 CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
508 ::printf("res = %d\n", res);
509 CHECK_EQ(expected, res);
510 }
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000511}
512
513
514TEST(7) {
515 // Test vfp rounding modes.
516
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000517 // s32_f64 (double to integer).
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000518
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000519 TestRoundingMode(s32_f64, RN, 0, 0);
520 TestRoundingMode(s32_f64, RN, 0.5, 0);
521 TestRoundingMode(s32_f64, RN, -0.5, 0);
522 TestRoundingMode(s32_f64, RN, 1.5, 2);
523 TestRoundingMode(s32_f64, RN, -1.5, -2);
524 TestRoundingMode(s32_f64, RN, 123.7, 124);
525 TestRoundingMode(s32_f64, RN, -123.7, -124);
526 TestRoundingMode(s32_f64, RN, 123456.2, 123456);
527 TestRoundingMode(s32_f64, RN, -123456.2, -123456);
528 TestRoundingMode(s32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
529 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.49), kMaxInt);
530 TestRoundingMode(s32_f64, RN, (kMaxInt + 1.0), kMaxInt, true);
531 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.5), kMaxInt, true);
532 TestRoundingMode(s32_f64, RN, static_cast<double>(kMinInt), kMinInt);
533 TestRoundingMode(s32_f64, RN, (kMinInt - 0.5), kMinInt);
534 TestRoundingMode(s32_f64, RN, (kMinInt - 1.0), kMinInt, true);
535 TestRoundingMode(s32_f64, RN, (kMinInt - 0.51), kMinInt, true);
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000536
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000537 TestRoundingMode(s32_f64, RM, 0, 0);
538 TestRoundingMode(s32_f64, RM, 0.5, 0);
539 TestRoundingMode(s32_f64, RM, -0.5, -1);
540 TestRoundingMode(s32_f64, RM, 123.7, 123);
541 TestRoundingMode(s32_f64, RM, -123.7, -124);
542 TestRoundingMode(s32_f64, RM, 123456.2, 123456);
543 TestRoundingMode(s32_f64, RM, -123456.2, -123457);
544 TestRoundingMode(s32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
545 TestRoundingMode(s32_f64, RM, (kMaxInt + 0.5), kMaxInt);
546 TestRoundingMode(s32_f64, RM, (kMaxInt + 1.0), kMaxInt, true);
547 TestRoundingMode(s32_f64, RM, static_cast<double>(kMinInt), kMinInt);
548 TestRoundingMode(s32_f64, RM, (kMinInt - 0.5), kMinInt, true);
549 TestRoundingMode(s32_f64, RM, (kMinInt + 0.5), kMinInt);
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000550
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000551 TestRoundingMode(s32_f64, RZ, 0, 0);
552 TestRoundingMode(s32_f64, RZ, 0.5, 0);
553 TestRoundingMode(s32_f64, RZ, -0.5, 0);
554 TestRoundingMode(s32_f64, RZ, 123.7, 123);
555 TestRoundingMode(s32_f64, RZ, -123.7, -123);
556 TestRoundingMode(s32_f64, RZ, 123456.2, 123456);
557 TestRoundingMode(s32_f64, RZ, -123456.2, -123456);
558 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
559 TestRoundingMode(s32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
560 TestRoundingMode(s32_f64, RZ, (kMaxInt + 1.0), kMaxInt, true);
561 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMinInt), kMinInt);
562 TestRoundingMode(s32_f64, RZ, (kMinInt - 0.5), kMinInt);
563 TestRoundingMode(s32_f64, RZ, (kMinInt - 1.0), kMinInt, true);
564
565
566 // u32_f64 (double to integer).
567
568 // Negative values.
569 TestRoundingMode(u32_f64, RN, -0.5, 0);
570 TestRoundingMode(u32_f64, RN, -123456.7, 0, true);
571 TestRoundingMode(u32_f64, RN, static_cast<double>(kMinInt), 0, true);
572 TestRoundingMode(u32_f64, RN, kMinInt - 1.0, 0, true);
573
574 TestRoundingMode(u32_f64, RM, -0.5, 0, true);
575 TestRoundingMode(u32_f64, RM, -123456.7, 0, true);
576 TestRoundingMode(u32_f64, RM, static_cast<double>(kMinInt), 0, true);
577 TestRoundingMode(u32_f64, RM, kMinInt - 1.0, 0, true);
578
579 TestRoundingMode(u32_f64, RZ, -0.5, 0);
580 TestRoundingMode(u32_f64, RZ, -123456.7, 0, true);
581 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMinInt), 0, true);
582 TestRoundingMode(u32_f64, RZ, kMinInt - 1.0, 0, true);
583
584 // Positive values.
585 // kMaxInt is the maximum *signed* integer: 0x7fffffff.
586 static const uint32_t kMaxUInt = 0xffffffffu;
587 TestRoundingMode(u32_f64, RZ, 0, 0);
588 TestRoundingMode(u32_f64, RZ, 0.5, 0);
589 TestRoundingMode(u32_f64, RZ, 123.7, 123);
590 TestRoundingMode(u32_f64, RZ, 123456.2, 123456);
591 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
592 TestRoundingMode(u32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
593 TestRoundingMode(u32_f64, RZ, (kMaxInt + 1.0),
594 static_cast<uint32_t>(kMaxInt) + 1);
595 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 0.5), kMaxUInt);
596 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 1.0), kMaxUInt, true);
597
598 TestRoundingMode(u32_f64, RM, 0, 0);
599 TestRoundingMode(u32_f64, RM, 0.5, 0);
600 TestRoundingMode(u32_f64, RM, 123.7, 123);
601 TestRoundingMode(u32_f64, RM, 123456.2, 123456);
602 TestRoundingMode(u32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
603 TestRoundingMode(u32_f64, RM, (kMaxInt + 0.5), kMaxInt);
604 TestRoundingMode(u32_f64, RM, (kMaxInt + 1.0),
605 static_cast<uint32_t>(kMaxInt) + 1);
606 TestRoundingMode(u32_f64, RM, (kMaxUInt + 0.5), kMaxUInt);
607 TestRoundingMode(u32_f64, RM, (kMaxUInt + 1.0), kMaxUInt, true);
608
609 TestRoundingMode(u32_f64, RN, 0, 0);
610 TestRoundingMode(u32_f64, RN, 0.5, 0);
611 TestRoundingMode(u32_f64, RN, 1.5, 2);
612 TestRoundingMode(u32_f64, RN, 123.7, 124);
613 TestRoundingMode(u32_f64, RN, 123456.2, 123456);
614 TestRoundingMode(u32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
615 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.49), kMaxInt);
616 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.5),
617 static_cast<uint32_t>(kMaxInt) + 1);
618 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.49), kMaxUInt);
619 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.5), kMaxUInt, true);
620 TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true);
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000621}
622
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000623TEST(8) {
624 // Test VFP multi load/store with ia_w.
625 InitializeVM();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000626 Isolate* isolate = Isolate::Current();
627 HandleScope scope(isolate);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000628
629 typedef struct {
630 double a;
631 double b;
632 double c;
633 double d;
634 double e;
635 double f;
636 double g;
637 double h;
638 } D;
639 D d;
640
641 typedef struct {
642 float a;
643 float b;
644 float c;
645 float d;
646 float e;
647 float f;
648 float g;
649 float h;
650 } F;
651 F f;
652
653 // Create a function that uses vldm/vstm to move some double and
654 // single precision values around in memory.
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000655 Assembler assm(isolate, NULL, 0);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000656
verwaest@chromium.orgb6d052d2012-07-27 08:03:27 +0000657 if (CpuFeatures::IsSupported(VFP2)) {
ulan@chromium.org750145a2013-03-07 15:14:13 +0000658 CpuFeatureScope scope(&assm, VFP2);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000659
660 __ mov(ip, Operand(sp));
661 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
662 __ sub(fp, ip, Operand(4));
663
664 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
665 __ vldm(ia_w, r4, d0, d3);
666 __ vldm(ia_w, r4, d4, d7);
667
668 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
669 __ vstm(ia_w, r4, d6, d7);
670 __ vstm(ia_w, r4, d0, d5);
671
672 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
673 __ vldm(ia_w, r4, s0, s3);
674 __ vldm(ia_w, r4, s4, s7);
675
676 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
677 __ vstm(ia_w, r4, s6, s7);
678 __ vstm(ia_w, r4, s0, s5);
679
680 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
681
682 CodeDesc desc;
683 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000684 Object* code = isolate->heap()->CreateCode(
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000685 desc,
686 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000687 Handle<Code>())->ToObjectChecked();
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000688 CHECK(code->IsCode());
689#ifdef DEBUG
690 Code::cast(code)->Print();
691#endif
692 F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
693 d.a = 1.1;
694 d.b = 2.2;
695 d.c = 3.3;
696 d.d = 4.4;
697 d.e = 5.5;
698 d.f = 6.6;
699 d.g = 7.7;
700 d.h = 8.8;
701
702 f.a = 1.0;
703 f.b = 2.0;
704 f.c = 3.0;
705 f.d = 4.0;
706 f.e = 5.0;
707 f.f = 6.0;
708 f.g = 7.0;
709 f.h = 8.0;
710
711 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
712 USE(dummy);
713
714 CHECK_EQ(7.7, d.a);
715 CHECK_EQ(8.8, d.b);
716 CHECK_EQ(1.1, d.c);
717 CHECK_EQ(2.2, d.d);
718 CHECK_EQ(3.3, d.e);
719 CHECK_EQ(4.4, d.f);
720 CHECK_EQ(5.5, d.g);
721 CHECK_EQ(6.6, d.h);
722
723 CHECK_EQ(7.0, f.a);
724 CHECK_EQ(8.0, f.b);
725 CHECK_EQ(1.0, f.c);
726 CHECK_EQ(2.0, f.d);
727 CHECK_EQ(3.0, f.e);
728 CHECK_EQ(4.0, f.f);
729 CHECK_EQ(5.0, f.g);
730 CHECK_EQ(6.0, f.h);
731 }
732}
733
734
735TEST(9) {
736 // Test VFP multi load/store with ia.
737 InitializeVM();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000738 Isolate* isolate = Isolate::Current();
739 HandleScope scope(isolate);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000740
741 typedef struct {
742 double a;
743 double b;
744 double c;
745 double d;
746 double e;
747 double f;
748 double g;
749 double h;
750 } D;
751 D d;
752
753 typedef struct {
754 float a;
755 float b;
756 float c;
757 float d;
758 float e;
759 float f;
760 float g;
761 float h;
762 } F;
763 F f;
764
765 // Create a function that uses vldm/vstm to move some double and
766 // single precision values around in memory.
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000767 Assembler assm(isolate, NULL, 0);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000768
verwaest@chromium.orgb6d052d2012-07-27 08:03:27 +0000769 if (CpuFeatures::IsSupported(VFP2)) {
ulan@chromium.org750145a2013-03-07 15:14:13 +0000770 CpuFeatureScope scope(&assm, VFP2);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000771
772 __ mov(ip, Operand(sp));
773 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
774 __ sub(fp, ip, Operand(4));
775
776 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
777 __ vldm(ia, r4, d0, d3);
778 __ add(r4, r4, Operand(4 * 8));
779 __ vldm(ia, r4, d4, d7);
780
781 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
782 __ vstm(ia, r4, d6, d7);
783 __ add(r4, r4, Operand(2 * 8));
784 __ vstm(ia, r4, d0, d5);
785
786 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
787 __ vldm(ia, r4, s0, s3);
788 __ add(r4, r4, Operand(4 * 4));
789 __ vldm(ia, r4, s4, s7);
790
791 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
792 __ vstm(ia, r4, s6, s7);
793 __ add(r4, r4, Operand(2 * 4));
794 __ vstm(ia, r4, s0, s5);
795
796 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
797
798 CodeDesc desc;
799 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000800 Object* code = isolate->heap()->CreateCode(
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000801 desc,
802 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000803 Handle<Code>())->ToObjectChecked();
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000804 CHECK(code->IsCode());
805#ifdef DEBUG
806 Code::cast(code)->Print();
807#endif
808 F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
809 d.a = 1.1;
810 d.b = 2.2;
811 d.c = 3.3;
812 d.d = 4.4;
813 d.e = 5.5;
814 d.f = 6.6;
815 d.g = 7.7;
816 d.h = 8.8;
817
818 f.a = 1.0;
819 f.b = 2.0;
820 f.c = 3.0;
821 f.d = 4.0;
822 f.e = 5.0;
823 f.f = 6.0;
824 f.g = 7.0;
825 f.h = 8.0;
826
827 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
828 USE(dummy);
829
830 CHECK_EQ(7.7, d.a);
831 CHECK_EQ(8.8, d.b);
832 CHECK_EQ(1.1, d.c);
833 CHECK_EQ(2.2, d.d);
834 CHECK_EQ(3.3, d.e);
835 CHECK_EQ(4.4, d.f);
836 CHECK_EQ(5.5, d.g);
837 CHECK_EQ(6.6, d.h);
838
839 CHECK_EQ(7.0, f.a);
840 CHECK_EQ(8.0, f.b);
841 CHECK_EQ(1.0, f.c);
842 CHECK_EQ(2.0, f.d);
843 CHECK_EQ(3.0, f.e);
844 CHECK_EQ(4.0, f.f);
845 CHECK_EQ(5.0, f.g);
846 CHECK_EQ(6.0, f.h);
847 }
848}
849
850
851TEST(10) {
852 // Test VFP multi load/store with db_w.
853 InitializeVM();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000854 Isolate* isolate = Isolate::Current();
855 HandleScope scope(isolate);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000856
857 typedef struct {
858 double a;
859 double b;
860 double c;
861 double d;
862 double e;
863 double f;
864 double g;
865 double h;
866 } D;
867 D d;
868
869 typedef struct {
870 float a;
871 float b;
872 float c;
873 float d;
874 float e;
875 float f;
876 float g;
877 float h;
878 } F;
879 F f;
880
881 // Create a function that uses vldm/vstm to move some double and
882 // single precision values around in memory.
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000883 Assembler assm(isolate, NULL, 0);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000884
verwaest@chromium.orgb6d052d2012-07-27 08:03:27 +0000885 if (CpuFeatures::IsSupported(VFP2)) {
ulan@chromium.org750145a2013-03-07 15:14:13 +0000886 CpuFeatureScope scope(&assm, VFP2);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000887
888 __ mov(ip, Operand(sp));
889 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
890 __ sub(fp, ip, Operand(4));
891
892 __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8));
893 __ vldm(db_w, r4, d4, d7);
894 __ vldm(db_w, r4, d0, d3);
895
896 __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8));
897 __ vstm(db_w, r4, d0, d5);
898 __ vstm(db_w, r4, d6, d7);
899
900 __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4));
901 __ vldm(db_w, r4, s4, s7);
902 __ vldm(db_w, r4, s0, s3);
903
904 __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4));
905 __ vstm(db_w, r4, s0, s5);
906 __ vstm(db_w, r4, s6, s7);
907
908 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
909
910 CodeDesc desc;
911 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000912 Object* code = isolate->heap()->CreateCode(
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000913 desc,
914 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000915 Handle<Code>())->ToObjectChecked();
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000916 CHECK(code->IsCode());
917#ifdef DEBUG
918 Code::cast(code)->Print();
919#endif
920 F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
921 d.a = 1.1;
922 d.b = 2.2;
923 d.c = 3.3;
924 d.d = 4.4;
925 d.e = 5.5;
926 d.f = 6.6;
927 d.g = 7.7;
928 d.h = 8.8;
929
930 f.a = 1.0;
931 f.b = 2.0;
932 f.c = 3.0;
933 f.d = 4.0;
934 f.e = 5.0;
935 f.f = 6.0;
936 f.g = 7.0;
937 f.h = 8.0;
938
939 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
940 USE(dummy);
941
942 CHECK_EQ(7.7, d.a);
943 CHECK_EQ(8.8, d.b);
944 CHECK_EQ(1.1, d.c);
945 CHECK_EQ(2.2, d.d);
946 CHECK_EQ(3.3, d.e);
947 CHECK_EQ(4.4, d.f);
948 CHECK_EQ(5.5, d.g);
949 CHECK_EQ(6.6, d.h);
950
951 CHECK_EQ(7.0, f.a);
952 CHECK_EQ(8.0, f.b);
953 CHECK_EQ(1.0, f.c);
954 CHECK_EQ(2.0, f.d);
955 CHECK_EQ(3.0, f.e);
956 CHECK_EQ(4.0, f.f);
957 CHECK_EQ(5.0, f.g);
958 CHECK_EQ(6.0, f.h);
959 }
960}
961
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000962
963TEST(11) {
964 // Test instructions using the carry flag.
965 InitializeVM();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000966 Isolate* isolate = Isolate::Current();
967 HandleScope scope(isolate);
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000968
969 typedef struct {
970 int32_t a;
971 int32_t b;
972 int32_t c;
973 int32_t d;
974 } I;
975 I i;
976
977 i.a = 0xabcd0001;
978 i.b = 0xabcd0000;
979
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000980 Assembler assm(isolate, NULL, 0);
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000981
982 // Test HeapObject untagging.
983 __ ldr(r1, MemOperand(r0, OFFSET_OF(I, a)));
984 __ mov(r1, Operand(r1, ASR, 1), SetCC);
985 __ adc(r1, r1, Operand(r1), LeaveCC, cs);
986 __ str(r1, MemOperand(r0, OFFSET_OF(I, a)));
987
988 __ ldr(r2, MemOperand(r0, OFFSET_OF(I, b)));
989 __ mov(r2, Operand(r2, ASR, 1), SetCC);
990 __ adc(r2, r2, Operand(r2), LeaveCC, cs);
991 __ str(r2, MemOperand(r0, OFFSET_OF(I, b)));
992
993 // Test corner cases.
994 __ mov(r1, Operand(0xffffffff));
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000995 __ mov(r2, Operand::Zero());
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000996 __ mov(r3, Operand(r1, ASR, 1), SetCC); // Set the carry.
997 __ adc(r3, r1, Operand(r2));
998 __ str(r3, MemOperand(r0, OFFSET_OF(I, c)));
999
1000 __ mov(r1, Operand(0xffffffff));
jkummerow@chromium.org59297c72013-01-09 16:32:23 +00001001 __ mov(r2, Operand::Zero());
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00001002 __ mov(r3, Operand(r2, ASR, 1), SetCC); // Unset the carry.
1003 __ adc(r3, r1, Operand(r2));
1004 __ str(r3, MemOperand(r0, OFFSET_OF(I, d)));
1005
1006 __ mov(pc, Operand(lr));
1007
1008 CodeDesc desc;
1009 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00001010 Object* code = isolate->heap()->CreateCode(
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00001011 desc,
1012 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00001013 Handle<Code>())->ToObjectChecked();
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00001014 CHECK(code->IsCode());
1015#ifdef DEBUG
1016 Code::cast(code)->Print();
1017#endif
1018 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1019 Object* dummy = CALL_GENERATED_CODE(f, &i, 0, 0, 0, 0);
1020 USE(dummy);
1021
1022 CHECK_EQ(0xabcd0001, i.a);
1023 CHECK_EQ(static_cast<int32_t>(0xabcd0000) >> 1, i.b);
1024 CHECK_EQ(0x00000000, i.c);
1025 CHECK_EQ(0xffffffff, i.d);
1026}
1027
yangguo@chromium.org80c42ed2011-08-31 09:03:56 +00001028
1029TEST(12) {
1030 // Test chaining of label usages within instructions (issue 1644).
1031 InitializeVM();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001032 Isolate* isolate = Isolate::Current();
1033 HandleScope scope(isolate);
yangguo@chromium.org80c42ed2011-08-31 09:03:56 +00001034
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001035 Assembler assm(isolate, NULL, 0);
yangguo@chromium.org80c42ed2011-08-31 09:03:56 +00001036 Label target;
1037 __ b(eq, &target);
1038 __ b(ne, &target);
1039 __ bind(&target);
1040 __ nop();
1041}
1042
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001043
1044TEST(13) {
1045 // Test VFP instructions using registers d16-d31.
1046 InitializeVM();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001047 Isolate* isolate = Isolate::Current();
1048 HandleScope scope(isolate);
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001049
1050 if (!CpuFeatures::IsSupported(VFP32DREGS)) {
1051 return;
1052 }
1053
1054 typedef struct {
1055 double a;
1056 double b;
1057 double c;
1058 double x;
1059 double y;
1060 double z;
1061 double i;
1062 double j;
1063 double k;
1064 } T;
1065 T t;
1066
1067 // Create a function that accepts &t, and loads, manipulates, and stores
1068 // the doubles and floats.
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00001069 Assembler assm(isolate, NULL, 0);
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001070 Label L, C;
1071
1072
1073 if (CpuFeatures::IsSupported(VFP3)) {
ulan@chromium.org750145a2013-03-07 15:14:13 +00001074 CpuFeatureScope scope(&assm, VFP3);
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001075
1076 __ stm(db_w, sp, r4.bit() | lr.bit());
1077
1078 // Load a, b, c into d16, d17, d18.
1079 __ mov(r4, Operand(r0));
1080 __ vldr(d16, r4, OFFSET_OF(T, a));
1081 __ vldr(d17, r4, OFFSET_OF(T, b));
1082 __ vldr(d18, r4, OFFSET_OF(T, c));
1083
1084 __ vneg(d25, d16);
1085 __ vadd(d25, d25, d17);
1086 __ vsub(d25, d25, d18);
1087 __ vmul(d25, d25, d25);
1088 __ vdiv(d25, d25, d18);
1089
1090 __ vmov(d16, d25);
1091 __ vsqrt(d17, d25);
1092 __ vneg(d17, d17);
1093 __ vabs(d17, d17);
1094 __ vmla(d18, d16, d17);
1095
1096 // Store d16, d17, d18 into a, b, c.
1097 __ mov(r4, Operand(r0));
1098 __ vstr(d16, r4, OFFSET_OF(T, a));
1099 __ vstr(d17, r4, OFFSET_OF(T, b));
1100 __ vstr(d18, r4, OFFSET_OF(T, c));
1101
1102 // Load x, y, z into d29-d31.
1103 __ add(r4, r0, Operand(OFFSET_OF(T, x)));
1104 __ vldm(ia_w, r4, d29, d31);
1105
1106 // Swap d29 and d30 via r registers.
1107 __ vmov(r1, r2, d29);
1108 __ vmov(d29, d30);
1109 __ vmov(d30, r1, r2);
1110
1111 // Convert to and from integer.
1112 __ vcvt_s32_f64(s1, d31);
1113 __ vcvt_f64_u32(d31, s1);
1114
1115 // Store d29-d31 into x, y, z.
1116 __ add(r4, r0, Operand(OFFSET_OF(T, x)));
1117 __ vstm(ia_w, r4, d29, d31);
1118
1119 // Move constants into d20, d21, d22 and store into i, j, k.
1120 __ vmov(d20, 14.7610017472335499);
1121 __ vmov(d21, 16.0);
1122 __ mov(r1, Operand(372106121));
1123 __ mov(r2, Operand(1079146608));
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +00001124 __ vmov(d22, VmovIndexLo, r1);
1125 __ vmov(d22, VmovIndexHi, r2);
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001126 __ add(r4, r0, Operand(OFFSET_OF(T, i)));
1127 __ vstm(ia_w, r4, d20, d22);
1128
1129 __ ldm(ia_w, sp, r4.bit() | pc.bit());
1130
1131 CodeDesc desc;
1132 assm.GetCode(&desc);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00001133 Object* code = isolate->heap()->CreateCode(
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001134 desc,
1135 Code::ComputeFlags(Code::STUB),
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00001136 Handle<Code>())->ToObjectChecked();
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001137 CHECK(code->IsCode());
1138#ifdef DEBUG
1139 Code::cast(code)->Print();
1140#endif
1141 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1142 t.a = 1.5;
1143 t.b = 2.75;
1144 t.c = 17.17;
1145 t.x = 1.5;
1146 t.y = 2.75;
1147 t.z = 17.17;
1148 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1149 USE(dummy);
1150 CHECK_EQ(14.7610017472335499, t.a);
1151 CHECK_EQ(3.84200491244266251, t.b);
1152 CHECK_EQ(73.8818412254460241, t.c);
1153 CHECK_EQ(2.75, t.x);
1154 CHECK_EQ(1.5, t.y);
1155 CHECK_EQ(17.0, t.z);
1156 CHECK_EQ(14.7610017472335499, t.i);
1157 CHECK_EQ(16.0, t.j);
1158 CHECK_EQ(73.8818412254460241, t.k);
1159 }
1160}
1161
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001162#undef __