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.
30 #include "disassembler.h"
32 #include "arm/simulator-arm.h"
33 #include "arm/assembler-arm-inl.h"
36 using namespace v8::internal;
39 // Define these function prototypes to match JSEntryFunction in execution.cc.
40 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
41 typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
42 typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4);
43 typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4);
49 CcTest::InitializeVM();
50 Isolate* isolate = CcTest::i_isolate();
51 HandleScope scope(isolate);
53 Assembler assm(isolate, NULL, 0);
55 __ add(r0, r0, Operand(r1));
56 __ mov(pc, Operand(lr));
60 Handle<Code> code = isolate->factory()->NewCode(
61 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
65 F2 f = FUNCTION_CAST<F2>(code->entry());
66 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 3, 4, 0, 0, 0));
67 ::printf("f() = %d\n", res);
73 CcTest::InitializeVM();
74 Isolate* isolate = CcTest::i_isolate();
75 HandleScope scope(isolate);
77 Assembler assm(isolate, NULL, 0);
80 __ mov(r1, Operand(r0));
81 __ mov(r0, Operand::Zero());
85 __ add(r0, r0, Operand(r1));
86 __ sub(r1, r1, Operand(1));
89 __ teq(r1, Operand::Zero());
91 __ mov(pc, Operand(lr));
95 Handle<Code> code = isolate->factory()->NewCode(
96 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
100 F1 f = FUNCTION_CAST<F1>(code->entry());
101 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 100, 0, 0, 0, 0));
102 ::printf("f() = %d\n", res);
108 CcTest::InitializeVM();
109 Isolate* isolate = CcTest::i_isolate();
110 HandleScope scope(isolate);
112 Assembler assm(isolate, NULL, 0);
115 __ mov(r1, Operand(r0));
116 __ mov(r0, Operand(1));
121 __ sub(r1, r1, Operand(1));
124 __ teq(r1, Operand::Zero());
126 __ mov(pc, Operand(lr));
128 // some relocated stuff here, not executed
129 __ RecordComment("dead code, just testing relocations");
130 __ mov(r0, Operand(isolate->factory()->true_value()));
131 __ RecordComment("dead code, just testing immediate operands");
132 __ mov(r0, Operand(-1));
133 __ mov(r0, Operand(0xFF000000));
134 __ mov(r0, Operand(0xF0F0F0F0));
135 __ mov(r0, Operand(0xFFF0FFFF));
139 Handle<Code> code = isolate->factory()->NewCode(
140 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
144 F1 f = FUNCTION_CAST<F1>(code->entry());
145 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 10, 0, 0, 0, 0));
146 ::printf("f() = %d\n", res);
147 CHECK_EQ(3628800, res);
152 CcTest::InitializeVM();
153 Isolate* isolate = CcTest::i_isolate();
154 HandleScope scope(isolate);
163 Assembler assm(isolate, NULL, 0);
166 __ mov(ip, Operand(sp));
167 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
168 __ sub(fp, ip, Operand(4));
169 __ mov(r4, Operand(r0));
170 __ ldr(r0, MemOperand(r4, OFFSET_OF(T, i)));
171 __ mov(r2, Operand(r0, ASR, 1));
172 __ str(r2, MemOperand(r4, OFFSET_OF(T, i)));
173 __ ldrsb(r2, MemOperand(r4, OFFSET_OF(T, c)));
174 __ add(r0, r2, Operand(r0));
175 __ mov(r2, Operand(r2, LSL, 2));
176 __ strb(r2, MemOperand(r4, OFFSET_OF(T, c)));
177 __ ldrsh(r2, MemOperand(r4, OFFSET_OF(T, s)));
178 __ add(r0, r2, Operand(r0));
179 __ mov(r2, Operand(r2, ASR, 3));
180 __ strh(r2, MemOperand(r4, OFFSET_OF(T, s)));
181 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
185 Handle<Code> code = isolate->factory()->NewCode(
186 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
190 F3 f = FUNCTION_CAST<F3>(code->entry());
194 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0));
195 ::printf("f() = %d\n", res);
196 CHECK_EQ(101010, res);
197 CHECK_EQ(100000/2, t.i);
199 CHECK_EQ(1000/8, t.s);
204 // Test the VFP floating point instructions.
205 CcTest::InitializeVM();
206 Isolate* isolate = CcTest::i_isolate();
207 HandleScope scope(isolate);
227 // Create a function that accepts &t, and loads, manipulates, and stores
228 // the doubles and floats.
229 Assembler assm(isolate, NULL, 0);
233 if (CpuFeatures::IsSupported(VFP3)) {
234 CpuFeatureScope scope(&assm, VFP3);
236 __ mov(ip, Operand(sp));
237 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
238 __ sub(fp, ip, Operand(4));
240 __ mov(r4, Operand(r0));
241 __ vldr(d6, r4, OFFSET_OF(T, a));
242 __ vldr(d7, r4, OFFSET_OF(T, b));
244 __ vstr(d5, r4, OFFSET_OF(T, c));
251 __ vstr(d4, r4, OFFSET_OF(T, b));
253 // Load t.x and t.y, switch values, and store back to the struct.
254 __ vldr(s0, r4, OFFSET_OF(T, x));
255 __ vldr(s31, r4, OFFSET_OF(T, y));
259 __ vstr(s0, r4, OFFSET_OF(T, x));
260 __ vstr(s31, r4, OFFSET_OF(T, y));
262 // Move a literal into a register that can be encoded in the instruction.
264 __ vstr(d4, r4, OFFSET_OF(T, e));
266 // Move a literal into a register that requires 64 bits to encode.
267 // 0x3ff0000010000000 = 1.000000059604644775390625
268 __ vmov(d4, 1.000000059604644775390625);
269 __ vstr(d4, r4, OFFSET_OF(T, d));
271 // Convert from floating point to integer.
273 __ vcvt_s32_f64(s31, d4);
274 __ vstr(s31, r4, OFFSET_OF(T, i));
276 // Convert from integer to floating point.
277 __ mov(lr, Operand(42));
279 __ vcvt_f64_s32(d4, s31);
280 __ vstr(d4, r4, OFFSET_OF(T, f));
282 // Convert from fixed point to floating point.
283 __ mov(lr, Operand(2468));
285 __ vcvt_f64_s32(d4, 2);
286 __ vstr(d4, r4, OFFSET_OF(T, j));
289 __ vldr(d1, r4, OFFSET_OF(T, g));
291 __ vstr(d0, r4, OFFSET_OF(T, g));
292 __ vldr(d2, r4, OFFSET_OF(T, h));
294 __ vstr(d0, r4, OFFSET_OF(T, h));
297 __ vldr(d1, r4, OFFSET_OF(T, m));
299 __ vstr(d0, r4, OFFSET_OF(T, m));
300 __ vldr(d1, r4, OFFSET_OF(T, n));
302 __ vstr(d0, r4, OFFSET_OF(T, n));
304 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
308 Handle<Code> code = isolate->factory()->NewCode(
309 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
313 F3 f = FUNCTION_CAST<F3>(code->entry());
328 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
332 CHECK_EQ(-123.456, t.n);
333 CHECK_EQ(2718.2818, t.m);
335 CHECK_EQ(2718.2818, t.g);
336 CHECK_EQ(31415926.5, t.h);
337 CHECK_EQ(617.0, t.j);
340 CHECK_EQ(1.000000059604644775390625, t.d);
342 CHECK_EQ(-4.1875, t.b);
349 // Test the ARMv7 bitfield instructions.
350 CcTest::InitializeVM();
351 Isolate* isolate = CcTest::i_isolate();
352 HandleScope scope(isolate);
354 Assembler assm(isolate, NULL, 0);
356 if (CpuFeatures::IsSupported(ARMv7)) {
357 CpuFeatureScope scope(&assm, ARMv7);
358 // On entry, r0 = 0xAAAAAAAA = 0b10..10101010.
359 __ ubfx(r0, r0, 1, 12); // 0b00..010101010101 = 0x555
360 __ sbfx(r0, r0, 0, 5); // 0b11..111111110101 = -11
361 __ bfc(r0, 1, 3); // 0b11..111111110001 = -15
362 __ mov(r1, Operand(7));
363 __ bfi(r0, r1, 3, 3); // 0b11..111111111001 = -7
364 __ mov(pc, Operand(lr));
368 Handle<Code> code = isolate->factory()->NewCode(
369 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
373 F1 f = FUNCTION_CAST<F1>(code->entry());
374 int res = reinterpret_cast<int>(
375 CALL_GENERATED_CODE(f, 0xAAAAAAAA, 0, 0, 0, 0));
376 ::printf("f() = %d\n", res);
383 // Test saturating instructions.
384 CcTest::InitializeVM();
385 Isolate* isolate = CcTest::i_isolate();
386 HandleScope scope(isolate);
388 Assembler assm(isolate, NULL, 0);
390 if (CpuFeatures::IsSupported(ARMv7)) {
391 CpuFeatureScope scope(&assm, ARMv7);
392 __ usat(r1, 8, Operand(r0)); // Sat 0xFFFF to 0-255 = 0xFF.
393 __ usat(r2, 12, Operand(r0, ASR, 9)); // Sat (0xFFFF>>9) to 0-4095 = 0x7F.
394 __ usat(r3, 1, Operand(r0, LSL, 16)); // Sat (0xFFFF<<16) to 0-1 = 0x0.
395 __ add(r0, r1, Operand(r2));
396 __ add(r0, r0, Operand(r3));
397 __ mov(pc, Operand(lr));
401 Handle<Code> code = isolate->factory()->NewCode(
402 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
406 F1 f = FUNCTION_CAST<F1>(code->entry());
407 int res = reinterpret_cast<int>(
408 CALL_GENERATED_CODE(f, 0xFFFF, 0, 0, 0, 0));
409 ::printf("f() = %d\n", res);
420 static void TestRoundingMode(VCVTTypes types,
421 VFPRoundingMode mode,
424 bool expected_exception = false) {
425 Isolate* isolate = CcTest::i_isolate();
426 HandleScope scope(isolate);
428 Assembler assm(isolate, NULL, 0);
430 if (CpuFeatures::IsSupported(VFP3)) {
431 CpuFeatureScope scope(&assm, VFP3);
433 Label wrong_exception;
437 __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask));
438 __ orr(r2, r2, Operand(mode));
441 // Load value, convert, and move back result to r0 if everything went well.
445 __ vcvt_s32_f64(s0, d1, kFPSCRRounding);
449 __ vcvt_u32_f64(s0, d1, kFPSCRRounding);
456 // Check for vfp exceptions
458 __ tst(r2, Operand(kVFPExceptionMask));
459 // Check that we behaved as expected.
460 __ b(&wrong_exception,
461 expected_exception ? eq : ne);
462 // There was no exception. Retrieve the result and return.
464 __ mov(pc, Operand(lr));
466 // The exception behaviour is not what we expected.
467 // Load a special value and return.
468 __ bind(&wrong_exception);
469 __ mov(r0, Operand(11223344));
470 __ mov(pc, Operand(lr));
474 Handle<Code> code = isolate->factory()->NewCode(
475 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
479 F1 f = FUNCTION_CAST<F1>(code->entry());
480 int res = reinterpret_cast<int>(
481 CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
482 ::printf("res = %d\n", res);
483 CHECK_EQ(expected, res);
489 CcTest::InitializeVM();
490 // Test vfp rounding modes.
492 // s32_f64 (double to integer).
494 TestRoundingMode(s32_f64, RN, 0, 0);
495 TestRoundingMode(s32_f64, RN, 0.5, 0);
496 TestRoundingMode(s32_f64, RN, -0.5, 0);
497 TestRoundingMode(s32_f64, RN, 1.5, 2);
498 TestRoundingMode(s32_f64, RN, -1.5, -2);
499 TestRoundingMode(s32_f64, RN, 123.7, 124);
500 TestRoundingMode(s32_f64, RN, -123.7, -124);
501 TestRoundingMode(s32_f64, RN, 123456.2, 123456);
502 TestRoundingMode(s32_f64, RN, -123456.2, -123456);
503 TestRoundingMode(s32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
504 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.49), kMaxInt);
505 TestRoundingMode(s32_f64, RN, (kMaxInt + 1.0), kMaxInt, true);
506 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.5), kMaxInt, true);
507 TestRoundingMode(s32_f64, RN, static_cast<double>(kMinInt), kMinInt);
508 TestRoundingMode(s32_f64, RN, (kMinInt - 0.5), kMinInt);
509 TestRoundingMode(s32_f64, RN, (kMinInt - 1.0), kMinInt, true);
510 TestRoundingMode(s32_f64, RN, (kMinInt - 0.51), kMinInt, true);
512 TestRoundingMode(s32_f64, RM, 0, 0);
513 TestRoundingMode(s32_f64, RM, 0.5, 0);
514 TestRoundingMode(s32_f64, RM, -0.5, -1);
515 TestRoundingMode(s32_f64, RM, 123.7, 123);
516 TestRoundingMode(s32_f64, RM, -123.7, -124);
517 TestRoundingMode(s32_f64, RM, 123456.2, 123456);
518 TestRoundingMode(s32_f64, RM, -123456.2, -123457);
519 TestRoundingMode(s32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
520 TestRoundingMode(s32_f64, RM, (kMaxInt + 0.5), kMaxInt);
521 TestRoundingMode(s32_f64, RM, (kMaxInt + 1.0), kMaxInt, true);
522 TestRoundingMode(s32_f64, RM, static_cast<double>(kMinInt), kMinInt);
523 TestRoundingMode(s32_f64, RM, (kMinInt - 0.5), kMinInt, true);
524 TestRoundingMode(s32_f64, RM, (kMinInt + 0.5), kMinInt);
526 TestRoundingMode(s32_f64, RZ, 0, 0);
527 TestRoundingMode(s32_f64, RZ, 0.5, 0);
528 TestRoundingMode(s32_f64, RZ, -0.5, 0);
529 TestRoundingMode(s32_f64, RZ, 123.7, 123);
530 TestRoundingMode(s32_f64, RZ, -123.7, -123);
531 TestRoundingMode(s32_f64, RZ, 123456.2, 123456);
532 TestRoundingMode(s32_f64, RZ, -123456.2, -123456);
533 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
534 TestRoundingMode(s32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
535 TestRoundingMode(s32_f64, RZ, (kMaxInt + 1.0), kMaxInt, true);
536 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMinInt), kMinInt);
537 TestRoundingMode(s32_f64, RZ, (kMinInt - 0.5), kMinInt);
538 TestRoundingMode(s32_f64, RZ, (kMinInt - 1.0), kMinInt, true);
541 // u32_f64 (double to integer).
544 TestRoundingMode(u32_f64, RN, -0.5, 0);
545 TestRoundingMode(u32_f64, RN, -123456.7, 0, true);
546 TestRoundingMode(u32_f64, RN, static_cast<double>(kMinInt), 0, true);
547 TestRoundingMode(u32_f64, RN, kMinInt - 1.0, 0, true);
549 TestRoundingMode(u32_f64, RM, -0.5, 0, true);
550 TestRoundingMode(u32_f64, RM, -123456.7, 0, true);
551 TestRoundingMode(u32_f64, RM, static_cast<double>(kMinInt), 0, true);
552 TestRoundingMode(u32_f64, RM, kMinInt - 1.0, 0, true);
554 TestRoundingMode(u32_f64, RZ, -0.5, 0);
555 TestRoundingMode(u32_f64, RZ, -123456.7, 0, true);
556 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMinInt), 0, true);
557 TestRoundingMode(u32_f64, RZ, kMinInt - 1.0, 0, true);
560 // kMaxInt is the maximum *signed* integer: 0x7fffffff.
561 static const uint32_t kMaxUInt = 0xffffffffu;
562 TestRoundingMode(u32_f64, RZ, 0, 0);
563 TestRoundingMode(u32_f64, RZ, 0.5, 0);
564 TestRoundingMode(u32_f64, RZ, 123.7, 123);
565 TestRoundingMode(u32_f64, RZ, 123456.2, 123456);
566 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
567 TestRoundingMode(u32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
568 TestRoundingMode(u32_f64, RZ, (kMaxInt + 1.0),
569 static_cast<uint32_t>(kMaxInt) + 1);
570 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 0.5), kMaxUInt);
571 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 1.0), kMaxUInt, true);
573 TestRoundingMode(u32_f64, RM, 0, 0);
574 TestRoundingMode(u32_f64, RM, 0.5, 0);
575 TestRoundingMode(u32_f64, RM, 123.7, 123);
576 TestRoundingMode(u32_f64, RM, 123456.2, 123456);
577 TestRoundingMode(u32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
578 TestRoundingMode(u32_f64, RM, (kMaxInt + 0.5), kMaxInt);
579 TestRoundingMode(u32_f64, RM, (kMaxInt + 1.0),
580 static_cast<uint32_t>(kMaxInt) + 1);
581 TestRoundingMode(u32_f64, RM, (kMaxUInt + 0.5), kMaxUInt);
582 TestRoundingMode(u32_f64, RM, (kMaxUInt + 1.0), kMaxUInt, true);
584 TestRoundingMode(u32_f64, RN, 0, 0);
585 TestRoundingMode(u32_f64, RN, 0.5, 0);
586 TestRoundingMode(u32_f64, RN, 1.5, 2);
587 TestRoundingMode(u32_f64, RN, 123.7, 124);
588 TestRoundingMode(u32_f64, RN, 123456.2, 123456);
589 TestRoundingMode(u32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
590 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.49), kMaxInt);
591 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.5),
592 static_cast<uint32_t>(kMaxInt) + 1);
593 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.49), kMaxUInt);
594 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.5), kMaxUInt, true);
595 TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true);
600 // Test VFP multi load/store with ia_w.
601 CcTest::InitializeVM();
602 Isolate* isolate = CcTest::i_isolate();
603 HandleScope scope(isolate);
629 // Create a function that uses vldm/vstm to move some double and
630 // single precision values around in memory.
631 Assembler assm(isolate, NULL, 0);
633 __ mov(ip, Operand(sp));
634 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
635 __ sub(fp, ip, Operand(4));
637 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
638 __ vldm(ia_w, r4, d0, d3);
639 __ vldm(ia_w, r4, d4, d7);
641 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
642 __ vstm(ia_w, r4, d6, d7);
643 __ vstm(ia_w, r4, d0, d5);
645 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
646 __ vldm(ia_w, r4, s0, s3);
647 __ vldm(ia_w, r4, s4, s7);
649 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
650 __ vstm(ia_w, r4, s6, s7);
651 __ vstm(ia_w, r4, s0, s5);
653 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
657 Handle<Code> code = isolate->factory()->NewCode(
658 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
662 F4 fn = FUNCTION_CAST<F4>(code->entry());
681 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
705 // Test VFP multi load/store with ia.
706 CcTest::InitializeVM();
707 Isolate* isolate = CcTest::i_isolate();
708 HandleScope scope(isolate);
734 // Create a function that uses vldm/vstm to move some double and
735 // single precision values around in memory.
736 Assembler assm(isolate, NULL, 0);
738 __ mov(ip, Operand(sp));
739 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
740 __ sub(fp, ip, Operand(4));
742 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
743 __ vldm(ia, r4, d0, d3);
744 __ add(r4, r4, Operand(4 * 8));
745 __ vldm(ia, r4, d4, d7);
747 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
748 __ vstm(ia, r4, d6, d7);
749 __ add(r4, r4, Operand(2 * 8));
750 __ vstm(ia, r4, d0, d5);
752 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
753 __ vldm(ia, r4, s0, s3);
754 __ add(r4, r4, Operand(4 * 4));
755 __ vldm(ia, r4, s4, s7);
757 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
758 __ vstm(ia, r4, s6, s7);
759 __ add(r4, r4, Operand(2 * 4));
760 __ vstm(ia, r4, s0, s5);
762 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
766 Handle<Code> code = isolate->factory()->NewCode(
767 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
771 F4 fn = FUNCTION_CAST<F4>(code->entry());
790 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
814 // Test VFP multi load/store with db_w.
815 CcTest::InitializeVM();
816 Isolate* isolate = CcTest::i_isolate();
817 HandleScope scope(isolate);
843 // Create a function that uses vldm/vstm to move some double and
844 // single precision values around in memory.
845 Assembler assm(isolate, NULL, 0);
847 __ mov(ip, Operand(sp));
848 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
849 __ sub(fp, ip, Operand(4));
851 __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8));
852 __ vldm(db_w, r4, d4, d7);
853 __ vldm(db_w, r4, d0, d3);
855 __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8));
856 __ vstm(db_w, r4, d0, d5);
857 __ vstm(db_w, r4, d6, d7);
859 __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4));
860 __ vldm(db_w, r4, s4, s7);
861 __ vldm(db_w, r4, s0, s3);
863 __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4));
864 __ vstm(db_w, r4, s0, s5);
865 __ vstm(db_w, r4, s6, s7);
867 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
871 Handle<Code> code = isolate->factory()->NewCode(
872 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
876 F4 fn = FUNCTION_CAST<F4>(code->entry());
895 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
919 // Test instructions using the carry flag.
920 CcTest::InitializeVM();
921 Isolate* isolate = CcTest::i_isolate();
922 HandleScope scope(isolate);
935 Assembler assm(isolate, NULL, 0);
937 // Test HeapObject untagging.
938 __ ldr(r1, MemOperand(r0, OFFSET_OF(I, a)));
939 __ mov(r1, Operand(r1, ASR, 1), SetCC);
940 __ adc(r1, r1, Operand(r1), LeaveCC, cs);
941 __ str(r1, MemOperand(r0, OFFSET_OF(I, a)));
943 __ ldr(r2, MemOperand(r0, OFFSET_OF(I, b)));
944 __ mov(r2, Operand(r2, ASR, 1), SetCC);
945 __ adc(r2, r2, Operand(r2), LeaveCC, cs);
946 __ str(r2, MemOperand(r0, OFFSET_OF(I, b)));
948 // Test corner cases.
949 __ mov(r1, Operand(0xffffffff));
950 __ mov(r2, Operand::Zero());
951 __ mov(r3, Operand(r1, ASR, 1), SetCC); // Set the carry.
952 __ adc(r3, r1, Operand(r2));
953 __ str(r3, MemOperand(r0, OFFSET_OF(I, c)));
955 __ mov(r1, Operand(0xffffffff));
956 __ mov(r2, Operand::Zero());
957 __ mov(r3, Operand(r2, ASR, 1), SetCC); // Unset the carry.
958 __ adc(r3, r1, Operand(r2));
959 __ str(r3, MemOperand(r0, OFFSET_OF(I, d)));
961 __ mov(pc, Operand(lr));
965 Handle<Code> code = isolate->factory()->NewCode(
966 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
970 F3 f = FUNCTION_CAST<F3>(code->entry());
971 Object* dummy = CALL_GENERATED_CODE(f, &i, 0, 0, 0, 0);
974 CHECK_EQ(0xabcd0001, i.a);
975 CHECK_EQ(static_cast<int32_t>(0xabcd0000) >> 1, i.b);
976 CHECK_EQ(0x00000000, i.c);
977 CHECK_EQ(0xffffffff, i.d);
982 // Test chaining of label usages within instructions (issue 1644).
983 CcTest::InitializeVM();
984 Isolate* isolate = CcTest::i_isolate();
985 HandleScope scope(isolate);
987 Assembler assm(isolate, NULL, 0);
997 // Test VFP instructions using registers d16-d31.
998 CcTest::InitializeVM();
999 Isolate* isolate = CcTest::i_isolate();
1000 HandleScope scope(isolate);
1002 if (!CpuFeatures::IsSupported(VFP32DREGS)) {
1021 // Create a function that accepts &t, and loads, manipulates, and stores
1022 // the doubles and floats.
1023 Assembler assm(isolate, NULL, 0);
1027 if (CpuFeatures::IsSupported(VFP3)) {
1028 CpuFeatureScope scope(&assm, VFP3);
1030 __ stm(db_w, sp, r4.bit() | lr.bit());
1032 // Load a, b, c into d16, d17, d18.
1033 __ mov(r4, Operand(r0));
1034 __ vldr(d16, r4, OFFSET_OF(T, a));
1035 __ vldr(d17, r4, OFFSET_OF(T, b));
1036 __ vldr(d18, r4, OFFSET_OF(T, c));
1039 __ vadd(d25, d25, d17);
1040 __ vsub(d25, d25, d18);
1041 __ vmul(d25, d25, d25);
1042 __ vdiv(d25, d25, d18);
1048 __ vmla(d18, d16, d17);
1050 // Store d16, d17, d18 into a, b, c.
1051 __ mov(r4, Operand(r0));
1052 __ vstr(d16, r4, OFFSET_OF(T, a));
1053 __ vstr(d17, r4, OFFSET_OF(T, b));
1054 __ vstr(d18, r4, OFFSET_OF(T, c));
1056 // Load x, y, z into d29-d31.
1057 __ add(r4, r0, Operand(OFFSET_OF(T, x)));
1058 __ vldm(ia_w, r4, d29, d31);
1060 // Swap d29 and d30 via r registers.
1061 __ vmov(r1, r2, d29);
1063 __ vmov(d30, r1, r2);
1065 // Convert to and from integer.
1066 __ vcvt_s32_f64(s1, d31);
1067 __ vcvt_f64_u32(d31, s1);
1069 // Store d29-d31 into x, y, z.
1070 __ add(r4, r0, Operand(OFFSET_OF(T, x)));
1071 __ vstm(ia_w, r4, d29, d31);
1073 // Move constants into d20, d21, d22 and store into i, j, k.
1074 __ vmov(d20, 14.7610017472335499);
1076 __ mov(r1, Operand(372106121));
1077 __ mov(r2, Operand(1079146608));
1078 __ vmov(d22, VmovIndexLo, r1);
1079 __ vmov(d22, VmovIndexHi, r2);
1080 __ add(r4, r0, Operand(OFFSET_OF(T, i)));
1081 __ vstm(ia_w, r4, d20, d22);
1082 // Move d22 into low and high.
1083 __ vmov(r4, VmovIndexLo, d22);
1084 __ str(r4, MemOperand(r0, OFFSET_OF(T, low)));
1085 __ vmov(r4, VmovIndexHi, d22);
1086 __ str(r4, MemOperand(r0, OFFSET_OF(T, high)));
1088 __ ldm(ia_w, sp, r4.bit() | pc.bit());
1091 assm.GetCode(&desc);
1092 Handle<Code> code = isolate->factory()->NewCode(
1093 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1097 F3 f = FUNCTION_CAST<F3>(code->entry());
1104 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1106 CHECK_EQ(14.7610017472335499, t.a);
1107 CHECK_EQ(3.84200491244266251, t.b);
1108 CHECK_EQ(73.8818412254460241, t.c);
1109 CHECK_EQ(2.75, t.x);
1111 CHECK_EQ(17.0, t.z);
1112 CHECK_EQ(14.7610017472335499, t.i);
1113 CHECK_EQ(16.0, t.j);
1114 CHECK_EQ(73.8818412254460241, t.k);
1115 CHECK_EQ(372106121, t.low);
1116 CHECK_EQ(1079146608, t.high);
1122 // Test the VFP Canonicalized Nan mode.
1123 CcTest::InitializeVM();
1124 Isolate* isolate = CcTest::i_isolate();
1125 HandleScope scope(isolate);
1137 // Create a function that makes the four basic operations.
1138 Assembler assm(isolate, NULL, 0);
1140 // Ensure FPSCR state (as JSEntryStub does).
1143 __ tst(r1, Operand(kVFPDefaultNaNModeControlBit));
1144 __ b(ne, &fpscr_done);
1145 __ orr(r1, r1, Operand(kVFPDefaultNaNModeControlBit));
1147 __ bind(&fpscr_done);
1149 __ vldr(d0, r0, OFFSET_OF(T, left));
1150 __ vldr(d1, r0, OFFSET_OF(T, right));
1151 __ vadd(d2, d0, d1);
1152 __ vstr(d2, r0, OFFSET_OF(T, add_result));
1153 __ vsub(d2, d0, d1);
1154 __ vstr(d2, r0, OFFSET_OF(T, sub_result));
1155 __ vmul(d2, d0, d1);
1156 __ vstr(d2, r0, OFFSET_OF(T, mul_result));
1157 __ vdiv(d2, d0, d1);
1158 __ vstr(d2, r0, OFFSET_OF(T, div_result));
1160 __ mov(pc, Operand(lr));
1163 assm.GetCode(&desc);
1164 Handle<Code> code = isolate->factory()->NewCode(
1165 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1169 F3 f = FUNCTION_CAST<F3>(code->entry());
1170 t.left = BitCast<double>(kHoleNanInt64);
1176 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1178 const uint32_t kArmNanUpper32 = 0x7ff80000;
1179 const uint32_t kArmNanLower32 = 0x00000000;
1181 const uint64_t kArmNanInt64 =
1182 (static_cast<uint64_t>(kArmNanUpper32) << 32) | kArmNanLower32;
1183 ASSERT(kArmNanInt64 != kHoleNanInt64);
1185 // With VFP2 the sign of the canonicalized Nan is undefined. So
1186 // we remove the sign bit for the upper tests.
1187 CHECK_EQ(kArmNanUpper32, (BitCast<int64_t>(t.add_result) >> 32) & 0x7fffffff);
1188 CHECK_EQ(kArmNanLower32, BitCast<int64_t>(t.add_result) & 0xffffffffu);
1189 CHECK_EQ(kArmNanUpper32, (BitCast<int64_t>(t.sub_result) >> 32) & 0x7fffffff);
1190 CHECK_EQ(kArmNanLower32, BitCast<int64_t>(t.sub_result) & 0xffffffffu);
1191 CHECK_EQ(kArmNanUpper32, (BitCast<int64_t>(t.mul_result) >> 32) & 0x7fffffff);
1192 CHECK_EQ(kArmNanLower32, BitCast<int64_t>(t.mul_result) & 0xffffffffu);
1193 CHECK_EQ(kArmNanUpper32, (BitCast<int64_t>(t.div_result) >> 32) & 0x7fffffff);
1194 CHECK_EQ(kArmNanLower32, BitCast<int64_t>(t.div_result) & 0xffffffffu);
1199 // Test the Neon instructions.
1200 CcTest::InitializeVM();
1201 Isolate* isolate = CcTest::i_isolate();
1202 HandleScope scope(isolate);
1234 // Create a function that accepts &t, and loads, manipulates, and stores
1235 // the doubles and floats.
1236 Assembler assm(isolate, NULL, 0);
1239 if (CpuFeatures::IsSupported(NEON)) {
1240 CpuFeatureScope scope(&assm, NEON);
1242 __ stm(db_w, sp, r4.bit() | lr.bit());
1243 // Move 32 bytes with neon.
1244 __ add(r4, r0, Operand(OFFSET_OF(T, src0)));
1245 __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4));
1246 __ add(r4, r0, Operand(OFFSET_OF(T, dst0)));
1247 __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4));
1249 // Expand 8 bytes into 8 words(16 bits).
1250 __ add(r4, r0, Operand(OFFSET_OF(T, srcA0)));
1251 __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(r4));
1252 __ vmovl(NeonU8, q0, d0);
1253 __ add(r4, r0, Operand(OFFSET_OF(T, dstA0)));
1254 __ vst1(Neon8, NeonListOperand(d0, 2), NeonMemOperand(r4));
1256 // The same expansion, but with different source and destination registers.
1257 __ add(r4, r0, Operand(OFFSET_OF(T, srcA0)));
1258 __ vld1(Neon8, NeonListOperand(d1), NeonMemOperand(r4));
1259 __ vmovl(NeonU8, q1, d1);
1260 __ add(r4, r0, Operand(OFFSET_OF(T, dstA4)));
1261 __ vst1(Neon8, NeonListOperand(d2, 2), NeonMemOperand(r4));
1263 __ ldm(ia_w, sp, r4.bit() | pc.bit());
1266 assm.GetCode(&desc);
1267 Handle<Code> code = isolate->factory()->NewCode(
1268 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1272 F3 f = FUNCTION_CAST<F3>(code->entry());
1273 t.src0 = 0x01020304;
1274 t.src1 = 0x11121314;
1275 t.src2 = 0x21222324;
1276 t.src3 = 0x31323334;
1277 t.src4 = 0x41424344;
1278 t.src5 = 0x51525354;
1279 t.src6 = 0x61626364;
1280 t.src7 = 0x71727374;
1289 t.srcA0 = 0x41424344;
1290 t.srcA1 = 0x81828384;
1299 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1301 CHECK_EQ(0x01020304, t.dst0);
1302 CHECK_EQ(0x11121314, t.dst1);
1303 CHECK_EQ(0x21222324, t.dst2);
1304 CHECK_EQ(0x31323334, t.dst3);
1305 CHECK_EQ(0x41424344, t.dst4);
1306 CHECK_EQ(0x51525354, t.dst5);
1307 CHECK_EQ(0x61626364, t.dst6);
1308 CHECK_EQ(0x71727374, t.dst7);
1309 CHECK_EQ(0x00430044, t.dstA0);
1310 CHECK_EQ(0x00410042, t.dstA1);
1311 CHECK_EQ(0x00830084, t.dstA2);
1312 CHECK_EQ(0x00810082, t.dstA3);
1313 CHECK_EQ(0x00430044, t.dstA4);
1314 CHECK_EQ(0x00410042, t.dstA5);
1315 CHECK_EQ(0x00830084, t.dstA6);
1316 CHECK_EQ(0x00810082, t.dstA7);
1322 // Test the pkh, uxtb, uxtab and uxtb16 instructions.
1323 CcTest::InitializeVM();
1324 Isolate* isolate = CcTest::i_isolate();
1325 HandleScope scope(isolate);
1339 // Create a function that accepts &t, and loads, manipulates, and stores
1340 // the doubles and floats.
1341 Assembler assm(isolate, NULL, 0);
1343 __ stm(db_w, sp, r4.bit() | lr.bit());
1345 __ mov(r4, Operand(r0));
1346 __ ldr(r0, MemOperand(r4, OFFSET_OF(T, src0)));
1347 __ ldr(r1, MemOperand(r4, OFFSET_OF(T, src1)));
1349 __ pkhbt(r2, r0, Operand(r1, LSL, 8));
1350 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst0)));
1352 __ pkhtb(r2, r0, Operand(r1, ASR, 8));
1353 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst1)));
1355 __ uxtb16(r2, Operand(r0, ROR, 8));
1356 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst2)));
1358 __ uxtb(r2, Operand(r0, ROR, 8));
1359 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst3)));
1361 __ ldr(r0, MemOperand(r4, OFFSET_OF(T, src2)));
1362 __ uxtab(r2, r0, Operand(r1, ROR, 8));
1363 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst4)));
1365 __ ldm(ia_w, sp, r4.bit() | pc.bit());
1368 assm.GetCode(&desc);
1369 Handle<Code> code = isolate->factory()->NewCode(
1370 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1374 F3 f = FUNCTION_CAST<F3>(code->entry());
1375 t.src0 = 0x01020304;
1376 t.src1 = 0x11121314;
1377 t.src2 = 0x11121300;
1383 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1385 CHECK_EQ(0x12130304, t.dst0);
1386 CHECK_EQ(0x01021213, t.dst1);
1387 CHECK_EQ(0x00010003, t.dst2);
1388 CHECK_EQ(0x00000003, t.dst3);
1389 CHECK_EQ(0x11121313, t.dst4);
1394 // Test generating labels at high addresses.
1395 // Should not assert.
1396 CcTest::InitializeVM();
1397 Isolate* isolate = CcTest::i_isolate();
1398 HandleScope scope(isolate);
1400 // Generate a code segment that will be longer than 2^24 bytes.
1401 Assembler assm(isolate, NULL, 0);
1402 for (size_t i = 0; i < 1 << 23 ; ++i) { // 2^23
1413 #define TEST_SDIV(expected_, dividend_, divisor_) \
1414 t.dividend = dividend_; \
1415 t.divisor = divisor_; \
1417 dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); \
1418 CHECK_EQ(expected_, t.result);
1423 CcTest::InitializeVM();
1424 Isolate* isolate = CcTest::i_isolate();
1425 HandleScope scope(isolate);
1434 Assembler assm(isolate, NULL, 0);
1436 if (CpuFeatures::IsSupported(SUDIV)) {
1437 CpuFeatureScope scope(&assm, SUDIV);
1439 __ mov(r3, Operand(r0));
1441 __ ldr(r0, MemOperand(r3, OFFSET_OF(T, dividend)));
1442 __ ldr(r1, MemOperand(r3, OFFSET_OF(T, divisor)));
1444 __ sdiv(r2, r0, r1);
1445 __ str(r2, MemOperand(r3, OFFSET_OF(T, result)));
1450 assm.GetCode(&desc);
1451 Handle<Code> code = isolate->factory()->NewCode(
1452 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1456 F3 f = FUNCTION_CAST<F3>(code->entry());
1458 TEST_SDIV(1073741824, kMinInt, -2);
1459 TEST_SDIV(kMinInt, kMinInt, -1);
1460 TEST_SDIV(5, 10, 2);
1461 TEST_SDIV(3, 10, 3);
1462 TEST_SDIV(-5, 10, -2);
1463 TEST_SDIV(-3, 10, -3);
1464 TEST_SDIV(-5, -10, 2);
1465 TEST_SDIV(-3, -10, 3);
1466 TEST_SDIV(5, -10, -2);
1467 TEST_SDIV(3, -10, -3);
1476 TEST(code_relative_offset) {
1477 // Test extracting the offset of a label from the beginning of the code
1479 CcTest::InitializeVM();
1480 Isolate* isolate = CcTest::i_isolate();
1481 HandleScope scope(isolate);
1482 // Initialize a code object that will contain the code.
1483 Handle<Object> code_object(isolate->heap()->undefined_value(), isolate);
1485 Assembler assm(isolate, NULL, 0);
1487 Label start, target_away, target_faraway;
1489 __ stm(db_w, sp, r4.bit() | r5.bit() | lr.bit());
1491 // r3 is used as the address zero, the test will crash when we load it.
1492 __ mov(r3, Operand::Zero());
1494 // r5 will be a pointer to the start of the code.
1495 __ mov(r5, Operand(code_object));
1496 __ mov_label_offset(r4, &start);
1498 __ mov_label_offset(r1, &target_faraway);
1499 __ str(r1, MemOperand(sp, kPointerSize, NegPreIndex));
1501 __ mov_label_offset(r1, &target_away);
1503 // Jump straight to 'target_away' the first time and use the relative
1504 // position the second time. This covers the case when extracting the
1505 // position of a label which is linked.
1506 __ mov(r2, Operand::Zero());
1508 __ cmp(r2, Operand::Zero());
1509 __ b(eq, &target_away);
1511 // Emit invalid instructions to push the label between 2^8 and 2^16
1512 // instructions away. The test will crash if they are reached.
1513 for (int i = 0; i < (1 << 10); i++) {
1514 __ ldr(r3, MemOperand(r3));
1516 __ bind(&target_away);
1517 // This will be hit twice: r0 = r0 + 5 + 5.
1518 __ add(r0, r0, Operand(5));
1520 __ ldr(r1, MemOperand(sp, kPointerSize, PostIndex), ne);
1521 __ add(pc, r5, r4, LeaveCC, ne);
1523 __ mov(r2, Operand(1));
1525 // Emit invalid instructions to push the label between 2^16 and 2^24
1526 // instructions away. The test will crash if they are reached.
1527 for (int i = 0; i < (1 << 21); i++) {
1528 __ ldr(r3, MemOperand(r3));
1530 __ bind(&target_faraway);
1531 // r0 = r0 + 5 + 5 + 11
1532 __ add(r0, r0, Operand(11));
1534 __ ldm(ia_w, sp, r4.bit() | r5.bit() | pc.bit());
1537 assm.GetCode(&desc);
1538 Handle<Code> code = isolate->factory()->NewCode(
1539 desc, Code::ComputeFlags(Code::STUB), code_object);
1540 F1 f = FUNCTION_CAST<F1>(code->entry());
1541 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 21, 0, 0, 0, 0));
1542 ::printf("f() = %d\n", res);