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
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.
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.
29 #include "test/cctest/cctest.h"
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"
37 using namespace v8::internal;
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);
50 CcTest::InitializeVM();
51 Isolate* isolate = CcTest::i_isolate();
52 HandleScope scope(isolate);
54 Assembler assm(isolate, NULL, 0);
56 __ add(r0, r0, Operand(r1));
57 __ mov(pc, Operand(lr));
61 Handle<Code> code = isolate->factory()->NewCode(
62 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
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);
75 CcTest::InitializeVM();
76 Isolate* isolate = CcTest::i_isolate();
77 HandleScope scope(isolate);
79 Assembler assm(isolate, NULL, 0);
82 __ mov(r1, Operand(r0));
83 __ mov(r0, Operand::Zero());
87 __ add(r0, r0, Operand(r1));
88 __ sub(r1, r1, Operand(1));
91 __ teq(r1, Operand::Zero());
93 __ mov(pc, Operand(lr));
97 Handle<Code> code = isolate->factory()->NewCode(
98 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
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);
111 CcTest::InitializeVM();
112 Isolate* isolate = CcTest::i_isolate();
113 HandleScope scope(isolate);
115 Assembler assm(isolate, NULL, 0);
118 __ mov(r1, Operand(r0));
119 __ mov(r0, Operand(1));
124 __ sub(r1, r1, Operand(1));
127 __ teq(r1, Operand::Zero());
129 __ mov(pc, Operand(lr));
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));
142 Handle<Code> code = isolate->factory()->NewCode(
143 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
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);
156 CcTest::InitializeVM();
157 Isolate* isolate = CcTest::i_isolate();
158 HandleScope scope(isolate);
167 Assembler assm(isolate, NULL, 0);
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());
189 Handle<Code> code = isolate->factory()->NewCode(
190 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
195 F3 f = FUNCTION_CAST<F3>(code->entry());
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);
204 CHECK_EQ(1000/8, t.s);
209 // Test the VFP floating point instructions.
210 CcTest::InitializeVM();
211 Isolate* isolate = CcTest::i_isolate();
212 HandleScope scope(isolate);
232 // Create a function that accepts &t, and loads, manipulates, and stores
233 // the doubles and floats.
234 Assembler assm(isolate, NULL, 0);
238 if (CpuFeatures::IsSupported(VFP3)) {
239 CpuFeatureScope scope(&assm, VFP3);
241 __ mov(ip, Operand(sp));
242 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
243 __ sub(fp, ip, Operand(4));
245 __ mov(r4, Operand(r0));
246 __ vldr(d6, r4, OFFSET_OF(T, a));
247 __ vldr(d7, r4, OFFSET_OF(T, b));
249 __ vstr(d5, r4, OFFSET_OF(T, c));
256 __ vstr(d4, r4, OFFSET_OF(T, b));
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));
264 __ vstr(s0, r4, OFFSET_OF(T, x));
265 __ vstr(s31, r4, OFFSET_OF(T, y));
267 // Move a literal into a register that can be encoded in the instruction.
269 __ vstr(d4, r4, OFFSET_OF(T, e));
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));
276 // Convert from floating point to integer.
278 __ vcvt_s32_f64(s31, d4);
279 __ vstr(s31, r4, OFFSET_OF(T, i));
281 // Convert from integer to floating point.
282 __ mov(lr, Operand(42));
284 __ vcvt_f64_s32(d4, s31);
285 __ vstr(d4, r4, OFFSET_OF(T, f));
287 // Convert from fixed point to floating point.
288 __ mov(lr, Operand(2468));
290 __ vcvt_f64_s32(d4, 2);
291 __ vstr(d4, r4, OFFSET_OF(T, j));
294 __ vldr(d1, r4, OFFSET_OF(T, g));
296 __ vstr(d0, r4, OFFSET_OF(T, g));
297 __ vldr(d2, r4, OFFSET_OF(T, h));
299 __ vstr(d0, r4, OFFSET_OF(T, h));
302 __ vldr(d1, r4, OFFSET_OF(T, m));
304 __ vstr(d0, r4, OFFSET_OF(T, m));
305 __ vldr(d1, r4, OFFSET_OF(T, n));
307 __ vstr(d0, r4, OFFSET_OF(T, n));
309 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
313 Handle<Code> code = isolate->factory()->NewCode(
314 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
319 F3 f = FUNCTION_CAST<F3>(code->entry());
334 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
338 CHECK_EQ(-123.456, t.n);
339 CHECK_EQ(2718.2818, t.m);
341 CHECK_EQ(2718.2818, t.g);
342 CHECK_EQ(31415926.5, t.h);
343 CHECK_EQ(617.0, t.j);
346 CHECK_EQ(1.000000059604644775390625, t.d);
348 CHECK_EQ(-4.1875, t.b);
355 // Test the ARMv7 bitfield instructions.
356 CcTest::InitializeVM();
357 Isolate* isolate = CcTest::i_isolate();
358 HandleScope scope(isolate);
360 Assembler assm(isolate, NULL, 0);
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));
374 Handle<Code> code = isolate->factory()->NewCode(
375 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
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);
390 // Test saturating instructions.
391 CcTest::InitializeVM();
392 Isolate* isolate = CcTest::i_isolate();
393 HandleScope scope(isolate);
395 Assembler assm(isolate, NULL, 0);
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));
408 Handle<Code> code = isolate->factory()->NewCode(
409 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
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);
428 static void TestRoundingMode(VCVTTypes types,
429 VFPRoundingMode mode,
432 bool expected_exception = false) {
433 Isolate* isolate = CcTest::i_isolate();
434 HandleScope scope(isolate);
436 Assembler assm(isolate, NULL, 0);
438 if (CpuFeatures::IsSupported(VFP3)) {
439 CpuFeatureScope scope(&assm, VFP3);
441 Label wrong_exception;
445 __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask));
446 __ orr(r2, r2, Operand(mode));
449 // Load value, convert, and move back result to r0 if everything went well.
453 __ vcvt_s32_f64(s0, d1, kFPSCRRounding);
457 __ vcvt_u32_f64(s0, d1, kFPSCRRounding);
464 // Check for vfp exceptions
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.
472 __ mov(pc, Operand(lr));
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));
482 Handle<Code> code = isolate->factory()->NewCode(
483 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
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);
498 CcTest::InitializeVM();
499 // Test vfp rounding modes.
501 // s32_f64 (double to integer).
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);
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);
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);
550 // u32_f64 (double to integer).
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);
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);
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);
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);
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);
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);
609 // Test VFP multi load/store with ia_w.
610 CcTest::InitializeVM();
611 Isolate* isolate = CcTest::i_isolate();
612 HandleScope scope(isolate);
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);
642 __ mov(ip, Operand(sp));
643 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
644 __ sub(fp, ip, Operand(4));
646 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
647 __ vldm(ia_w, r4, d0, d3);
648 __ vldm(ia_w, r4, d4, d7);
650 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
651 __ vstm(ia_w, r4, d6, d7);
652 __ vstm(ia_w, r4, d0, d5);
654 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
655 __ vldm(ia_w, r4, s0, s3);
656 __ vldm(ia_w, r4, s4, s7);
658 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
659 __ vstm(ia_w, r4, s6, s7);
660 __ vstm(ia_w, r4, s0, s5);
662 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
666 Handle<Code> code = isolate->factory()->NewCode(
667 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
672 F4 fn = FUNCTION_CAST<F4>(code->entry());
691 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
715 // Test VFP multi load/store with ia.
716 CcTest::InitializeVM();
717 Isolate* isolate = CcTest::i_isolate();
718 HandleScope scope(isolate);
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);
748 __ mov(ip, Operand(sp));
749 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
750 __ sub(fp, ip, Operand(4));
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);
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);
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);
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);
772 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
776 Handle<Code> code = isolate->factory()->NewCode(
777 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
782 F4 fn = FUNCTION_CAST<F4>(code->entry());
801 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
825 // Test VFP multi load/store with db_w.
826 CcTest::InitializeVM();
827 Isolate* isolate = CcTest::i_isolate();
828 HandleScope scope(isolate);
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);
858 __ mov(ip, Operand(sp));
859 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
860 __ sub(fp, ip, Operand(4));
862 __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8));
863 __ vldm(db_w, r4, d4, d7);
864 __ vldm(db_w, r4, d0, d3);
866 __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8));
867 __ vstm(db_w, r4, d0, d5);
868 __ vstm(db_w, r4, d6, d7);
870 __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4));
871 __ vldm(db_w, r4, s4, s7);
872 __ vldm(db_w, r4, s0, s3);
874 __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4));
875 __ vstm(db_w, r4, s0, s5);
876 __ vstm(db_w, r4, s6, s7);
878 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
882 Handle<Code> code = isolate->factory()->NewCode(
883 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
888 F4 fn = FUNCTION_CAST<F4>(code->entry());
907 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
931 // Test instructions using the carry flag.
932 CcTest::InitializeVM();
933 Isolate* isolate = CcTest::i_isolate();
934 HandleScope scope(isolate);
947 Assembler assm(isolate, NULL, 0);
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)));
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)));
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)));
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)));
973 __ mov(pc, Operand(lr));
977 Handle<Code> code = isolate->factory()->NewCode(
978 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
983 F3 f = FUNCTION_CAST<F3>(code->entry());
984 Object* dummy = CALL_GENERATED_CODE(f, &i, 0, 0, 0, 0);
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);
995 // Test chaining of label usages within instructions (issue 1644).
996 CcTest::InitializeVM();
997 Isolate* isolate = CcTest::i_isolate();
998 HandleScope scope(isolate);
1000 Assembler assm(isolate, NULL, 0);
1010 // Test VFP instructions using registers d16-d31.
1011 CcTest::InitializeVM();
1012 Isolate* isolate = CcTest::i_isolate();
1013 HandleScope scope(isolate);
1015 if (!CpuFeatures::IsSupported(VFP32DREGS)) {
1034 // Create a function that accepts &t, and loads, manipulates, and stores
1035 // the doubles and floats.
1036 Assembler assm(isolate, NULL, 0);
1040 if (CpuFeatures::IsSupported(VFP3)) {
1041 CpuFeatureScope scope(&assm, VFP3);
1043 __ stm(db_w, sp, r4.bit() | lr.bit());
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));
1052 __ vadd(d25, d25, d17);
1053 __ vsub(d25, d25, d18);
1054 __ vmul(d25, d25, d25);
1055 __ vdiv(d25, d25, d18);
1061 __ vmla(d18, d16, d17);
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));
1069 // Load x, y, z into d29-d31.
1070 __ add(r4, r0, Operand(OFFSET_OF(T, x)));
1071 __ vldm(ia_w, r4, d29, d31);
1073 // Swap d29 and d30 via r registers.
1074 __ vmov(r1, r2, d29);
1076 __ vmov(d30, r1, r2);
1078 // Convert to and from integer.
1079 __ vcvt_s32_f64(s1, d31);
1080 __ vcvt_f64_u32(d31, s1);
1082 // Store d29-d31 into x, y, z.
1083 __ add(r4, r0, Operand(OFFSET_OF(T, x)));
1084 __ vstm(ia_w, r4, d29, d31);
1086 // Move constants into d20, d21, d22 and store into i, j, k.
1087 __ vmov(d20, 14.7610017472335499);
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)));
1101 __ ldm(ia_w, sp, r4.bit() | pc.bit());
1104 assm.GetCode(&desc);
1105 Handle<Code> code = isolate->factory()->NewCode(
1106 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1108 OFStream os(stdout);
1111 F3 f = FUNCTION_CAST<F3>(code->entry());
1118 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
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);
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);
1136 // Test the VFP Canonicalized Nan mode.
1137 CcTest::InitializeVM();
1138 Isolate* isolate = CcTest::i_isolate();
1139 HandleScope scope(isolate);
1151 // Create a function that makes the four basic operations.
1152 Assembler assm(isolate, NULL, 0);
1154 // Ensure FPSCR state (as JSEntryStub does).
1157 __ tst(r1, Operand(kVFPDefaultNaNModeControlBit));
1158 __ b(ne, &fpscr_done);
1159 __ orr(r1, r1, Operand(kVFPDefaultNaNModeControlBit));
1161 __ bind(&fpscr_done);
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));
1174 __ mov(pc, Operand(lr));
1177 assm.GetCode(&desc);
1178 Handle<Code> code = isolate->factory()->NewCode(
1179 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1181 OFStream os(stdout);
1184 F3 f = FUNCTION_CAST<F3>(code->entry());
1185 t.left = bit_cast<double>(kHoleNanInt64);
1191 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1193 const uint32_t kArmNanUpper32 = 0x7ff80000;
1194 const uint32_t kArmNanLower32 = 0x00000000;
1196 const uint64_t kArmNanInt64 =
1197 (static_cast<uint64_t>(kArmNanUpper32) << 32) | kArmNanLower32;
1198 DCHECK(kArmNanInt64 != kHoleNanInt64);
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);
1218 // Test the Neon instructions.
1219 CcTest::InitializeVM();
1220 Isolate* isolate = CcTest::i_isolate();
1221 HandleScope scope(isolate);
1253 // Create a function that accepts &t, and loads, manipulates, and stores
1254 // the doubles and floats.
1255 Assembler assm(isolate, NULL, 0);
1258 if (CpuFeatures::IsSupported(NEON)) {
1259 CpuFeatureScope scope(&assm, NEON);
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));
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));
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));
1282 __ ldm(ia_w, sp, r4.bit() | pc.bit());
1285 assm.GetCode(&desc);
1286 Handle<Code> code = isolate->factory()->NewCode(
1287 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1289 OFStream os(stdout);
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;
1309 t.srcA0 = 0x41424344;
1310 t.srcA1 = 0x81828384;
1319 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
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);
1342 // Test the pkh, uxtb, uxtab and uxtb16 instructions.
1343 CcTest::InitializeVM();
1344 Isolate* isolate = CcTest::i_isolate();
1345 HandleScope scope(isolate);
1359 // Create a function that accepts &t, and loads, manipulates, and stores
1360 // the doubles and floats.
1361 Assembler assm(isolate, NULL, 0);
1363 __ stm(db_w, sp, r4.bit() | lr.bit());
1365 __ mov(r4, Operand(r0));
1366 __ ldr(r0, MemOperand(r4, OFFSET_OF(T, src0)));
1367 __ ldr(r1, MemOperand(r4, OFFSET_OF(T, src1)));
1369 __ pkhbt(r2, r0, Operand(r1, LSL, 8));
1370 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst0)));
1372 __ pkhtb(r2, r0, Operand(r1, ASR, 8));
1373 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst1)));
1375 __ uxtb16(r2, Operand(r0, ROR, 8));
1376 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst2)));
1378 __ uxtb(r2, Operand(r0, ROR, 8));
1379 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst3)));
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)));
1385 __ ldm(ia_w, sp, r4.bit() | pc.bit());
1388 assm.GetCode(&desc);
1389 Handle<Code> code = isolate->factory()->NewCode(
1390 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1392 OFStream os(stdout);
1395 F3 f = FUNCTION_CAST<F3>(code->entry());
1396 t.src0 = 0x01020304;
1397 t.src1 = 0x11121314;
1398 t.src2 = 0x11121300;
1404 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
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);
1415 // Test generating labels at high addresses.
1416 // Should not assert.
1417 CcTest::InitializeVM();
1418 Isolate* isolate = CcTest::i_isolate();
1419 HandleScope scope(isolate);
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
1434 #define TEST_SDIV(expected_, dividend_, divisor_) \
1435 t.dividend = dividend_; \
1436 t.divisor = divisor_; \
1438 dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); \
1439 CHECK_EQ(expected_, t.result);
1444 CcTest::InitializeVM();
1445 Isolate* isolate = CcTest::i_isolate();
1446 HandleScope scope(isolate);
1455 Assembler assm(isolate, NULL, 0);
1457 if (CpuFeatures::IsSupported(SUDIV)) {
1458 CpuFeatureScope scope(&assm, SUDIV);
1460 __ mov(r3, Operand(r0));
1462 __ ldr(r0, MemOperand(r3, OFFSET_OF(T, dividend)));
1463 __ ldr(r1, MemOperand(r3, OFFSET_OF(T, divisor)));
1465 __ sdiv(r2, r0, r1);
1466 __ str(r2, MemOperand(r3, OFFSET_OF(T, result)));
1471 assm.GetCode(&desc);
1472 Handle<Code> code = isolate->factory()->NewCode(
1473 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1475 OFStream os(stdout);
1478 F3 f = FUNCTION_CAST<F3>(code->entry());
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);
1498 TEST(code_relative_offset) {
1499 // Test extracting the offset of a label from the beginning of the code
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);
1507 Assembler assm(isolate, NULL, 0);
1509 Label start, target_away, target_faraway;
1511 __ stm(db_w, sp, r4.bit() | r5.bit() | lr.bit());
1513 // r3 is used as the address zero, the test will crash when we load it.
1514 __ mov(r3, Operand::Zero());
1516 // r5 will be a pointer to the start of the code.
1517 __ mov(r5, Operand(code_object));
1518 __ mov_label_offset(r4, &start);
1520 __ mov_label_offset(r1, &target_faraway);
1521 __ str(r1, MemOperand(sp, kPointerSize, NegPreIndex));
1523 __ mov_label_offset(r1, &target_away);
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());
1530 __ cmp(r2, Operand::Zero());
1531 __ b(eq, &target_away);
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));
1538 __ bind(&target_away);
1539 // This will be hit twice: r0 = r0 + 5 + 5.
1540 __ add(r0, r0, Operand(5));
1542 __ ldr(r1, MemOperand(sp, kPointerSize, PostIndex), ne);
1543 __ add(pc, r5, r4, LeaveCC, ne);
1545 __ mov(r2, Operand(1));
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));
1552 __ bind(&target_faraway);
1553 // r0 = r0 + 5 + 5 + 11
1554 __ add(r0, r0, Operand(11));
1556 __ ldm(ia_w, sp, r4.bit() | r5.bit() | pc.bit());
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);