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.
28 #include <iostream> // NOLINT(readability/streams)
31 #include "test/cctest/cctest.h"
33 #include "src/arm/assembler-arm-inl.h"
34 #include "src/arm/simulator-arm.h"
35 #include "src/disassembler.h"
36 #include "src/factory.h"
37 #include "src/ostreams.h"
39 using namespace v8::base;
40 using namespace v8::internal;
43 // Define these function prototypes to match JSEntryFunction in execution.cc.
44 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
45 typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
46 typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4);
47 typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4);
53 CcTest::InitializeVM();
54 Isolate* isolate = CcTest::i_isolate();
55 HandleScope scope(isolate);
57 Assembler assm(isolate, NULL, 0);
59 __ add(r0, r0, Operand(r1));
60 __ mov(pc, Operand(lr));
64 Handle<Code> code = isolate->factory()->NewCode(
65 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
70 F2 f = FUNCTION_CAST<F2>(code->entry());
71 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 3, 4, 0, 0, 0));
72 ::printf("f() = %d\n", res);
78 CcTest::InitializeVM();
79 Isolate* isolate = CcTest::i_isolate();
80 HandleScope scope(isolate);
82 Assembler assm(isolate, NULL, 0);
85 __ mov(r1, Operand(r0));
86 __ mov(r0, Operand::Zero());
90 __ add(r0, r0, Operand(r1));
91 __ sub(r1, r1, Operand(1));
94 __ teq(r1, Operand::Zero());
96 __ mov(pc, Operand(lr));
100 Handle<Code> code = isolate->factory()->NewCode(
101 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
106 F1 f = FUNCTION_CAST<F1>(code->entry());
107 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 100, 0, 0, 0, 0));
108 ::printf("f() = %d\n", res);
114 CcTest::InitializeVM();
115 Isolate* isolate = CcTest::i_isolate();
116 HandleScope scope(isolate);
118 Assembler assm(isolate, NULL, 0);
121 __ mov(r1, Operand(r0));
122 __ mov(r0, Operand(1));
127 __ sub(r1, r1, Operand(1));
130 __ teq(r1, Operand::Zero());
132 __ mov(pc, Operand(lr));
134 // some relocated stuff here, not executed
135 __ RecordComment("dead code, just testing relocations");
136 __ mov(r0, Operand(isolate->factory()->true_value()));
137 __ RecordComment("dead code, just testing immediate operands");
138 __ mov(r0, Operand(-1));
139 __ mov(r0, Operand(0xFF000000));
140 __ mov(r0, Operand(0xF0F0F0F0));
141 __ mov(r0, Operand(0xFFF0FFFF));
145 Handle<Code> code = isolate->factory()->NewCode(
146 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
151 F1 f = FUNCTION_CAST<F1>(code->entry());
152 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 10, 0, 0, 0, 0));
153 ::printf("f() = %d\n", res);
154 CHECK_EQ(3628800, res);
159 CcTest::InitializeVM();
160 Isolate* isolate = CcTest::i_isolate();
161 HandleScope scope(isolate);
170 Assembler assm(isolate, NULL, 0);
173 __ mov(ip, Operand(sp));
174 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
175 __ sub(fp, ip, Operand(4));
176 __ mov(r4, Operand(r0));
177 __ ldr(r0, MemOperand(r4, OFFSET_OF(T, i)));
178 __ mov(r2, Operand(r0, ASR, 1));
179 __ str(r2, MemOperand(r4, OFFSET_OF(T, i)));
180 __ ldrsb(r2, MemOperand(r4, OFFSET_OF(T, c)));
181 __ add(r0, r2, Operand(r0));
182 __ mov(r2, Operand(r2, LSL, 2));
183 __ strb(r2, MemOperand(r4, OFFSET_OF(T, c)));
184 __ ldrsh(r2, MemOperand(r4, OFFSET_OF(T, s)));
185 __ add(r0, r2, Operand(r0));
186 __ mov(r2, Operand(r2, ASR, 3));
187 __ strh(r2, MemOperand(r4, OFFSET_OF(T, s)));
188 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
192 Handle<Code> code = isolate->factory()->NewCode(
193 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
198 F3 f = FUNCTION_CAST<F3>(code->entry());
202 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0));
203 ::printf("f() = %d\n", res);
204 CHECK_EQ(101010, res);
205 CHECK_EQ(100000/2, t.i);
207 CHECK_EQ(1000/8, t.s);
212 // Test the VFP floating point instructions.
213 CcTest::InitializeVM();
214 Isolate* isolate = CcTest::i_isolate();
215 HandleScope scope(isolate);
235 // Create a function that accepts &t, and loads, manipulates, and stores
236 // the doubles and floats.
237 Assembler assm(isolate, NULL, 0);
241 if (CpuFeatures::IsSupported(VFP3)) {
242 CpuFeatureScope scope(&assm, VFP3);
244 __ mov(ip, Operand(sp));
245 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
246 __ sub(fp, ip, Operand(4));
248 __ mov(r4, Operand(r0));
249 __ vldr(d6, r4, OFFSET_OF(T, a));
250 __ vldr(d7, r4, OFFSET_OF(T, b));
252 __ vstr(d5, r4, OFFSET_OF(T, c));
259 __ vstr(d4, r4, OFFSET_OF(T, b));
261 // Load t.x and t.y, switch values, and store back to the struct.
262 __ vldr(s0, r4, OFFSET_OF(T, x));
263 __ vldr(s31, r4, OFFSET_OF(T, y));
267 __ vstr(s0, r4, OFFSET_OF(T, x));
268 __ vstr(s31, r4, OFFSET_OF(T, y));
270 // Move a literal into a register that can be encoded in the instruction.
272 __ vstr(d4, r4, OFFSET_OF(T, e));
274 // Move a literal into a register that requires 64 bits to encode.
275 // 0x3ff0000010000000 = 1.000000059604644775390625
276 __ vmov(d4, 1.000000059604644775390625);
277 __ vstr(d4, r4, OFFSET_OF(T, d));
279 // Convert from floating point to integer.
281 __ vcvt_s32_f64(s31, d4);
282 __ vstr(s31, r4, OFFSET_OF(T, i));
284 // Convert from integer to floating point.
285 __ mov(lr, Operand(42));
287 __ vcvt_f64_s32(d4, s31);
288 __ vstr(d4, r4, OFFSET_OF(T, f));
290 // Convert from fixed point to floating point.
291 __ mov(lr, Operand(2468));
293 __ vcvt_f64_s32(d4, 2);
294 __ vstr(d4, r4, OFFSET_OF(T, j));
297 __ vldr(d1, r4, OFFSET_OF(T, g));
299 __ vstr(d0, r4, OFFSET_OF(T, g));
300 __ vldr(d2, r4, OFFSET_OF(T, h));
302 __ vstr(d0, r4, OFFSET_OF(T, h));
305 __ vldr(d1, r4, OFFSET_OF(T, m));
307 __ vstr(d0, r4, OFFSET_OF(T, m));
308 __ vldr(d1, r4, OFFSET_OF(T, n));
310 __ vstr(d0, r4, OFFSET_OF(T, n));
312 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
316 Handle<Code> code = isolate->factory()->NewCode(
317 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
322 F3 f = FUNCTION_CAST<F3>(code->entry());
337 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
341 CHECK_EQ(-123.456, t.n);
342 CHECK_EQ(2718.2818, t.m);
344 CHECK_EQ(2718.2818, t.g);
345 CHECK_EQ(31415926.5, t.h);
346 CHECK_EQ(617.0, t.j);
349 CHECK_EQ(1.000000059604644775390625, t.d);
351 CHECK_EQ(-4.1875, t.b);
358 // Test the ARMv7 bitfield instructions.
359 CcTest::InitializeVM();
360 Isolate* isolate = CcTest::i_isolate();
361 HandleScope scope(isolate);
363 Assembler assm(isolate, NULL, 0);
365 if (CpuFeatures::IsSupported(ARMv7)) {
366 CpuFeatureScope scope(&assm, ARMv7);
367 // On entry, r0 = 0xAAAAAAAA = 0b10..10101010.
368 __ ubfx(r0, r0, 1, 12); // 0b00..010101010101 = 0x555
369 __ sbfx(r0, r0, 0, 5); // 0b11..111111110101 = -11
370 __ bfc(r0, 1, 3); // 0b11..111111110001 = -15
371 __ mov(r1, Operand(7));
372 __ bfi(r0, r1, 3, 3); // 0b11..111111111001 = -7
373 __ mov(pc, Operand(lr));
377 Handle<Code> code = isolate->factory()->NewCode(
378 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
383 F1 f = FUNCTION_CAST<F1>(code->entry());
384 int res = reinterpret_cast<int>(
385 CALL_GENERATED_CODE(f, 0xAAAAAAAA, 0, 0, 0, 0));
386 ::printf("f() = %d\n", res);
393 // Test saturating instructions.
394 CcTest::InitializeVM();
395 Isolate* isolate = CcTest::i_isolate();
396 HandleScope scope(isolate);
398 Assembler assm(isolate, NULL, 0);
400 if (CpuFeatures::IsSupported(ARMv7)) {
401 CpuFeatureScope scope(&assm, ARMv7);
402 __ usat(r1, 8, Operand(r0)); // Sat 0xFFFF to 0-255 = 0xFF.
403 __ usat(r2, 12, Operand(r0, ASR, 9)); // Sat (0xFFFF>>9) to 0-4095 = 0x7F.
404 __ usat(r3, 1, Operand(r0, LSL, 16)); // Sat (0xFFFF<<16) to 0-1 = 0x0.
405 __ add(r0, r1, Operand(r2));
406 __ add(r0, r0, Operand(r3));
407 __ mov(pc, Operand(lr));
411 Handle<Code> code = isolate->factory()->NewCode(
412 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
417 F1 f = FUNCTION_CAST<F1>(code->entry());
418 int res = reinterpret_cast<int>(
419 CALL_GENERATED_CODE(f, 0xFFFF, 0, 0, 0, 0));
420 ::printf("f() = %d\n", res);
431 static void TestRoundingMode(VCVTTypes types,
432 VFPRoundingMode mode,
435 bool expected_exception = false) {
436 Isolate* isolate = CcTest::i_isolate();
437 HandleScope scope(isolate);
439 Assembler assm(isolate, NULL, 0);
441 if (CpuFeatures::IsSupported(VFP3)) {
442 CpuFeatureScope scope(&assm, VFP3);
444 Label wrong_exception;
448 __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask));
449 __ orr(r2, r2, Operand(mode));
452 // Load value, convert, and move back result to r0 if everything went well.
456 __ vcvt_s32_f64(s0, d1, kFPSCRRounding);
460 __ vcvt_u32_f64(s0, d1, kFPSCRRounding);
467 // Check for vfp exceptions
469 __ tst(r2, Operand(kVFPExceptionMask));
470 // Check that we behaved as expected.
471 __ b(&wrong_exception,
472 expected_exception ? eq : ne);
473 // There was no exception. Retrieve the result and return.
475 __ mov(pc, Operand(lr));
477 // The exception behaviour is not what we expected.
478 // Load a special value and return.
479 __ bind(&wrong_exception);
480 __ mov(r0, Operand(11223344));
481 __ mov(pc, Operand(lr));
485 Handle<Code> code = isolate->factory()->NewCode(
486 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
491 F1 f = FUNCTION_CAST<F1>(code->entry());
492 int res = reinterpret_cast<int>(
493 CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
494 ::printf("res = %d\n", res);
495 CHECK_EQ(expected, res);
501 CcTest::InitializeVM();
502 // Test vfp rounding modes.
504 // s32_f64 (double to integer).
506 TestRoundingMode(s32_f64, RN, 0, 0);
507 TestRoundingMode(s32_f64, RN, 0.5, 0);
508 TestRoundingMode(s32_f64, RN, -0.5, 0);
509 TestRoundingMode(s32_f64, RN, 1.5, 2);
510 TestRoundingMode(s32_f64, RN, -1.5, -2);
511 TestRoundingMode(s32_f64, RN, 123.7, 124);
512 TestRoundingMode(s32_f64, RN, -123.7, -124);
513 TestRoundingMode(s32_f64, RN, 123456.2, 123456);
514 TestRoundingMode(s32_f64, RN, -123456.2, -123456);
515 TestRoundingMode(s32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
516 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.49), kMaxInt);
517 TestRoundingMode(s32_f64, RN, (kMaxInt + 1.0), kMaxInt, true);
518 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.5), kMaxInt, true);
519 TestRoundingMode(s32_f64, RN, static_cast<double>(kMinInt), kMinInt);
520 TestRoundingMode(s32_f64, RN, (kMinInt - 0.5), kMinInt);
521 TestRoundingMode(s32_f64, RN, (kMinInt - 1.0), kMinInt, true);
522 TestRoundingMode(s32_f64, RN, (kMinInt - 0.51), kMinInt, true);
524 TestRoundingMode(s32_f64, RM, 0, 0);
525 TestRoundingMode(s32_f64, RM, 0.5, 0);
526 TestRoundingMode(s32_f64, RM, -0.5, -1);
527 TestRoundingMode(s32_f64, RM, 123.7, 123);
528 TestRoundingMode(s32_f64, RM, -123.7, -124);
529 TestRoundingMode(s32_f64, RM, 123456.2, 123456);
530 TestRoundingMode(s32_f64, RM, -123456.2, -123457);
531 TestRoundingMode(s32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
532 TestRoundingMode(s32_f64, RM, (kMaxInt + 0.5), kMaxInt);
533 TestRoundingMode(s32_f64, RM, (kMaxInt + 1.0), kMaxInt, true);
534 TestRoundingMode(s32_f64, RM, static_cast<double>(kMinInt), kMinInt);
535 TestRoundingMode(s32_f64, RM, (kMinInt - 0.5), kMinInt, true);
536 TestRoundingMode(s32_f64, RM, (kMinInt + 0.5), kMinInt);
538 TestRoundingMode(s32_f64, RZ, 0, 0);
539 TestRoundingMode(s32_f64, RZ, 0.5, 0);
540 TestRoundingMode(s32_f64, RZ, -0.5, 0);
541 TestRoundingMode(s32_f64, RZ, 123.7, 123);
542 TestRoundingMode(s32_f64, RZ, -123.7, -123);
543 TestRoundingMode(s32_f64, RZ, 123456.2, 123456);
544 TestRoundingMode(s32_f64, RZ, -123456.2, -123456);
545 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
546 TestRoundingMode(s32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
547 TestRoundingMode(s32_f64, RZ, (kMaxInt + 1.0), kMaxInt, true);
548 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMinInt), kMinInt);
549 TestRoundingMode(s32_f64, RZ, (kMinInt - 0.5), kMinInt);
550 TestRoundingMode(s32_f64, RZ, (kMinInt - 1.0), kMinInt, true);
553 // u32_f64 (double to integer).
556 TestRoundingMode(u32_f64, RN, -0.5, 0);
557 TestRoundingMode(u32_f64, RN, -123456.7, 0, true);
558 TestRoundingMode(u32_f64, RN, static_cast<double>(kMinInt), 0, true);
559 TestRoundingMode(u32_f64, RN, kMinInt - 1.0, 0, true);
561 TestRoundingMode(u32_f64, RM, -0.5, 0, true);
562 TestRoundingMode(u32_f64, RM, -123456.7, 0, true);
563 TestRoundingMode(u32_f64, RM, static_cast<double>(kMinInt), 0, true);
564 TestRoundingMode(u32_f64, RM, kMinInt - 1.0, 0, true);
566 TestRoundingMode(u32_f64, RZ, -0.5, 0);
567 TestRoundingMode(u32_f64, RZ, -123456.7, 0, true);
568 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMinInt), 0, true);
569 TestRoundingMode(u32_f64, RZ, kMinInt - 1.0, 0, true);
572 // kMaxInt is the maximum *signed* integer: 0x7fffffff.
573 static const uint32_t kMaxUInt = 0xffffffffu;
574 TestRoundingMode(u32_f64, RZ, 0, 0);
575 TestRoundingMode(u32_f64, RZ, 0.5, 0);
576 TestRoundingMode(u32_f64, RZ, 123.7, 123);
577 TestRoundingMode(u32_f64, RZ, 123456.2, 123456);
578 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
579 TestRoundingMode(u32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
580 TestRoundingMode(u32_f64, RZ, (kMaxInt + 1.0),
581 static_cast<uint32_t>(kMaxInt) + 1);
582 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 0.5), kMaxUInt);
583 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 1.0), kMaxUInt, true);
585 TestRoundingMode(u32_f64, RM, 0, 0);
586 TestRoundingMode(u32_f64, RM, 0.5, 0);
587 TestRoundingMode(u32_f64, RM, 123.7, 123);
588 TestRoundingMode(u32_f64, RM, 123456.2, 123456);
589 TestRoundingMode(u32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
590 TestRoundingMode(u32_f64, RM, (kMaxInt + 0.5), kMaxInt);
591 TestRoundingMode(u32_f64, RM, (kMaxInt + 1.0),
592 static_cast<uint32_t>(kMaxInt) + 1);
593 TestRoundingMode(u32_f64, RM, (kMaxUInt + 0.5), kMaxUInt);
594 TestRoundingMode(u32_f64, RM, (kMaxUInt + 1.0), kMaxUInt, true);
596 TestRoundingMode(u32_f64, RN, 0, 0);
597 TestRoundingMode(u32_f64, RN, 0.5, 0);
598 TestRoundingMode(u32_f64, RN, 1.5, 2);
599 TestRoundingMode(u32_f64, RN, 123.7, 124);
600 TestRoundingMode(u32_f64, RN, 123456.2, 123456);
601 TestRoundingMode(u32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
602 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.49), kMaxInt);
603 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.5),
604 static_cast<uint32_t>(kMaxInt) + 1);
605 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.49), kMaxUInt);
606 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.5), kMaxUInt, true);
607 TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true);
612 // Test VFP multi load/store with ia_w.
613 CcTest::InitializeVM();
614 Isolate* isolate = CcTest::i_isolate();
615 HandleScope scope(isolate);
641 // Create a function that uses vldm/vstm to move some double and
642 // single precision values around in memory.
643 Assembler assm(isolate, NULL, 0);
645 __ mov(ip, Operand(sp));
646 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
647 __ sub(fp, ip, Operand(4));
649 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
650 __ vldm(ia_w, r4, d0, d3);
651 __ vldm(ia_w, r4, d4, d7);
653 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
654 __ vstm(ia_w, r4, d6, d7);
655 __ vstm(ia_w, r4, d0, d5);
657 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
658 __ vldm(ia_w, r4, s0, s3);
659 __ vldm(ia_w, r4, s4, s7);
661 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
662 __ vstm(ia_w, r4, s6, s7);
663 __ vstm(ia_w, r4, s0, s5);
665 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
669 Handle<Code> code = isolate->factory()->NewCode(
670 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
675 F4 fn = FUNCTION_CAST<F4>(code->entry());
694 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
718 // Test VFP multi load/store with ia.
719 CcTest::InitializeVM();
720 Isolate* isolate = CcTest::i_isolate();
721 HandleScope scope(isolate);
747 // Create a function that uses vldm/vstm to move some double and
748 // single precision values around in memory.
749 Assembler assm(isolate, NULL, 0);
751 __ mov(ip, Operand(sp));
752 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
753 __ sub(fp, ip, Operand(4));
755 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
756 __ vldm(ia, r4, d0, d3);
757 __ add(r4, r4, Operand(4 * 8));
758 __ vldm(ia, r4, d4, d7);
760 __ add(r4, r0, Operand(OFFSET_OF(D, a)));
761 __ vstm(ia, r4, d6, d7);
762 __ add(r4, r4, Operand(2 * 8));
763 __ vstm(ia, r4, d0, d5);
765 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
766 __ vldm(ia, r4, s0, s3);
767 __ add(r4, r4, Operand(4 * 4));
768 __ vldm(ia, r4, s4, s7);
770 __ add(r4, r1, Operand(OFFSET_OF(F, a)));
771 __ vstm(ia, r4, s6, s7);
772 __ add(r4, r4, Operand(2 * 4));
773 __ vstm(ia, r4, s0, s5);
775 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
779 Handle<Code> code = isolate->factory()->NewCode(
780 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
785 F4 fn = FUNCTION_CAST<F4>(code->entry());
804 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
828 // Test VFP multi load/store with db_w.
829 CcTest::InitializeVM();
830 Isolate* isolate = CcTest::i_isolate();
831 HandleScope scope(isolate);
857 // Create a function that uses vldm/vstm to move some double and
858 // single precision values around in memory.
859 Assembler assm(isolate, NULL, 0);
861 __ mov(ip, Operand(sp));
862 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
863 __ sub(fp, ip, Operand(4));
865 __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8));
866 __ vldm(db_w, r4, d4, d7);
867 __ vldm(db_w, r4, d0, d3);
869 __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8));
870 __ vstm(db_w, r4, d0, d5);
871 __ vstm(db_w, r4, d6, d7);
873 __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4));
874 __ vldm(db_w, r4, s4, s7);
875 __ vldm(db_w, r4, s0, s3);
877 __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4));
878 __ vstm(db_w, r4, s0, s5);
879 __ vstm(db_w, r4, s6, s7);
881 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
885 Handle<Code> code = isolate->factory()->NewCode(
886 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
891 F4 fn = FUNCTION_CAST<F4>(code->entry());
910 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
934 // Test instructions using the carry flag.
935 CcTest::InitializeVM();
936 Isolate* isolate = CcTest::i_isolate();
937 HandleScope scope(isolate);
950 Assembler assm(isolate, NULL, 0);
952 // Test HeapObject untagging.
953 __ ldr(r1, MemOperand(r0, OFFSET_OF(I, a)));
954 __ mov(r1, Operand(r1, ASR, 1), SetCC);
955 __ adc(r1, r1, Operand(r1), LeaveCC, cs);
956 __ str(r1, MemOperand(r0, OFFSET_OF(I, a)));
958 __ ldr(r2, MemOperand(r0, OFFSET_OF(I, b)));
959 __ mov(r2, Operand(r2, ASR, 1), SetCC);
960 __ adc(r2, r2, Operand(r2), LeaveCC, cs);
961 __ str(r2, MemOperand(r0, OFFSET_OF(I, b)));
963 // Test corner cases.
964 __ mov(r1, Operand(0xffffffff));
965 __ mov(r2, Operand::Zero());
966 __ mov(r3, Operand(r1, ASR, 1), SetCC); // Set the carry.
967 __ adc(r3, r1, Operand(r2));
968 __ str(r3, MemOperand(r0, OFFSET_OF(I, c)));
970 __ mov(r1, Operand(0xffffffff));
971 __ mov(r2, Operand::Zero());
972 __ mov(r3, Operand(r2, ASR, 1), SetCC); // Unset the carry.
973 __ adc(r3, r1, Operand(r2));
974 __ str(r3, MemOperand(r0, OFFSET_OF(I, d)));
976 __ mov(pc, Operand(lr));
980 Handle<Code> code = isolate->factory()->NewCode(
981 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
986 F3 f = FUNCTION_CAST<F3>(code->entry());
987 Object* dummy = CALL_GENERATED_CODE(f, &i, 0, 0, 0, 0);
990 CHECK_EQ(0xabcd0001, i.a);
991 CHECK_EQ(static_cast<int32_t>(0xabcd0000) >> 1, i.b);
992 CHECK_EQ(0x00000000, i.c);
993 CHECK_EQ(0xffffffff, i.d);
998 // Test chaining of label usages within instructions (issue 1644).
999 CcTest::InitializeVM();
1000 Isolate* isolate = CcTest::i_isolate();
1001 HandleScope scope(isolate);
1003 Assembler assm(isolate, NULL, 0);
1013 // Test VFP instructions using registers d16-d31.
1014 CcTest::InitializeVM();
1015 Isolate* isolate = CcTest::i_isolate();
1016 HandleScope scope(isolate);
1018 if (!CpuFeatures::IsSupported(VFP32DREGS)) {
1037 // Create a function that accepts &t, and loads, manipulates, and stores
1038 // the doubles and floats.
1039 Assembler assm(isolate, NULL, 0);
1043 if (CpuFeatures::IsSupported(VFP3)) {
1044 CpuFeatureScope scope(&assm, VFP3);
1046 __ stm(db_w, sp, r4.bit() | lr.bit());
1048 // Load a, b, c into d16, d17, d18.
1049 __ mov(r4, Operand(r0));
1050 __ vldr(d16, r4, OFFSET_OF(T, a));
1051 __ vldr(d17, r4, OFFSET_OF(T, b));
1052 __ vldr(d18, r4, OFFSET_OF(T, c));
1055 __ vadd(d25, d25, d17);
1056 __ vsub(d25, d25, d18);
1057 __ vmul(d25, d25, d25);
1058 __ vdiv(d25, d25, d18);
1064 __ vmla(d18, d16, d17);
1066 // Store d16, d17, d18 into a, b, c.
1067 __ mov(r4, Operand(r0));
1068 __ vstr(d16, r4, OFFSET_OF(T, a));
1069 __ vstr(d17, r4, OFFSET_OF(T, b));
1070 __ vstr(d18, r4, OFFSET_OF(T, c));
1072 // Load x, y, z into d29-d31.
1073 __ add(r4, r0, Operand(OFFSET_OF(T, x)));
1074 __ vldm(ia_w, r4, d29, d31);
1076 // Swap d29 and d30 via r registers.
1077 __ vmov(r1, r2, d29);
1079 __ vmov(d30, r1, r2);
1081 // Convert to and from integer.
1082 __ vcvt_s32_f64(s1, d31);
1083 __ vcvt_f64_u32(d31, s1);
1085 // Store d29-d31 into x, y, z.
1086 __ add(r4, r0, Operand(OFFSET_OF(T, x)));
1087 __ vstm(ia_w, r4, d29, d31);
1089 // Move constants into d20, d21, d22 and store into i, j, k.
1090 __ vmov(d20, 14.7610017472335499);
1092 __ mov(r1, Operand(372106121));
1093 __ mov(r2, Operand(1079146608));
1094 __ vmov(d22, VmovIndexLo, r1);
1095 __ vmov(d22, VmovIndexHi, r2);
1096 __ add(r4, r0, Operand(OFFSET_OF(T, i)));
1097 __ vstm(ia_w, r4, d20, d22);
1098 // Move d22 into low and high.
1099 __ vmov(r4, VmovIndexLo, d22);
1100 __ str(r4, MemOperand(r0, OFFSET_OF(T, low)));
1101 __ vmov(r4, VmovIndexHi, d22);
1102 __ str(r4, MemOperand(r0, OFFSET_OF(T, high)));
1104 __ ldm(ia_w, sp, r4.bit() | pc.bit());
1107 assm.GetCode(&desc);
1108 Handle<Code> code = isolate->factory()->NewCode(
1109 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1111 OFStream os(stdout);
1114 F3 f = FUNCTION_CAST<F3>(code->entry());
1121 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1123 CHECK_EQ(14.7610017472335499, t.a);
1124 CHECK_EQ(3.84200491244266251, t.b);
1125 CHECK_EQ(73.8818412254460241, t.c);
1126 CHECK_EQ(2.75, t.x);
1128 CHECK_EQ(17.0, t.z);
1129 CHECK_EQ(14.7610017472335499, t.i);
1130 CHECK_EQ(16.0, t.j);
1131 CHECK_EQ(73.8818412254460241, t.k);
1132 CHECK_EQ(372106121, t.low);
1133 CHECK_EQ(1079146608, t.high);
1139 // Test the VFP Canonicalized Nan mode.
1140 CcTest::InitializeVM();
1141 Isolate* isolate = CcTest::i_isolate();
1142 HandleScope scope(isolate);
1154 // Create a function that makes the four basic operations.
1155 Assembler assm(isolate, NULL, 0);
1157 // Ensure FPSCR state (as JSEntryStub does).
1160 __ tst(r1, Operand(kVFPDefaultNaNModeControlBit));
1161 __ b(ne, &fpscr_done);
1162 __ orr(r1, r1, Operand(kVFPDefaultNaNModeControlBit));
1164 __ bind(&fpscr_done);
1166 __ vldr(d0, r0, OFFSET_OF(T, left));
1167 __ vldr(d1, r0, OFFSET_OF(T, right));
1168 __ vadd(d2, d0, d1);
1169 __ vstr(d2, r0, OFFSET_OF(T, add_result));
1170 __ vsub(d2, d0, d1);
1171 __ vstr(d2, r0, OFFSET_OF(T, sub_result));
1172 __ vmul(d2, d0, d1);
1173 __ vstr(d2, r0, OFFSET_OF(T, mul_result));
1174 __ vdiv(d2, d0, d1);
1175 __ vstr(d2, r0, OFFSET_OF(T, div_result));
1177 __ mov(pc, Operand(lr));
1180 assm.GetCode(&desc);
1181 Handle<Code> code = isolate->factory()->NewCode(
1182 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1184 OFStream os(stdout);
1187 F3 f = FUNCTION_CAST<F3>(code->entry());
1188 t.left = bit_cast<double>(kHoleNanInt64);
1194 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1196 const uint32_t kArmNanUpper32 = 0x7ff80000;
1197 const uint32_t kArmNanLower32 = 0x00000000;
1199 const uint64_t kArmNanInt64 =
1200 (static_cast<uint64_t>(kArmNanUpper32) << 32) | kArmNanLower32;
1201 DCHECK(kArmNanInt64 != kHoleNanInt64);
1203 // With VFP2 the sign of the canonicalized Nan is undefined. So
1204 // we remove the sign bit for the upper tests.
1205 CHECK_EQ(kArmNanUpper32,
1206 (bit_cast<int64_t>(t.add_result) >> 32) & 0x7fffffff);
1207 CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.add_result) & 0xffffffffu);
1208 CHECK_EQ(kArmNanUpper32,
1209 (bit_cast<int64_t>(t.sub_result) >> 32) & 0x7fffffff);
1210 CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.sub_result) & 0xffffffffu);
1211 CHECK_EQ(kArmNanUpper32,
1212 (bit_cast<int64_t>(t.mul_result) >> 32) & 0x7fffffff);
1213 CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.mul_result) & 0xffffffffu);
1214 CHECK_EQ(kArmNanUpper32,
1215 (bit_cast<int64_t>(t.div_result) >> 32) & 0x7fffffff);
1216 CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.div_result) & 0xffffffffu);
1221 // Test the Neon instructions.
1222 CcTest::InitializeVM();
1223 Isolate* isolate = CcTest::i_isolate();
1224 HandleScope scope(isolate);
1256 // Create a function that accepts &t, and loads, manipulates, and stores
1257 // the doubles and floats.
1258 Assembler assm(isolate, NULL, 0);
1261 if (CpuFeatures::IsSupported(NEON)) {
1262 CpuFeatureScope scope(&assm, NEON);
1264 __ stm(db_w, sp, r4.bit() | lr.bit());
1265 // Move 32 bytes with neon.
1266 __ add(r4, r0, Operand(OFFSET_OF(T, src0)));
1267 __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4));
1268 __ add(r4, r0, Operand(OFFSET_OF(T, dst0)));
1269 __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4));
1271 // Expand 8 bytes into 8 words(16 bits).
1272 __ add(r4, r0, Operand(OFFSET_OF(T, srcA0)));
1273 __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(r4));
1274 __ vmovl(NeonU8, q0, d0);
1275 __ add(r4, r0, Operand(OFFSET_OF(T, dstA0)));
1276 __ vst1(Neon8, NeonListOperand(d0, 2), NeonMemOperand(r4));
1278 // The same expansion, but with different source and destination registers.
1279 __ add(r4, r0, Operand(OFFSET_OF(T, srcA0)));
1280 __ vld1(Neon8, NeonListOperand(d1), NeonMemOperand(r4));
1281 __ vmovl(NeonU8, q1, d1);
1282 __ add(r4, r0, Operand(OFFSET_OF(T, dstA4)));
1283 __ vst1(Neon8, NeonListOperand(d2, 2), NeonMemOperand(r4));
1285 __ ldm(ia_w, sp, r4.bit() | pc.bit());
1288 assm.GetCode(&desc);
1289 Handle<Code> code = isolate->factory()->NewCode(
1290 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1292 OFStream os(stdout);
1295 F3 f = FUNCTION_CAST<F3>(code->entry());
1296 t.src0 = 0x01020304;
1297 t.src1 = 0x11121314;
1298 t.src2 = 0x21222324;
1299 t.src3 = 0x31323334;
1300 t.src4 = 0x41424344;
1301 t.src5 = 0x51525354;
1302 t.src6 = 0x61626364;
1303 t.src7 = 0x71727374;
1312 t.srcA0 = 0x41424344;
1313 t.srcA1 = 0x81828384;
1322 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1324 CHECK_EQ(0x01020304, t.dst0);
1325 CHECK_EQ(0x11121314, t.dst1);
1326 CHECK_EQ(0x21222324, t.dst2);
1327 CHECK_EQ(0x31323334, t.dst3);
1328 CHECK_EQ(0x41424344, t.dst4);
1329 CHECK_EQ(0x51525354, t.dst5);
1330 CHECK_EQ(0x61626364, t.dst6);
1331 CHECK_EQ(0x71727374, t.dst7);
1332 CHECK_EQ(0x00430044, t.dstA0);
1333 CHECK_EQ(0x00410042, t.dstA1);
1334 CHECK_EQ(0x00830084, t.dstA2);
1335 CHECK_EQ(0x00810082, t.dstA3);
1336 CHECK_EQ(0x00430044, t.dstA4);
1337 CHECK_EQ(0x00410042, t.dstA5);
1338 CHECK_EQ(0x00830084, t.dstA6);
1339 CHECK_EQ(0x00810082, t.dstA7);
1345 // Test the pkh, uxtb, uxtab and uxtb16 instructions.
1346 CcTest::InitializeVM();
1347 Isolate* isolate = CcTest::i_isolate();
1348 HandleScope scope(isolate);
1362 // Create a function that accepts &t, and loads, manipulates, and stores
1363 // the doubles and floats.
1364 Assembler assm(isolate, NULL, 0);
1366 __ stm(db_w, sp, r4.bit() | lr.bit());
1368 __ mov(r4, Operand(r0));
1369 __ ldr(r0, MemOperand(r4, OFFSET_OF(T, src0)));
1370 __ ldr(r1, MemOperand(r4, OFFSET_OF(T, src1)));
1372 __ pkhbt(r2, r0, Operand(r1, LSL, 8));
1373 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst0)));
1375 __ pkhtb(r2, r0, Operand(r1, ASR, 8));
1376 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst1)));
1378 __ uxtb16(r2, Operand(r0, ROR, 8));
1379 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst2)));
1381 __ uxtb(r2, Operand(r0, ROR, 8));
1382 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst3)));
1384 __ ldr(r0, MemOperand(r4, OFFSET_OF(T, src2)));
1385 __ uxtab(r2, r0, Operand(r1, ROR, 8));
1386 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst4)));
1388 __ ldm(ia_w, sp, r4.bit() | pc.bit());
1391 assm.GetCode(&desc);
1392 Handle<Code> code = isolate->factory()->NewCode(
1393 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1395 OFStream os(stdout);
1398 F3 f = FUNCTION_CAST<F3>(code->entry());
1399 t.src0 = 0x01020304;
1400 t.src1 = 0x11121314;
1401 t.src2 = 0x11121300;
1407 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1409 CHECK_EQ(0x12130304, t.dst0);
1410 CHECK_EQ(0x01021213, t.dst1);
1411 CHECK_EQ(0x00010003, t.dst2);
1412 CHECK_EQ(0x00000003, t.dst3);
1413 CHECK_EQ(0x11121313, t.dst4);
1418 // Test generating labels at high addresses.
1419 // Should not assert.
1420 CcTest::InitializeVM();
1421 Isolate* isolate = CcTest::i_isolate();
1422 HandleScope scope(isolate);
1424 // Generate a code segment that will be longer than 2^24 bytes.
1425 Assembler assm(isolate, NULL, 0);
1426 for (size_t i = 0; i < 1 << 23 ; ++i) { // 2^23
1437 #define TEST_SDIV(expected_, dividend_, divisor_) \
1438 t.dividend = dividend_; \
1439 t.divisor = divisor_; \
1441 dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); \
1442 CHECK_EQ(expected_, t.result);
1447 CcTest::InitializeVM();
1448 Isolate* isolate = CcTest::i_isolate();
1449 HandleScope scope(isolate);
1450 Assembler assm(isolate, NULL, 0);
1458 if (CpuFeatures::IsSupported(SUDIV)) {
1459 CpuFeatureScope scope(&assm, SUDIV);
1461 __ mov(r3, Operand(r0));
1463 __ ldr(r0, MemOperand(r3, OFFSET_OF(T, dividend)));
1464 __ ldr(r1, MemOperand(r3, OFFSET_OF(T, divisor)));
1466 __ sdiv(r2, r0, r1);
1467 __ str(r2, MemOperand(r3, OFFSET_OF(T, result)));
1472 assm.GetCode(&desc);
1473 Handle<Code> code = isolate->factory()->NewCode(
1474 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1476 OFStream os(stdout);
1479 F3 f = FUNCTION_CAST<F3>(code->entry());
1481 TEST_SDIV(0, kMinInt, 0);
1482 TEST_SDIV(0, 1024, 0);
1483 TEST_SDIV(1073741824, kMinInt, -2);
1484 TEST_SDIV(kMinInt, kMinInt, -1);
1485 TEST_SDIV(5, 10, 2);
1486 TEST_SDIV(3, 10, 3);
1487 TEST_SDIV(-5, 10, -2);
1488 TEST_SDIV(-3, 10, -3);
1489 TEST_SDIV(-5, -10, 2);
1490 TEST_SDIV(-3, -10, 3);
1491 TEST_SDIV(5, -10, -2);
1492 TEST_SDIV(3, -10, -3);
1501 #define TEST_UDIV(expected_, dividend_, divisor_) \
1502 t.dividend = dividend_; \
1503 t.divisor = divisor_; \
1505 dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); \
1506 CHECK_EQ(expected_, t.result);
1511 CcTest::InitializeVM();
1512 Isolate* isolate = CcTest::i_isolate();
1513 HandleScope scope(isolate);
1514 Assembler assm(isolate, NULL, 0);
1522 if (CpuFeatures::IsSupported(SUDIV)) {
1523 CpuFeatureScope scope(&assm, SUDIV);
1525 __ mov(r3, Operand(r0));
1527 __ ldr(r0, MemOperand(r3, OFFSET_OF(T, dividend)));
1528 __ ldr(r1, MemOperand(r3, OFFSET_OF(T, divisor)));
1530 __ sdiv(r2, r0, r1);
1531 __ str(r2, MemOperand(r3, OFFSET_OF(T, result)));
1536 assm.GetCode(&desc);
1537 Handle<Code> code = isolate->factory()->NewCode(
1538 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1540 OFStream os(stdout);
1543 F3 f = FUNCTION_CAST<F3>(code->entry());
1546 TEST_UDIV(0, 1024, 0);
1547 TEST_UDIV(5, 10, 2);
1548 TEST_UDIV(3, 10, 3);
1558 CcTest::InitializeVM();
1559 Isolate* const isolate = CcTest::i_isolate();
1560 HandleScope scope(isolate);
1561 RandomNumberGenerator* const rng = isolate->random_number_generator();
1562 Assembler assm(isolate, nullptr, 0);
1563 __ smmla(r1, r1, r2, r3);
1564 __ str(r1, MemOperand(r0));
1567 assm.GetCode(&desc);
1568 Handle<Code> code = isolate->factory()->NewCode(
1569 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1571 code->Print(std::cout);
1573 F3 f = FUNCTION_CAST<F3>(code->entry());
1574 for (size_t i = 0; i < 128; ++i) {
1575 int32_t r, x = rng->NextInt(), y = rng->NextInt(), z = rng->NextInt();
1576 Object* dummy = CALL_GENERATED_CODE(f, &r, x, y, z, 0);
1577 CHECK_EQ(bits::SignedMulHighAndAdd32(x, y, z), r);
1584 CcTest::InitializeVM();
1585 Isolate* const isolate = CcTest::i_isolate();
1586 HandleScope scope(isolate);
1587 RandomNumberGenerator* const rng = isolate->random_number_generator();
1588 Assembler assm(isolate, nullptr, 0);
1589 __ smmul(r1, r1, r2);
1590 __ str(r1, MemOperand(r0));
1593 assm.GetCode(&desc);
1594 Handle<Code> code = isolate->factory()->NewCode(
1595 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1597 code->Print(std::cout);
1599 F3 f = FUNCTION_CAST<F3>(code->entry());
1600 for (size_t i = 0; i < 128; ++i) {
1601 int32_t r, x = rng->NextInt(), y = rng->NextInt();
1602 Object* dummy = CALL_GENERATED_CODE(f, &r, x, y, 0, 0);
1603 CHECK_EQ(bits::SignedMulHigh32(x, y), r);
1609 TEST(code_relative_offset) {
1610 // Test extracting the offset of a label from the beginning of the code
1612 CcTest::InitializeVM();
1613 Isolate* isolate = CcTest::i_isolate();
1614 HandleScope scope(isolate);
1615 // Initialize a code object that will contain the code.
1616 Handle<Object> code_object(isolate->heap()->undefined_value(), isolate);
1618 Assembler assm(isolate, NULL, 0);
1620 Label start, target_away, target_faraway;
1622 __ stm(db_w, sp, r4.bit() | r5.bit() | lr.bit());
1624 // r3 is used as the address zero, the test will crash when we load it.
1625 __ mov(r3, Operand::Zero());
1627 // r5 will be a pointer to the start of the code.
1628 __ mov(r5, Operand(code_object));
1629 __ mov_label_offset(r4, &start);
1631 __ mov_label_offset(r1, &target_faraway);
1632 __ str(r1, MemOperand(sp, kPointerSize, NegPreIndex));
1634 __ mov_label_offset(r1, &target_away);
1636 // Jump straight to 'target_away' the first time and use the relative
1637 // position the second time. This covers the case when extracting the
1638 // position of a label which is linked.
1639 __ mov(r2, Operand::Zero());
1641 __ cmp(r2, Operand::Zero());
1642 __ b(eq, &target_away);
1644 // Emit invalid instructions to push the label between 2^8 and 2^16
1645 // instructions away. The test will crash if they are reached.
1646 for (int i = 0; i < (1 << 10); i++) {
1647 __ ldr(r3, MemOperand(r3));
1649 __ bind(&target_away);
1650 // This will be hit twice: r0 = r0 + 5 + 5.
1651 __ add(r0, r0, Operand(5));
1653 __ ldr(r1, MemOperand(sp, kPointerSize, PostIndex), ne);
1654 __ add(pc, r5, r4, LeaveCC, ne);
1656 __ mov(r2, Operand(1));
1658 // Emit invalid instructions to push the label between 2^16 and 2^24
1659 // instructions away. The test will crash if they are reached.
1660 for (int i = 0; i < (1 << 21); i++) {
1661 __ ldr(r3, MemOperand(r3));
1663 __ bind(&target_faraway);
1664 // r0 = r0 + 5 + 5 + 11
1665 __ add(r0, r0, Operand(11));
1667 __ ldm(ia_w, sp, r4.bit() | r5.bit() | pc.bit());
1670 assm.GetCode(&desc);
1671 Handle<Code> code = isolate->factory()->NewCode(
1672 desc, Code::ComputeFlags(Code::STUB), code_object);
1673 F1 f = FUNCTION_CAST<F1>(code->entry());
1674 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 21, 0, 0, 0, 0));
1675 ::printf("f() = %d\n", res);
1680 TEST(ARMv8_vrintX) {
1681 // Test the vrintX floating point instructions.
1682 CcTest::InitializeVM();
1683 Isolate* isolate = CcTest::i_isolate();
1684 HandleScope scope(isolate);
1696 // Create a function that accepts &t, and loads, manipulates, and stores
1697 // the doubles and floats.
1698 Assembler assm(isolate, NULL, 0);
1702 if (CpuFeatures::IsSupported(ARMv8)) {
1703 CpuFeatureScope scope(&assm, ARMv8);
1705 __ mov(ip, Operand(sp));
1706 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
1708 __ mov(r4, Operand(r0));
1711 __ vldr(d6, r4, OFFSET_OF(T, input));
1713 __ vstr(d5, r4, OFFSET_OF(T, ar));
1716 __ vldr(d6, r4, OFFSET_OF(T, input));
1718 __ vstr(d5, r4, OFFSET_OF(T, nr));
1721 __ vldr(d6, r4, OFFSET_OF(T, input));
1723 __ vstr(d5, r4, OFFSET_OF(T, pr));
1726 __ vldr(d6, r4, OFFSET_OF(T, input));
1728 __ vstr(d5, r4, OFFSET_OF(T, mr));
1731 __ vldr(d6, r4, OFFSET_OF(T, input));
1733 __ vstr(d5, r4, OFFSET_OF(T, zr));
1735 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
1738 assm.GetCode(&desc);
1739 Handle<Code> code = isolate->factory()->NewCode(
1740 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1742 OFStream os(stdout);
1745 F3 f = FUNCTION_CAST<F3>(code->entry());
1747 Object* dummy = nullptr;
1750 #define CHECK_VRINT(input_val, ares, nres, mres, pres, zres) \
1751 t.input = input_val; \
1752 dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); \
1753 CHECK_EQ(ares, t.ar); \
1754 CHECK_EQ(nres, t.nr); \
1755 CHECK_EQ(mres, t.mr); \
1756 CHECK_EQ(pres, t.pr); \
1757 CHECK_EQ(zres, t.zr);
1759 CHECK_VRINT(-0.5, -1.0, -0.0, -1.0, -0.0, -0.0)
1760 CHECK_VRINT(-0.6, -1.0, -1.0, -1.0, -0.0, -0.0)
1761 CHECK_VRINT(-1.1, -1.0, -1.0, -2.0, -1.0, -1.0)
1762 CHECK_VRINT(0.5, 1.0, 0.0, 0.0, 1.0, 0.0)
1763 CHECK_VRINT(0.6, 1.0, 1.0, 0.0, 1.0, 0.0)
1764 CHECK_VRINT(1.1, 1.0, 1.0, 1.0, 2.0, 1.0)
1765 double inf = std::numeric_limits<double>::infinity();
1766 CHECK_VRINT(inf, inf, inf, inf, inf, inf)
1767 CHECK_VRINT(-inf, -inf, -inf, -inf, -inf, -inf)
1768 CHECK_VRINT(-0.0, -0.0, -0.0, -0.0, -0.0, -0.0)
1769 double nan = std::numeric_limits<double>::quiet_NaN();
1770 CHECK_VRINT(nan, nan, nan, nan, nan, nan)