1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // 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 "src/v8.h"
29 #include "test/cctest/cctest.h"
30
31 #include "src/arm/assembler-arm-inl.h"
32 #include "src/arm/simulator-arm.h"
33 #include "src/disassembler.h"
34 #include "src/factory.h"
35 #include "src/ostreams.h"
36
37 using namespace v8::internal;
38
39
40 // Define these function prototypes to match JSEntryFunction in execution.cc.
41 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
42 typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
43 typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4);
44 typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4);
45
46
47 #define __ assm.
48
49 TEST(0) {
50 CcTest::InitializeVM();
51 Isolate* isolate = CcTest::i_isolate();
52 HandleScope scope(isolate);
53
54 Assembler assm(isolate, NULL, 0);
55
56 __ add(r0, r0, Operand(r1));
57 __ mov(pc, Operand(lr));
58
59 CodeDesc desc;
60 assm.GetCode(&desc);
61 Handle<Code> code = isolate->factory()->NewCode(
62 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
63 #ifdef DEBUG
64 OFStream os(stdout);
65 code->Print(os);
66 #endif
67 F2 f = FUNCTION_CAST<F2>(code->entry());
68 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 3, 4, 0, 0, 0));
69 ::printf("f() = %d\n", res);
70 CHECK_EQ(7, res);
71 }
72
73
74 TEST(1) {
75 CcTest::InitializeVM();
76 Isolate* isolate = CcTest::i_isolate();
77 HandleScope scope(isolate);
78
79 Assembler assm(isolate, NULL, 0);
80 Label L, C;
81
82 __ mov(r1, Operand(r0));
83 __ mov(r0, Operand::Zero());
84 __ b(&C);
85
86 __ bind(&L);
87 __ add(r0, r0, Operand(r1));
88 __ sub(r1, r1, Operand(1));
89
90 __ bind(&C);
91 __ teq(r1, Operand::Zero());
92 __ b(ne, &L);
93 __ mov(pc, Operand(lr));
94
95 CodeDesc desc;
96 assm.GetCode(&desc);
97 Handle<Code> code = isolate->factory()->NewCode(
98 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
99 #ifdef DEBUG
100 OFStream os(stdout);
101 code->Print(os);
102 #endif
103 F1 f = FUNCTION_CAST<F1>(code->entry());
104 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 100, 0, 0, 0, 0));
105 ::printf("f() = %d\n", res);
106 CHECK_EQ(5050, res);
107 }
108
109
110 TEST(2) {
111 CcTest::InitializeVM();
112 Isolate* isolate = CcTest::i_isolate();
113 HandleScope scope(isolate);
114
115 Assembler assm(isolate, NULL, 0);
116 Label L, C;
117
118 __ mov(r1, Operand(r0));
119 __ mov(r0, Operand(1));
120 __ b(&C);
121
122 __ bind(&L);
123 __ mul(r0, r1, r0);
124 __ sub(r1, r1, Operand(1));
125
126 __ bind(&C);
127 __ teq(r1, Operand::Zero());
128 __ b(ne, &L);
129 __ mov(pc, Operand(lr));
130
131 // some relocated stuff here, not executed
132 __ RecordComment("dead code, just testing relocations");
133 __ mov(r0, Operand(isolate->factory()->true_value()));
134 __ RecordComment("dead code, just testing immediate operands");
135 __ mov(r0, Operand(-1));
136 __ mov(r0, Operand(0xFF000000));
137 __ mov(r0, Operand(0xF0F0F0F0));
138 __ mov(r0, Operand(0xFFF0FFFF));
139
140 CodeDesc desc;
141 assm.GetCode(&desc);
142 Handle<Code> code = isolate->factory()->NewCode(
143 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
144 #ifdef DEBUG
145 OFStream os(stdout);
146 code->Print(os);
147 #endif
148 F1 f = FUNCTION_CAST<F1>(code->entry());
149 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 10, 0, 0, 0, 0));
150 ::printf("f() = %d\n", res);
151 CHECK_EQ(3628800, res);
152 }
153
154
155 TEST(3) {
156 CcTest::InitializeVM();
157 Isolate* isolate = CcTest::i_isolate();
158 HandleScope scope(isolate);
159
160 typedef struct {
161 int i;
162 char c;
163 int16_t s;
164 } T;
165 T t;
166
167 Assembler assm(isolate, NULL, 0);
168 Label L, C;
169
170 __ mov(ip, Operand(sp));
171 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
172 __ sub(fp, ip, Operand(4));
173 __ mov(r4, Operand(r0));
174 __ ldr(r0, MemOperand(r4, OFFSET_OF(T, i)));
175 __ mov(r2, Operand(r0, ASR, 1));
176 __ str(r2, MemOperand(r4, OFFSET_OF(T, i)));
177 __ ldrsb(r2, MemOperand(r4, OFFSET_OF(T, c)));
178 __ add(r0, r2, Operand(r0));
179 __ mov(r2, Operand(r2, LSL, 2));
180 __ strb(r2, MemOperand(r4, OFFSET_OF(T, c)));
181 __ ldrsh(r2, MemOperand(r4, OFFSET_OF(T, s)));
182 __ add(r0, r2, Operand(r0));
183 __ mov(r2, Operand(r2, ASR, 3));
184 __ strh(r2, MemOperand(r4, OFFSET_OF(T, s)));
185 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
186
187 CodeDesc desc;
188 assm.GetCode(&desc);
189 Handle<Code> code = isolate->factory()->NewCode(
190 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
191 #ifdef DEBUG
192 OFStream os(stdout);
193 code->Print(os);
194 #endif
195 F3 f = FUNCTION_CAST<F3>(code->entry());
196 t.i = 100000;
197 t.c = 10;
198 t.s = 1000;
199 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0));
200 ::printf("f() = %d\n", res);
201 CHECK_EQ(101010, res);
202 CHECK_EQ(100000/2, t.i);
203 CHECK_EQ(10*4, t.c);
204 CHECK_EQ(1000/8, t.s);
205 }
206
207
208 TEST(4) {
209 // Test the VFP floating point instructions.
210 CcTest::InitializeVM();
211 Isolate* isolate = CcTest::i_isolate();
212 HandleScope scope(isolate);
213
214 typedef struct {
215 double a;
216 double b;
217 double c;
218 double d;
219 double e;
220 double f;
221 double g;
222 double h;
223 int i;
224 double j;
225 double m;
226 double n;
227 float x;
228 float y;
229 } T;
230 T t;
231
232 // Create a function that accepts &t, and loads, manipulates, and stores
233 // the doubles and floats.
234 Assembler assm(isolate, NULL, 0);
235 Label L, C;
236
237
238 if (CpuFeatures::IsSupported(VFP3)) {
239 CpuFeatureScope scope(&assm, VFP3);
240
241 __ mov(ip, Operand(sp));
242 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
243 __ sub(fp, ip, Operand(4));
244
245 __ mov(r4, Operand(r0));
246 __ vldr(d6, r4, OFFSET_OF(T, a));
247 __ vldr(d7, r4, OFFSET_OF(T, b));
248 __ vadd(d5, d6, d7);
249 __ vstr(d5, r4, OFFSET_OF(T, c));
250
251 __ vmla(d5, d6, d7);
252 __ vmls(d5, d5, d6);
253
254 __ vmov(r2, r3, d5);
255 __ vmov(d4, r2, r3);
256 __ vstr(d4, r4, OFFSET_OF(T, b));
257
258 // Load t.x and t.y, switch values, and store back to the struct.
259 __ vldr(s0, r4, OFFSET_OF(T, x));
260 __ vldr(s31, r4, OFFSET_OF(T, y));
261 __ vmov(s16, s0);
262 __ vmov(s0, s31);
263 __ vmov(s31, s16);
264 __ vstr(s0, r4, OFFSET_OF(T, x));
265 __ vstr(s31, r4, OFFSET_OF(T, y));
266
267 // Move a literal into a register that can be encoded in the instruction.
268 __ vmov(d4, 1.0);
269 __ vstr(d4, r4, OFFSET_OF(T, e));
270
271 // Move a literal into a register that requires 64 bits to encode.
272 // 0x3ff0000010000000 = 1.000000059604644775390625
273 __ vmov(d4, 1.000000059604644775390625);
274 __ vstr(d4, r4, OFFSET_OF(T, d));
275
276 // Convert from floating point to integer.
277 __ vmov(d4, 2.0);
278 __ vcvt_s32_f64(s31, d4);
279 __ vstr(s31, r4, OFFSET_OF(T, i));
280
281 // Convert from integer to floating point.
282 __ mov(lr, Operand(42));
283 __ vmov(s31, lr);
284 __ vcvt_f64_s32(d4, s31);
285 __ vstr(d4, r4, OFFSET_OF(T, f));
286
287 // Convert from fixed point to floating point.
288 __ mov(lr, Operand(2468));
289 __ vmov(s8, lr);
290 __ vcvt_f64_s32(d4, 2);
291 __ vstr(d4, r4, OFFSET_OF(T, j));
292
293 // Test vabs.
294 __ vldr(d1, r4, OFFSET_OF(T, g));
295 __ vabs(d0, d1);
296 __ vstr(d0, r4, OFFSET_OF(T, g));
297 __ vldr(d2, r4, OFFSET_OF(T, h));
298 __ vabs(d0, d2);
299 __ vstr(d0, r4, OFFSET_OF(T, h));
300
301 // Test vneg.
302 __ vldr(d1, r4, OFFSET_OF(T, m));
303 __ vneg(d0, d1);
304 __ vstr(d0, r4, OFFSET_OF(T, m));
305 __ vldr(d1, r4, OFFSET_OF(T, n));
306 __ vneg(d0, d1);
307 __ vstr(d0, r4, OFFSET_OF(T, n));
308
309 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
310
311 CodeDesc desc;
312 assm.GetCode(&desc);
313 Handle<Code> code = isolate->factory()->NewCode(
314 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
315 #ifdef DEBUG
316 OFStream os(stdout);
317 code->Print(os);
318 #endif
319 F3 f = FUNCTION_CAST<F3>(code->entry());
320 t.a = 1.5;
321 t.b = 2.75;
322 t.c = 17.17;
323 t.d = 0.0;
324 t.e = 0.0;
325 t.f = 0.0;
326 t.g = -2718.2818;
327 t.h = 31415926.5;
328 t.i = 0;
329 t.j = 0;
330 t.m = -2718.2818;
331 t.n = 123.456;
332 t.x = 4.5;
333 t.y = 9.0;
334 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
335 USE(dummy);
336 CHECK_EQ(4.5, t.y);
337 CHECK_EQ(9.0, t.x);
338 CHECK_EQ(-123.456, t.n);
339 CHECK_EQ(2718.2818, t.m);
340 CHECK_EQ(2, t.i);
341 CHECK_EQ(2718.2818, t.g);
342 CHECK_EQ(31415926.5, t.h);
343 CHECK_EQ(617.0, t.j);
344 CHECK_EQ(42.0, t.f);
345 CHECK_EQ(1.0, t.e);
346 CHECK_EQ(1.000000059604644775390625, t.d);
347 CHECK_EQ(4.25, t.c);
348 CHECK_EQ(-4.1875, t.b);
349 CHECK_EQ(1.5, t.a);
350 }
351 }
352
353
354 TEST(5) {
355 // Test the ARMv7 bitfield instructions.
356 CcTest::InitializeVM();
357 Isolate* isolate = CcTest::i_isolate();
358 HandleScope scope(isolate);
359
360 Assembler assm(isolate, NULL, 0);
361
362 if (CpuFeatures::IsSupported(ARMv7)) {
363 CpuFeatureScope scope(&assm, ARMv7);
364 // On entry, r0 = 0xAAAAAAAA = 0b10..10101010.
365 __ ubfx(r0, r0, 1, 12); // 0b00..010101010101 = 0x555
366 __ sbfx(r0, r0, 0, 5); // 0b11..111111110101 = -11
367 __ bfc(r0, 1, 3); // 0b11..111111110001 = -15
368 __ mov(r1, Operand(7));
369 __ bfi(r0, r1, 3, 3); // 0b11..111111111001 = -7
370 __ mov(pc, Operand(lr));
371
372 CodeDesc desc;
373 assm.GetCode(&desc);
374 Handle<Code> code = isolate->factory()->NewCode(
375 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
376 #ifdef DEBUG
377 OFStream os(stdout);
378 code->Print(os);
379 #endif
380 F1 f = FUNCTION_CAST<F1>(code->entry());
381 int res = reinterpret_cast<int>(
382 CALL_GENERATED_CODE(f, 0xAAAAAAAA, 0, 0, 0, 0));
383 ::printf("f() = %d\n", res);
384 CHECK_EQ(-7, res);
385 }
386 }
387
388
389 TEST(6) {
390 // Test saturating instructions.
391 CcTest::InitializeVM();
392 Isolate* isolate = CcTest::i_isolate();
393 HandleScope scope(isolate);
394
395 Assembler assm(isolate, NULL, 0);
396
397 if (CpuFeatures::IsSupported(ARMv7)) {
398 CpuFeatureScope scope(&assm, ARMv7);
399 __ usat(r1, 8, Operand(r0)); // Sat 0xFFFF to 0-255 = 0xFF.
400 __ usat(r2, 12, Operand(r0, ASR, 9)); // Sat (0xFFFF>>9) to 0-4095 = 0x7F.
401 __ usat(r3, 1, Operand(r0, LSL, 16)); // Sat (0xFFFF<<16) to 0-1 = 0x0.
402 __ add(r0, r1, Operand(r2));
403 __ add(r0, r0, Operand(r3));
404 __ mov(pc, Operand(lr));
405
406 CodeDesc desc;
407 assm.GetCode(&desc);
408 Handle<Code> code = isolate->factory()->NewCode(
409 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
410 #ifdef DEBUG
411 OFStream os(stdout);
412 code->Print(os);
413 #endif
414 F1 f = FUNCTION_CAST<F1>(code->entry());
415 int res = reinterpret_cast<int>(
416 CALL_GENERATED_CODE(f, 0xFFFF, 0, 0, 0, 0));
417 ::printf("f() = %d\n", res);
418 CHECK_EQ(382, res);
419 }
420 }
421
422
423 enum VCVTTypes {
424 s32_f64,
425 u32_f64
426 };
427
TestRoundingMode(VCVTTypes types,VFPRoundingMode mode,double value,int expected,bool expected_exception=false)428 static void TestRoundingMode(VCVTTypes types,
429 VFPRoundingMode mode,
430 double value,
431 int expected,
432 bool expected_exception = false) {
433 Isolate* isolate = CcTest::i_isolate();
434 HandleScope scope(isolate);
435
436 Assembler assm(isolate, NULL, 0);
437
438 if (CpuFeatures::IsSupported(VFP3)) {
439 CpuFeatureScope scope(&assm, VFP3);
440
441 Label wrong_exception;
442
443 __ vmrs(r1);
444 // Set custom FPSCR.
445 __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask));
446 __ orr(r2, r2, Operand(mode));
447 __ vmsr(r2);
448
449 // Load value, convert, and move back result to r0 if everything went well.
450 __ vmov(d1, value);
451 switch (types) {
452 case s32_f64:
453 __ vcvt_s32_f64(s0, d1, kFPSCRRounding);
454 break;
455
456 case u32_f64:
457 __ vcvt_u32_f64(s0, d1, kFPSCRRounding);
458 break;
459
460 default:
461 UNREACHABLE();
462 break;
463 }
464 // Check for vfp exceptions
465 __ vmrs(r2);
466 __ tst(r2, Operand(kVFPExceptionMask));
467 // Check that we behaved as expected.
468 __ b(&wrong_exception,
469 expected_exception ? eq : ne);
470 // There was no exception. Retrieve the result and return.
471 __ vmov(r0, s0);
472 __ mov(pc, Operand(lr));
473
474 // The exception behaviour is not what we expected.
475 // Load a special value and return.
476 __ bind(&wrong_exception);
477 __ mov(r0, Operand(11223344));
478 __ mov(pc, Operand(lr));
479
480 CodeDesc desc;
481 assm.GetCode(&desc);
482 Handle<Code> code = isolate->factory()->NewCode(
483 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
484 #ifdef DEBUG
485 OFStream os(stdout);
486 code->Print(os);
487 #endif
488 F1 f = FUNCTION_CAST<F1>(code->entry());
489 int res = reinterpret_cast<int>(
490 CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
491 ::printf("res = %d\n", res);
492 CHECK_EQ(expected, res);
493 }
494 }
495
496
497 TEST(7) {
498 CcTest::InitializeVM();
499 // Test vfp rounding modes.
500
501 // s32_f64 (double to integer).
502
503 TestRoundingMode(s32_f64, RN, 0, 0);
504 TestRoundingMode(s32_f64, RN, 0.5, 0);
505 TestRoundingMode(s32_f64, RN, -0.5, 0);
506 TestRoundingMode(s32_f64, RN, 1.5, 2);
507 TestRoundingMode(s32_f64, RN, -1.5, -2);
508 TestRoundingMode(s32_f64, RN, 123.7, 124);
509 TestRoundingMode(s32_f64, RN, -123.7, -124);
510 TestRoundingMode(s32_f64, RN, 123456.2, 123456);
511 TestRoundingMode(s32_f64, RN, -123456.2, -123456);
512 TestRoundingMode(s32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
513 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.49), kMaxInt);
514 TestRoundingMode(s32_f64, RN, (kMaxInt + 1.0), kMaxInt, true);
515 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.5), kMaxInt, true);
516 TestRoundingMode(s32_f64, RN, static_cast<double>(kMinInt), kMinInt);
517 TestRoundingMode(s32_f64, RN, (kMinInt - 0.5), kMinInt);
518 TestRoundingMode(s32_f64, RN, (kMinInt - 1.0), kMinInt, true);
519 TestRoundingMode(s32_f64, RN, (kMinInt - 0.51), kMinInt, true);
520
521 TestRoundingMode(s32_f64, RM, 0, 0);
522 TestRoundingMode(s32_f64, RM, 0.5, 0);
523 TestRoundingMode(s32_f64, RM, -0.5, -1);
524 TestRoundingMode(s32_f64, RM, 123.7, 123);
525 TestRoundingMode(s32_f64, RM, -123.7, -124);
526 TestRoundingMode(s32_f64, RM, 123456.2, 123456);
527 TestRoundingMode(s32_f64, RM, -123456.2, -123457);
528 TestRoundingMode(s32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
529 TestRoundingMode(s32_f64, RM, (kMaxInt + 0.5), kMaxInt);
530 TestRoundingMode(s32_f64, RM, (kMaxInt + 1.0), kMaxInt, true);
531 TestRoundingMode(s32_f64, RM, static_cast<double>(kMinInt), kMinInt);
532 TestRoundingMode(s32_f64, RM, (kMinInt - 0.5), kMinInt, true);
533 TestRoundingMode(s32_f64, RM, (kMinInt + 0.5), kMinInt);
534
535 TestRoundingMode(s32_f64, RZ, 0, 0);
536 TestRoundingMode(s32_f64, RZ, 0.5, 0);
537 TestRoundingMode(s32_f64, RZ, -0.5, 0);
538 TestRoundingMode(s32_f64, RZ, 123.7, 123);
539 TestRoundingMode(s32_f64, RZ, -123.7, -123);
540 TestRoundingMode(s32_f64, RZ, 123456.2, 123456);
541 TestRoundingMode(s32_f64, RZ, -123456.2, -123456);
542 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
543 TestRoundingMode(s32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
544 TestRoundingMode(s32_f64, RZ, (kMaxInt + 1.0), kMaxInt, true);
545 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMinInt), kMinInt);
546 TestRoundingMode(s32_f64, RZ, (kMinInt - 0.5), kMinInt);
547 TestRoundingMode(s32_f64, RZ, (kMinInt - 1.0), kMinInt, true);
548
549
550 // u32_f64 (double to integer).
551
552 // Negative values.
553 TestRoundingMode(u32_f64, RN, -0.5, 0);
554 TestRoundingMode(u32_f64, RN, -123456.7, 0, true);
555 TestRoundingMode(u32_f64, RN, static_cast<double>(kMinInt), 0, true);
556 TestRoundingMode(u32_f64, RN, kMinInt - 1.0, 0, true);
557
558 TestRoundingMode(u32_f64, RM, -0.5, 0, true);
559 TestRoundingMode(u32_f64, RM, -123456.7, 0, true);
560 TestRoundingMode(u32_f64, RM, static_cast<double>(kMinInt), 0, true);
561 TestRoundingMode(u32_f64, RM, kMinInt - 1.0, 0, true);
562
563 TestRoundingMode(u32_f64, RZ, -0.5, 0);
564 TestRoundingMode(u32_f64, RZ, -123456.7, 0, true);
565 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMinInt), 0, true);
566 TestRoundingMode(u32_f64, RZ, kMinInt - 1.0, 0, true);
567
568 // Positive values.
569 // kMaxInt is the maximum *signed* integer: 0x7fffffff.
570 static const uint32_t kMaxUInt = 0xffffffffu;
571 TestRoundingMode(u32_f64, RZ, 0, 0);
572 TestRoundingMode(u32_f64, RZ, 0.5, 0);
573 TestRoundingMode(u32_f64, RZ, 123.7, 123);
574 TestRoundingMode(u32_f64, RZ, 123456.2, 123456);
575 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
576 TestRoundingMode(u32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
577 TestRoundingMode(u32_f64, RZ, (kMaxInt + 1.0),
578 static_cast<uint32_t>(kMaxInt) + 1);
579 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 0.5), kMaxUInt);
580 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 1.0), kMaxUInt, true);
581
582 TestRoundingMode(u32_f64, RM, 0, 0);
583 TestRoundingMode(u32_f64, RM, 0.5, 0);
584 TestRoundingMode(u32_f64, RM, 123.7, 123);
585 TestRoundingMode(u32_f64, RM, 123456.2, 123456);
586 TestRoundingMode(u32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
587 TestRoundingMode(u32_f64, RM, (kMaxInt + 0.5), kMaxInt);
588 TestRoundingMode(u32_f64, RM, (kMaxInt + 1.0),
589 static_cast<uint32_t>(kMaxInt) + 1);
590 TestRoundingMode(u32_f64, RM, (kMaxUInt + 0.5), kMaxUInt);
591 TestRoundingMode(u32_f64, RM, (kMaxUInt + 1.0), kMaxUInt, true);
592
593 TestRoundingMode(u32_f64, RN, 0, 0);
594 TestRoundingMode(u32_f64, RN, 0.5, 0);
595 TestRoundingMode(u32_f64, RN, 1.5, 2);
596 TestRoundingMode(u32_f64, RN, 123.7, 124);
597 TestRoundingMode(u32_f64, RN, 123456.2, 123456);
598 TestRoundingMode(u32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
599 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.49), kMaxInt);
600 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.5),
601 static_cast<uint32_t>(kMaxInt) + 1);
602 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.49), kMaxUInt);
603 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.5), kMaxUInt, true);
604 TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true);
605 }
606
607
608 TEST(8) {
609 // Test VFP multi load/store with ia_w.
610 CcTest::InitializeVM();
611 Isolate* isolate = CcTest::i_isolate();
612 HandleScope scope(isolate);
613
614 typedef struct {
615 double a;
616 double b;
617 double c;
618 double d;
619 double e;
620 double f;
621 double g;
622 double h;
623 } D;
624 D d;
625
626 typedef struct {
627 float a;
628 float b;
629 float c;
630 float d;
631 float e;
632 float f;
633 float g;
634 float h;
635 } F;
636 F f;
637
638 // Create a function that uses vldm/vstm to move some double and
639 // single precision values around in memory.
640 Assembler assm(isolate, NULL, 0);
641
642 __ mov(ip, Operand(sp));
643 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
644 __ sub(fp, ip, Operand(4));
645
646 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
647 __ vldm(ia_w, r4, d0, d3);
648 __ vldm(ia_w, r4, d4, d7);
649
650 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
651 __ vstm(ia_w, r4, d6, d7);
652 __ vstm(ia_w, r4, d0, d5);
653
654 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
655 __ vldm(ia_w, r4, s0, s3);
656 __ vldm(ia_w, r4, s4, s7);
657
658 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
659 __ vstm(ia_w, r4, s6, s7);
660 __ vstm(ia_w, r4, s0, s5);
661
662 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
663
664 CodeDesc desc;
665 assm.GetCode(&desc);
666 Handle<Code> code = isolate->factory()->NewCode(
667 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
668 #ifdef DEBUG
669 OFStream os(stdout);
670 code->Print(os);
671 #endif
672 F4 fn = FUNCTION_CAST<F4>(code->entry());
673 d.a = 1.1;
674 d.b = 2.2;
675 d.c = 3.3;
676 d.d = 4.4;
677 d.e = 5.5;
678 d.f = 6.6;
679 d.g = 7.7;
680 d.h = 8.8;
681
682 f.a = 1.0;
683 f.b = 2.0;
684 f.c = 3.0;
685 f.d = 4.0;
686 f.e = 5.0;
687 f.f = 6.0;
688 f.g = 7.0;
689 f.h = 8.0;
690
691 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
692 USE(dummy);
693
694 CHECK_EQ(7.7, d.a);
695 CHECK_EQ(8.8, d.b);
696 CHECK_EQ(1.1, d.c);
697 CHECK_EQ(2.2, d.d);
698 CHECK_EQ(3.3, d.e);
699 CHECK_EQ(4.4, d.f);
700 CHECK_EQ(5.5, d.g);
701 CHECK_EQ(6.6, d.h);
702
703 CHECK_EQ(7.0, f.a);
704 CHECK_EQ(8.0, f.b);
705 CHECK_EQ(1.0, f.c);
706 CHECK_EQ(2.0, f.d);
707 CHECK_EQ(3.0, f.e);
708 CHECK_EQ(4.0, f.f);
709 CHECK_EQ(5.0, f.g);
710 CHECK_EQ(6.0, f.h);
711 }
712
713
714 TEST(9) {
715 // Test VFP multi load/store with ia.
716 CcTest::InitializeVM();
717 Isolate* isolate = CcTest::i_isolate();
718 HandleScope scope(isolate);
719
720 typedef struct {
721 double a;
722 double b;
723 double c;
724 double d;
725 double e;
726 double f;
727 double g;
728 double h;
729 } D;
730 D d;
731
732 typedef struct {
733 float a;
734 float b;
735 float c;
736 float d;
737 float e;
738 float f;
739 float g;
740 float h;
741 } F;
742 F f;
743
744 // Create a function that uses vldm/vstm to move some double and
745 // single precision values around in memory.
746 Assembler assm(isolate, NULL, 0);
747
748 __ mov(ip, Operand(sp));
749 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
750 __ sub(fp, ip, Operand(4));
751
752 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
753 __ vldm(ia, r4, d0, d3);
754 __ add(r4, r4, Operand(4 * 8));
755 __ vldm(ia, r4, d4, d7);
756
757 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
758 __ vstm(ia, r4, d6, d7);
759 __ add(r4, r4, Operand(2 * 8));
760 __ vstm(ia, r4, d0, d5);
761
762 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
763 __ vldm(ia, r4, s0, s3);
764 __ add(r4, r4, Operand(4 * 4));
765 __ vldm(ia, r4, s4, s7);
766
767 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
768 __ vstm(ia, r4, s6, s7);
769 __ add(r4, r4, Operand(2 * 4));
770 __ vstm(ia, r4, s0, s5);
771
772 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
773
774 CodeDesc desc;
775 assm.GetCode(&desc);
776 Handle<Code> code = isolate->factory()->NewCode(
777 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
778 #ifdef DEBUG
779 OFStream os(stdout);
780 code->Print(os);
781 #endif
782 F4 fn = FUNCTION_CAST<F4>(code->entry());
783 d.a = 1.1;
784 d.b = 2.2;
785 d.c = 3.3;
786 d.d = 4.4;
787 d.e = 5.5;
788 d.f = 6.6;
789 d.g = 7.7;
790 d.h = 8.8;
791
792 f.a = 1.0;
793 f.b = 2.0;
794 f.c = 3.0;
795 f.d = 4.0;
796 f.e = 5.0;
797 f.f = 6.0;
798 f.g = 7.0;
799 f.h = 8.0;
800
801 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
802 USE(dummy);
803
804 CHECK_EQ(7.7, d.a);
805 CHECK_EQ(8.8, d.b);
806 CHECK_EQ(1.1, d.c);
807 CHECK_EQ(2.2, d.d);
808 CHECK_EQ(3.3, d.e);
809 CHECK_EQ(4.4, d.f);
810 CHECK_EQ(5.5, d.g);
811 CHECK_EQ(6.6, d.h);
812
813 CHECK_EQ(7.0, f.a);
814 CHECK_EQ(8.0, f.b);
815 CHECK_EQ(1.0, f.c);
816 CHECK_EQ(2.0, f.d);
817 CHECK_EQ(3.0, f.e);
818 CHECK_EQ(4.0, f.f);
819 CHECK_EQ(5.0, f.g);
820 CHECK_EQ(6.0, f.h);
821 }
822
823
824 TEST(10) {
825 // Test VFP multi load/store with db_w.
826 CcTest::InitializeVM();
827 Isolate* isolate = CcTest::i_isolate();
828 HandleScope scope(isolate);
829
830 typedef struct {
831 double a;
832 double b;
833 double c;
834 double d;
835 double e;
836 double f;
837 double g;
838 double h;
839 } D;
840 D d;
841
842 typedef struct {
843 float a;
844 float b;
845 float c;
846 float d;
847 float e;
848 float f;
849 float g;
850 float h;
851 } F;
852 F f;
853
854 // Create a function that uses vldm/vstm to move some double and
855 // single precision values around in memory.
856 Assembler assm(isolate, NULL, 0);
857
858 __ mov(ip, Operand(sp));
859 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
860 __ sub(fp, ip, Operand(4));
861
862 __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8));
863 __ vldm(db_w, r4, d4, d7);
864 __ vldm(db_w, r4, d0, d3);
865
866 __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8));
867 __ vstm(db_w, r4, d0, d5);
868 __ vstm(db_w, r4, d6, d7);
869
870 __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4));
871 __ vldm(db_w, r4, s4, s7);
872 __ vldm(db_w, r4, s0, s3);
873
874 __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4));
875 __ vstm(db_w, r4, s0, s5);
876 __ vstm(db_w, r4, s6, s7);
877
878 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
879
880 CodeDesc desc;
881 assm.GetCode(&desc);
882 Handle<Code> code = isolate->factory()->NewCode(
883 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
884 #ifdef DEBUG
885 OFStream os(stdout);
886 code->Print(os);
887 #endif
888 F4 fn = FUNCTION_CAST<F4>(code->entry());
889 d.a = 1.1;
890 d.b = 2.2;
891 d.c = 3.3;
892 d.d = 4.4;
893 d.e = 5.5;
894 d.f = 6.6;
895 d.g = 7.7;
896 d.h = 8.8;
897
898 f.a = 1.0;
899 f.b = 2.0;
900 f.c = 3.0;
901 f.d = 4.0;
902 f.e = 5.0;
903 f.f = 6.0;
904 f.g = 7.0;
905 f.h = 8.0;
906
907 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
908 USE(dummy);
909
910 CHECK_EQ(7.7, d.a);
911 CHECK_EQ(8.8, d.b);
912 CHECK_EQ(1.1, d.c);
913 CHECK_EQ(2.2, d.d);
914 CHECK_EQ(3.3, d.e);
915 CHECK_EQ(4.4, d.f);
916 CHECK_EQ(5.5, d.g);
917 CHECK_EQ(6.6, d.h);
918
919 CHECK_EQ(7.0, f.a);
920 CHECK_EQ(8.0, f.b);
921 CHECK_EQ(1.0, f.c);
922 CHECK_EQ(2.0, f.d);
923 CHECK_EQ(3.0, f.e);
924 CHECK_EQ(4.0, f.f);
925 CHECK_EQ(5.0, f.g);
926 CHECK_EQ(6.0, f.h);
927 }
928
929
930 TEST(11) {
931 // Test instructions using the carry flag.
932 CcTest::InitializeVM();
933 Isolate* isolate = CcTest::i_isolate();
934 HandleScope scope(isolate);
935
936 typedef struct {
937 int32_t a;
938 int32_t b;
939 int32_t c;
940 int32_t d;
941 } I;
942 I i;
943
944 i.a = 0xabcd0001;
945 i.b = 0xabcd0000;
946
947 Assembler assm(isolate, NULL, 0);
948
949 // Test HeapObject untagging.
950 __ ldr(r1, MemOperand(r0, OFFSET_OF(I, a)));
951 __ mov(r1, Operand(r1, ASR, 1), SetCC);
952 __ adc(r1, r1, Operand(r1), LeaveCC, cs);
953 __ str(r1, MemOperand(r0, OFFSET_OF(I, a)));
954
955 __ ldr(r2, MemOperand(r0, OFFSET_OF(I, b)));
956 __ mov(r2, Operand(r2, ASR, 1), SetCC);
957 __ adc(r2, r2, Operand(r2), LeaveCC, cs);
958 __ str(r2, MemOperand(r0, OFFSET_OF(I, b)));
959
960 // Test corner cases.
961 __ mov(r1, Operand(0xffffffff));
962 __ mov(r2, Operand::Zero());
963 __ mov(r3, Operand(r1, ASR, 1), SetCC); // Set the carry.
964 __ adc(r3, r1, Operand(r2));
965 __ str(r3, MemOperand(r0, OFFSET_OF(I, c)));
966
967 __ mov(r1, Operand(0xffffffff));
968 __ mov(r2, Operand::Zero());
969 __ mov(r3, Operand(r2, ASR, 1), SetCC); // Unset the carry.
970 __ adc(r3, r1, Operand(r2));
971 __ str(r3, MemOperand(r0, OFFSET_OF(I, d)));
972
973 __ mov(pc, Operand(lr));
974
975 CodeDesc desc;
976 assm.GetCode(&desc);
977 Handle<Code> code = isolate->factory()->NewCode(
978 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
979 #ifdef DEBUG
980 OFStream os(stdout);
981 code->Print(os);
982 #endif
983 F3 f = FUNCTION_CAST<F3>(code->entry());
984 Object* dummy = CALL_GENERATED_CODE(f, &i, 0, 0, 0, 0);
985 USE(dummy);
986
987 CHECK_EQ(0xabcd0001, i.a);
988 CHECK_EQ(static_cast<int32_t>(0xabcd0000) >> 1, i.b);
989 CHECK_EQ(0x00000000, i.c);
990 CHECK_EQ(0xffffffff, i.d);
991 }
992
993
994 TEST(12) {
995 // Test chaining of label usages within instructions (issue 1644).
996 CcTest::InitializeVM();
997 Isolate* isolate = CcTest::i_isolate();
998 HandleScope scope(isolate);
999
1000 Assembler assm(isolate, NULL, 0);
1001 Label target;
1002 __ b(eq, &target);
1003 __ b(ne, &target);
1004 __ bind(&target);
1005 __ nop();
1006 }
1007
1008
1009 TEST(13) {
1010 // Test VFP instructions using registers d16-d31.
1011 CcTest::InitializeVM();
1012 Isolate* isolate = CcTest::i_isolate();
1013 HandleScope scope(isolate);
1014
1015 if (!CpuFeatures::IsSupported(VFP32DREGS)) {
1016 return;
1017 }
1018
1019 typedef struct {
1020 double a;
1021 double b;
1022 double c;
1023 double x;
1024 double y;
1025 double z;
1026 double i;
1027 double j;
1028 double k;
1029 uint32_t low;
1030 uint32_t high;
1031 } T;
1032 T t;
1033
1034 // Create a function that accepts &t, and loads, manipulates, and stores
1035 // the doubles and floats.
1036 Assembler assm(isolate, NULL, 0);
1037 Label L, C;
1038
1039
1040 if (CpuFeatures::IsSupported(VFP3)) {
1041 CpuFeatureScope scope(&assm, VFP3);
1042
1043 __ stm(db_w, sp, r4.bit() | lr.bit());
1044
1045 // Load a, b, c into d16, d17, d18.
1046 __ mov(r4, Operand(r0));
1047 __ vldr(d16, r4, OFFSET_OF(T, a));
1048 __ vldr(d17, r4, OFFSET_OF(T, b));
1049 __ vldr(d18, r4, OFFSET_OF(T, c));
1050
1051 __ vneg(d25, d16);
1052 __ vadd(d25, d25, d17);
1053 __ vsub(d25, d25, d18);
1054 __ vmul(d25, d25, d25);
1055 __ vdiv(d25, d25, d18);
1056
1057 __ vmov(d16, d25);
1058 __ vsqrt(d17, d25);
1059 __ vneg(d17, d17);
1060 __ vabs(d17, d17);
1061 __ vmla(d18, d16, d17);
1062
1063 // Store d16, d17, d18 into a, b, c.
1064 __ mov(r4, Operand(r0));
1065 __ vstr(d16, r4, OFFSET_OF(T, a));
1066 __ vstr(d17, r4, OFFSET_OF(T, b));
1067 __ vstr(d18, r4, OFFSET_OF(T, c));
1068
1069 // Load x, y, z into d29-d31.
1070 __ add(r4, r0, Operand(OFFSET_OF(T, x)));
1071 __ vldm(ia_w, r4, d29, d31);
1072
1073 // Swap d29 and d30 via r registers.
1074 __ vmov(r1, r2, d29);
1075 __ vmov(d29, d30);
1076 __ vmov(d30, r1, r2);
1077
1078 // Convert to and from integer.
1079 __ vcvt_s32_f64(s1, d31);
1080 __ vcvt_f64_u32(d31, s1);
1081
1082 // Store d29-d31 into x, y, z.
1083 __ add(r4, r0, Operand(OFFSET_OF(T, x)));
1084 __ vstm(ia_w, r4, d29, d31);
1085
1086 // Move constants into d20, d21, d22 and store into i, j, k.
1087 __ vmov(d20, 14.7610017472335499);
1088 __ vmov(d21, 16.0);
1089 __ mov(r1, Operand(372106121));
1090 __ mov(r2, Operand(1079146608));
1091 __ vmov(d22, VmovIndexLo, r1);
1092 __ vmov(d22, VmovIndexHi, r2);
1093 __ add(r4, r0, Operand(OFFSET_OF(T, i)));
1094 __ vstm(ia_w, r4, d20, d22);
1095 // Move d22 into low and high.
1096 __ vmov(r4, VmovIndexLo, d22);
1097 __ str(r4, MemOperand(r0, OFFSET_OF(T, low)));
1098 __ vmov(r4, VmovIndexHi, d22);
1099 __ str(r4, MemOperand(r0, OFFSET_OF(T, high)));
1100
1101 __ ldm(ia_w, sp, r4.bit() | pc.bit());
1102
1103 CodeDesc desc;
1104 assm.GetCode(&desc);
1105 Handle<Code> code = isolate->factory()->NewCode(
1106 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1107 #ifdef DEBUG
1108 OFStream os(stdout);
1109 code->Print(os);
1110 #endif
1111 F3 f = FUNCTION_CAST<F3>(code->entry());
1112 t.a = 1.5;
1113 t.b = 2.75;
1114 t.c = 17.17;
1115 t.x = 1.5;
1116 t.y = 2.75;
1117 t.z = 17.17;
1118 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1119 USE(dummy);
1120 CHECK_EQ(14.7610017472335499, t.a);
1121 CHECK_EQ(3.84200491244266251, t.b);
1122 CHECK_EQ(73.8818412254460241, t.c);
1123 CHECK_EQ(2.75, t.x);
1124 CHECK_EQ(1.5, t.y);
1125 CHECK_EQ(17.0, t.z);
1126 CHECK_EQ(14.7610017472335499, t.i);
1127 CHECK_EQ(16.0, t.j);
1128 CHECK_EQ(73.8818412254460241, t.k);
1129 CHECK_EQ(372106121, t.low);
1130 CHECK_EQ(1079146608, t.high);
1131 }
1132 }
1133
1134
1135 TEST(14) {
1136 // Test the VFP Canonicalized Nan mode.
1137 CcTest::InitializeVM();
1138 Isolate* isolate = CcTest::i_isolate();
1139 HandleScope scope(isolate);
1140
1141 typedef struct {
1142 double left;
1143 double right;
1144 double add_result;
1145 double sub_result;
1146 double mul_result;
1147 double div_result;
1148 } T;
1149 T t;
1150
1151 // Create a function that makes the four basic operations.
1152 Assembler assm(isolate, NULL, 0);
1153
1154 // Ensure FPSCR state (as JSEntryStub does).
1155 Label fpscr_done;
1156 __ vmrs(r1);
1157 __ tst(r1, Operand(kVFPDefaultNaNModeControlBit));
1158 __ b(ne, &fpscr_done);
1159 __ orr(r1, r1, Operand(kVFPDefaultNaNModeControlBit));
1160 __ vmsr(r1);
1161 __ bind(&fpscr_done);
1162
1163 __ vldr(d0, r0, OFFSET_OF(T, left));
1164 __ vldr(d1, r0, OFFSET_OF(T, right));
1165 __ vadd(d2, d0, d1);
1166 __ vstr(d2, r0, OFFSET_OF(T, add_result));
1167 __ vsub(d2, d0, d1);
1168 __ vstr(d2, r0, OFFSET_OF(T, sub_result));
1169 __ vmul(d2, d0, d1);
1170 __ vstr(d2, r0, OFFSET_OF(T, mul_result));
1171 __ vdiv(d2, d0, d1);
1172 __ vstr(d2, r0, OFFSET_OF(T, div_result));
1173
1174 __ mov(pc, Operand(lr));
1175
1176 CodeDesc desc;
1177 assm.GetCode(&desc);
1178 Handle<Code> code = isolate->factory()->NewCode(
1179 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1180 #ifdef DEBUG
1181 OFStream os(stdout);
1182 code->Print(os);
1183 #endif
1184 F3 f = FUNCTION_CAST<F3>(code->entry());
1185 t.left = bit_cast<double>(kHoleNanInt64);
1186 t.right = 1;
1187 t.add_result = 0;
1188 t.sub_result = 0;
1189 t.mul_result = 0;
1190 t.div_result = 0;
1191 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1192 USE(dummy);
1193 const uint32_t kArmNanUpper32 = 0x7ff80000;
1194 const uint32_t kArmNanLower32 = 0x00000000;
1195 #ifdef DEBUG
1196 const uint64_t kArmNanInt64 =
1197 (static_cast<uint64_t>(kArmNanUpper32) << 32) | kArmNanLower32;
1198 DCHECK(kArmNanInt64 != kHoleNanInt64);
1199 #endif
1200 // With VFP2 the sign of the canonicalized Nan is undefined. So
1201 // we remove the sign bit for the upper tests.
1202 CHECK_EQ(kArmNanUpper32,
1203 (bit_cast<int64_t>(t.add_result) >> 32) & 0x7fffffff);
1204 CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.add_result) & 0xffffffffu);
1205 CHECK_EQ(kArmNanUpper32,
1206 (bit_cast<int64_t>(t.sub_result) >> 32) & 0x7fffffff);
1207 CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.sub_result) & 0xffffffffu);
1208 CHECK_EQ(kArmNanUpper32,
1209 (bit_cast<int64_t>(t.mul_result) >> 32) & 0x7fffffff);
1210 CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.mul_result) & 0xffffffffu);
1211 CHECK_EQ(kArmNanUpper32,
1212 (bit_cast<int64_t>(t.div_result) >> 32) & 0x7fffffff);
1213 CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.div_result) & 0xffffffffu);
1214 }
1215
1216
1217 TEST(15) {
1218 // Test the Neon instructions.
1219 CcTest::InitializeVM();
1220 Isolate* isolate = CcTest::i_isolate();
1221 HandleScope scope(isolate);
1222
1223 typedef struct {
1224 uint32_t src0;
1225 uint32_t src1;
1226 uint32_t src2;
1227 uint32_t src3;
1228 uint32_t src4;
1229 uint32_t src5;
1230 uint32_t src6;
1231 uint32_t src7;
1232 uint32_t dst0;
1233 uint32_t dst1;
1234 uint32_t dst2;
1235 uint32_t dst3;
1236 uint32_t dst4;
1237 uint32_t dst5;
1238 uint32_t dst6;
1239 uint32_t dst7;
1240 uint32_t srcA0;
1241 uint32_t srcA1;
1242 uint32_t dstA0;
1243 uint32_t dstA1;
1244 uint32_t dstA2;
1245 uint32_t dstA3;
1246 uint32_t dstA4;
1247 uint32_t dstA5;
1248 uint32_t dstA6;
1249 uint32_t dstA7;
1250 } T;
1251 T t;
1252
1253 // Create a function that accepts &t, and loads, manipulates, and stores
1254 // the doubles and floats.
1255 Assembler assm(isolate, NULL, 0);
1256
1257
1258 if (CpuFeatures::IsSupported(NEON)) {
1259 CpuFeatureScope scope(&assm, NEON);
1260
1261 __ stm(db_w, sp, r4.bit() | lr.bit());
1262 // Move 32 bytes with neon.
1263 __ add(r4, r0, Operand(OFFSET_OF(T, src0)));
1264 __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4));
1265 __ add(r4, r0, Operand(OFFSET_OF(T, dst0)));
1266 __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4));
1267
1268 // Expand 8 bytes into 8 words(16 bits).
1269 __ add(r4, r0, Operand(OFFSET_OF(T, srcA0)));
1270 __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(r4));
1271 __ vmovl(NeonU8, q0, d0);
1272 __ add(r4, r0, Operand(OFFSET_OF(T, dstA0)));
1273 __ vst1(Neon8, NeonListOperand(d0, 2), NeonMemOperand(r4));
1274
1275 // The same expansion, but with different source and destination registers.
1276 __ add(r4, r0, Operand(OFFSET_OF(T, srcA0)));
1277 __ vld1(Neon8, NeonListOperand(d1), NeonMemOperand(r4));
1278 __ vmovl(NeonU8, q1, d1);
1279 __ add(r4, r0, Operand(OFFSET_OF(T, dstA4)));
1280 __ vst1(Neon8, NeonListOperand(d2, 2), NeonMemOperand(r4));
1281
1282 __ ldm(ia_w, sp, r4.bit() | pc.bit());
1283
1284 CodeDesc desc;
1285 assm.GetCode(&desc);
1286 Handle<Code> code = isolate->factory()->NewCode(
1287 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1288 #ifdef DEBUG
1289 OFStream os(stdout);
1290 code->Print(os);
1291 #endif
1292 F3 f = FUNCTION_CAST<F3>(code->entry());
1293 t.src0 = 0x01020304;
1294 t.src1 = 0x11121314;
1295 t.src2 = 0x21222324;
1296 t.src3 = 0x31323334;
1297 t.src4 = 0x41424344;
1298 t.src5 = 0x51525354;
1299 t.src6 = 0x61626364;
1300 t.src7 = 0x71727374;
1301 t.dst0 = 0;
1302 t.dst1 = 0;
1303 t.dst2 = 0;
1304 t.dst3 = 0;
1305 t.dst4 = 0;
1306 t.dst5 = 0;
1307 t.dst6 = 0;
1308 t.dst7 = 0;
1309 t.srcA0 = 0x41424344;
1310 t.srcA1 = 0x81828384;
1311 t.dstA0 = 0;
1312 t.dstA1 = 0;
1313 t.dstA2 = 0;
1314 t.dstA3 = 0;
1315 t.dstA4 = 0;
1316 t.dstA5 = 0;
1317 t.dstA6 = 0;
1318 t.dstA7 = 0;
1319 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1320 USE(dummy);
1321 CHECK_EQ(0x01020304, t.dst0);
1322 CHECK_EQ(0x11121314, t.dst1);
1323 CHECK_EQ(0x21222324, t.dst2);
1324 CHECK_EQ(0x31323334, t.dst3);
1325 CHECK_EQ(0x41424344, t.dst4);
1326 CHECK_EQ(0x51525354, t.dst5);
1327 CHECK_EQ(0x61626364, t.dst6);
1328 CHECK_EQ(0x71727374, t.dst7);
1329 CHECK_EQ(0x00430044, t.dstA0);
1330 CHECK_EQ(0x00410042, t.dstA1);
1331 CHECK_EQ(0x00830084, t.dstA2);
1332 CHECK_EQ(0x00810082, t.dstA3);
1333 CHECK_EQ(0x00430044, t.dstA4);
1334 CHECK_EQ(0x00410042, t.dstA5);
1335 CHECK_EQ(0x00830084, t.dstA6);
1336 CHECK_EQ(0x00810082, t.dstA7);
1337 }
1338 }
1339
1340
1341 TEST(16) {
1342 // Test the pkh, uxtb, uxtab and uxtb16 instructions.
1343 CcTest::InitializeVM();
1344 Isolate* isolate = CcTest::i_isolate();
1345 HandleScope scope(isolate);
1346
1347 typedef struct {
1348 uint32_t src0;
1349 uint32_t src1;
1350 uint32_t src2;
1351 uint32_t dst0;
1352 uint32_t dst1;
1353 uint32_t dst2;
1354 uint32_t dst3;
1355 uint32_t dst4;
1356 } T;
1357 T t;
1358
1359 // Create a function that accepts &t, and loads, manipulates, and stores
1360 // the doubles and floats.
1361 Assembler assm(isolate, NULL, 0);
1362
1363 __ stm(db_w, sp, r4.bit() | lr.bit());
1364
1365 __ mov(r4, Operand(r0));
1366 __ ldr(r0, MemOperand(r4, OFFSET_OF(T, src0)));
1367 __ ldr(r1, MemOperand(r4, OFFSET_OF(T, src1)));
1368
1369 __ pkhbt(r2, r0, Operand(r1, LSL, 8));
1370 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst0)));
1371
1372 __ pkhtb(r2, r0, Operand(r1, ASR, 8));
1373 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst1)));
1374
1375 __ uxtb16(r2, Operand(r0, ROR, 8));
1376 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst2)));
1377
1378 __ uxtb(r2, Operand(r0, ROR, 8));
1379 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst3)));
1380
1381 __ ldr(r0, MemOperand(r4, OFFSET_OF(T, src2)));
1382 __ uxtab(r2, r0, Operand(r1, ROR, 8));
1383 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst4)));
1384
1385 __ ldm(ia_w, sp, r4.bit() | pc.bit());
1386
1387 CodeDesc desc;
1388 assm.GetCode(&desc);
1389 Handle<Code> code = isolate->factory()->NewCode(
1390 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1391 #ifdef DEBUG
1392 OFStream os(stdout);
1393 code->Print(os);
1394 #endif
1395 F3 f = FUNCTION_CAST<F3>(code->entry());
1396 t.src0 = 0x01020304;
1397 t.src1 = 0x11121314;
1398 t.src2 = 0x11121300;
1399 t.dst0 = 0;
1400 t.dst1 = 0;
1401 t.dst2 = 0;
1402 t.dst3 = 0;
1403 t.dst4 = 0;
1404 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1405 USE(dummy);
1406 CHECK_EQ(0x12130304, t.dst0);
1407 CHECK_EQ(0x01021213, t.dst1);
1408 CHECK_EQ(0x00010003, t.dst2);
1409 CHECK_EQ(0x00000003, t.dst3);
1410 CHECK_EQ(0x11121313, t.dst4);
1411 }
1412
1413
1414 TEST(17) {
1415 // Test generating labels at high addresses.
1416 // Should not assert.
1417 CcTest::InitializeVM();
1418 Isolate* isolate = CcTest::i_isolate();
1419 HandleScope scope(isolate);
1420
1421 // Generate a code segment that will be longer than 2^24 bytes.
1422 Assembler assm(isolate, NULL, 0);
1423 for (size_t i = 0; i < 1 << 23 ; ++i) { // 2^23
1424 __ nop();
1425 }
1426
1427 Label target;
1428 __ b(eq, &target);
1429 __ bind(&target);
1430 __ nop();
1431 }
1432
1433
1434 #define TEST_SDIV(expected_, dividend_, divisor_) \
1435 t.dividend = dividend_; \
1436 t.divisor = divisor_; \
1437 t.result = 0; \
1438 dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); \
1439 CHECK_EQ(expected_, t.result);
1440
1441
1442 TEST(18) {
1443 // Test the sdiv.
1444 CcTest::InitializeVM();
1445 Isolate* isolate = CcTest::i_isolate();
1446 HandleScope scope(isolate);
1447
1448 typedef struct {
1449 uint32_t dividend;
1450 uint32_t divisor;
1451 uint32_t result;
1452 } T;
1453 T t;
1454
1455 Assembler assm(isolate, NULL, 0);
1456
1457 if (CpuFeatures::IsSupported(SUDIV)) {
1458 CpuFeatureScope scope(&assm, SUDIV);
1459
1460 __ mov(r3, Operand(r0));
1461
1462 __ ldr(r0, MemOperand(r3, OFFSET_OF(T, dividend)));
1463 __ ldr(r1, MemOperand(r3, OFFSET_OF(T, divisor)));
1464
1465 __ sdiv(r2, r0, r1);
1466 __ str(r2, MemOperand(r3, OFFSET_OF(T, result)));
1467
1468 __ bx(lr);
1469
1470 CodeDesc desc;
1471 assm.GetCode(&desc);
1472 Handle<Code> code = isolate->factory()->NewCode(
1473 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1474 #ifdef DEBUG
1475 OFStream os(stdout);
1476 code->Print(os);
1477 #endif
1478 F3 f = FUNCTION_CAST<F3>(code->entry());
1479 Object* dummy;
1480 TEST_SDIV(1073741824, kMinInt, -2);
1481 TEST_SDIV(kMinInt, kMinInt, -1);
1482 TEST_SDIV(5, 10, 2);
1483 TEST_SDIV(3, 10, 3);
1484 TEST_SDIV(-5, 10, -2);
1485 TEST_SDIV(-3, 10, -3);
1486 TEST_SDIV(-5, -10, 2);
1487 TEST_SDIV(-3, -10, 3);
1488 TEST_SDIV(5, -10, -2);
1489 TEST_SDIV(3, -10, -3);
1490 USE(dummy);
1491 }
1492 }
1493
1494
1495 #undef TEST_SDIV
1496
1497
TEST(code_relative_offset)1498 TEST(code_relative_offset) {
1499 // Test extracting the offset of a label from the beginning of the code
1500 // in a register.
1501 CcTest::InitializeVM();
1502 Isolate* isolate = CcTest::i_isolate();
1503 HandleScope scope(isolate);
1504 // Initialize a code object that will contain the code.
1505 Handle<Object> code_object(isolate->heap()->undefined_value(), isolate);
1506
1507 Assembler assm(isolate, NULL, 0);
1508
1509 Label start, target_away, target_faraway;
1510
1511 __ stm(db_w, sp, r4.bit() | r5.bit() | lr.bit());
1512
1513 // r3 is used as the address zero, the test will crash when we load it.
1514 __ mov(r3, Operand::Zero());
1515
1516 // r5 will be a pointer to the start of the code.
1517 __ mov(r5, Operand(code_object));
1518 __ mov_label_offset(r4, &start);
1519
1520 __ mov_label_offset(r1, &target_faraway);
1521 __ str(r1, MemOperand(sp, kPointerSize, NegPreIndex));
1522
1523 __ mov_label_offset(r1, &target_away);
1524
1525 // Jump straight to 'target_away' the first time and use the relative
1526 // position the second time. This covers the case when extracting the
1527 // position of a label which is linked.
1528 __ mov(r2, Operand::Zero());
1529 __ bind(&start);
1530 __ cmp(r2, Operand::Zero());
1531 __ b(eq, &target_away);
1532 __ add(pc, r5, r1);
1533 // Emit invalid instructions to push the label between 2^8 and 2^16
1534 // instructions away. The test will crash if they are reached.
1535 for (int i = 0; i < (1 << 10); i++) {
1536 __ ldr(r3, MemOperand(r3));
1537 }
1538 __ bind(&target_away);
1539 // This will be hit twice: r0 = r0 + 5 + 5.
1540 __ add(r0, r0, Operand(5));
1541
1542 __ ldr(r1, MemOperand(sp, kPointerSize, PostIndex), ne);
1543 __ add(pc, r5, r4, LeaveCC, ne);
1544
1545 __ mov(r2, Operand(1));
1546 __ b(&start);
1547 // Emit invalid instructions to push the label between 2^16 and 2^24
1548 // instructions away. The test will crash if they are reached.
1549 for (int i = 0; i < (1 << 21); i++) {
1550 __ ldr(r3, MemOperand(r3));
1551 }
1552 __ bind(&target_faraway);
1553 // r0 = r0 + 5 + 5 + 11
1554 __ add(r0, r0, Operand(11));
1555
1556 __ ldm(ia_w, sp, r4.bit() | r5.bit() | pc.bit());
1557
1558 CodeDesc desc;
1559 assm.GetCode(&desc);
1560 Handle<Code> code = isolate->factory()->NewCode(
1561 desc, Code::ComputeFlags(Code::STUB), code_object);
1562 F1 f = FUNCTION_CAST<F1>(code->entry());
1563 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 21, 0, 0, 0, 0));
1564 ::printf("f() = %d\n", res);
1565 CHECK_EQ(42, res);
1566 }
1567
1568 #undef __
1569