1// Copyright 2012 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "src/v8.h"
29
30#include "src/disassembler.h"
31#include "src/factory.h"
32#include "src/ppc/assembler-ppc-inl.h"
33#include "src/ppc/simulator-ppc.h"
34#include "test/cctest/cctest.h"
35
36using namespace v8::internal;
37
38
39// Define these function prototypes to match JSEntryFunction in execution.cc.
40typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
41typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
42typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4);
43typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4);
44
45
46#define __ assm.
47
48// Simple add parameter 1 to parameter 2 and return
49TEST(0) {
50  CcTest::InitializeVM();
51  Isolate* isolate = CcTest::i_isolate();
52  HandleScope scope(isolate);
53
54  Assembler assm(isolate, NULL, 0);
55
56  __ function_descriptor();
57
58  __ add(r3, r3, r4);
59  __ blr();
60
61  CodeDesc desc;
62  assm.GetCode(&desc);
63  Handle<Code> code = isolate->factory()->NewCode(
64      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
65#ifdef DEBUG
66  code->Print();
67#endif
68  F2 f = FUNCTION_CAST<F2>(code->entry());
69  intptr_t res = reinterpret_cast<intptr_t>(
70      CALL_GENERATED_CODE(isolate, f, 3, 4, 0, 0, 0));
71  ::printf("f() = %" V8PRIdPTR "\n", res);
72  CHECK_EQ(7, static_cast<int>(res));
73}
74
75
76// Loop 100 times, adding loop counter to result
77TEST(1) {
78  CcTest::InitializeVM();
79  Isolate* isolate = CcTest::i_isolate();
80  HandleScope scope(isolate);
81
82  Assembler assm(isolate, NULL, 0);
83  Label L, C;
84
85  __ function_descriptor();
86
87  __ mr(r4, r3);
88  __ li(r3, Operand::Zero());
89  __ b(&C);
90
91  __ bind(&L);
92  __ add(r3, r3, r4);
93  __ subi(r4, r4, Operand(1));
94
95  __ bind(&C);
96  __ cmpi(r4, Operand::Zero());
97  __ bne(&L);
98  __ blr();
99
100  CodeDesc desc;
101  assm.GetCode(&desc);
102  Handle<Code> code = isolate->factory()->NewCode(
103      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
104#ifdef DEBUG
105  code->Print();
106#endif
107  F1 f = FUNCTION_CAST<F1>(code->entry());
108  intptr_t res = reinterpret_cast<intptr_t>(
109      CALL_GENERATED_CODE(isolate, f, 100, 0, 0, 0, 0));
110  ::printf("f() = %" V8PRIdPTR "\n", res);
111  CHECK_EQ(5050, static_cast<int>(res));
112}
113
114
115TEST(2) {
116  CcTest::InitializeVM();
117  Isolate* isolate = CcTest::i_isolate();
118  HandleScope scope(isolate);
119
120  Assembler assm(isolate, NULL, 0);
121  Label L, C;
122
123  __ function_descriptor();
124
125  __ mr(r4, r3);
126  __ li(r3, Operand(1));
127  __ b(&C);
128
129  __ bind(&L);
130#if defined(V8_TARGET_ARCH_PPC64)
131  __ mulld(r3, r4, r3);
132#else
133  __ mullw(r3, r4, r3);
134#endif
135  __ subi(r4, r4, Operand(1));
136
137  __ bind(&C);
138  __ cmpi(r4, Operand::Zero());
139  __ bne(&L);
140  __ blr();
141
142  // some relocated stuff here, not executed
143  __ RecordComment("dead code, just testing relocations");
144  __ mov(r0, Operand(isolate->factory()->true_value()));
145  __ RecordComment("dead code, just testing immediate operands");
146  __ mov(r0, Operand(-1));
147  __ mov(r0, Operand(0xFF000000));
148  __ mov(r0, Operand(0xF0F0F0F0));
149  __ mov(r0, Operand(0xFFF0FFFF));
150
151  CodeDesc desc;
152  assm.GetCode(&desc);
153  Handle<Code> code = isolate->factory()->NewCode(
154      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
155#ifdef DEBUG
156  code->Print();
157#endif
158  F1 f = FUNCTION_CAST<F1>(code->entry());
159  intptr_t res = reinterpret_cast<intptr_t>(
160      CALL_GENERATED_CODE(isolate, f, 10, 0, 0, 0, 0));
161  ::printf("f() = %" V8PRIdPTR "\n", res);
162  CHECK_EQ(3628800, static_cast<int>(res));
163}
164
165
166TEST(3) {
167  CcTest::InitializeVM();
168  Isolate* isolate = CcTest::i_isolate();
169  HandleScope scope(isolate);
170
171  typedef struct {
172    int i;
173    char c;
174    int16_t s;
175  } T;
176  T t;
177
178  Assembler assm(CcTest::i_isolate(), NULL, 0);
179  Label L, C;
180
181  __ function_descriptor();
182
183// build a frame
184#if V8_TARGET_ARCH_PPC64
185  __ stdu(sp, MemOperand(sp, -32));
186  __ std(fp, MemOperand(sp, 24));
187#else
188  __ stwu(sp, MemOperand(sp, -16));
189  __ stw(fp, MemOperand(sp, 12));
190#endif
191  __ mr(fp, sp);
192
193  // r4 points to our struct
194  __ mr(r4, r3);
195
196  // modify field int i of struct
197  __ lwz(r3, MemOperand(r4, offsetof(T, i)));
198  __ srwi(r5, r3, Operand(1));
199  __ stw(r5, MemOperand(r4, offsetof(T, i)));
200
201  // modify field char c of struct
202  __ lbz(r5, MemOperand(r4, offsetof(T, c)));
203  __ add(r3, r5, r3);
204  __ slwi(r5, r5, Operand(2));
205  __ stb(r5, MemOperand(r4, offsetof(T, c)));
206
207  // modify field int16_t s of struct
208  __ lhz(r5, MemOperand(r4, offsetof(T, s)));
209  __ add(r3, r5, r3);
210  __ srwi(r5, r5, Operand(3));
211  __ sth(r5, MemOperand(r4, offsetof(T, s)));
212
213// restore frame
214#if V8_TARGET_ARCH_PPC64
215  __ addi(r11, fp, Operand(32));
216  __ ld(fp, MemOperand(r11, -8));
217#else
218  __ addi(r11, fp, Operand(16));
219  __ lwz(fp, MemOperand(r11, -4));
220#endif
221  __ mr(sp, r11);
222  __ blr();
223
224  CodeDesc desc;
225  assm.GetCode(&desc);
226  Handle<Code> code = isolate->factory()->NewCode(
227      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
228#ifdef DEBUG
229  code->Print();
230#endif
231  F3 f = FUNCTION_CAST<F3>(code->entry());
232  t.i = 100000;
233  t.c = 10;
234  t.s = 1000;
235  intptr_t res = reinterpret_cast<intptr_t>(
236      CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0));
237  ::printf("f() = %" V8PRIdPTR "\n", res);
238  CHECK_EQ(101010, static_cast<int>(res));
239  CHECK_EQ(100000 / 2, t.i);
240  CHECK_EQ(10 * 4, t.c);
241  CHECK_EQ(1000 / 8, t.s);
242}
243
244#if 0
245TEST(4) {
246  // Test the VFP floating point instructions.
247  CcTest::InitializeVM();
248  Isolate* isolate = CcTest::i_isolate();
249  HandleScope scope(isolate);
250
251  typedef struct {
252    double a;
253    double b;
254    double c;
255    double d;
256    double e;
257    double f;
258    double g;
259    double h;
260    int i;
261    double m;
262    double n;
263    float x;
264    float y;
265  } T;
266  T t;
267
268  // Create a function that accepts &t, and loads, manipulates, and stores
269  // the doubles and floats.
270  Assembler assm(CcTest::i_isolate(), NULL, 0);
271  Label L, C;
272
273  if (CpuFeatures::IsSupported(VFP3)) {
274    CpuFeatures::Scope scope(VFP3);
275
276    __ mov(ip, Operand(sp));
277    __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
278    __ sub(fp, ip, Operand(4));
279
280    __ mov(r4, Operand(r0));
281    __ vldr(d6, r4, offsetof(T, a));
282    __ vldr(d7, r4, offsetof(T, b));
283    __ vadd(d5, d6, d7);
284    __ vstr(d5, r4, offsetof(T, c));
285
286    __ vmov(r2, r3, d5);
287    __ vmov(d4, r2, r3);
288    __ vstr(d4, r4, offsetof(T, b));
289
290    // Load t.x and t.y, switch values, and store back to the struct.
291    __ vldr(s0, r4, offsetof(T, x));
292    __ vldr(s31, r4, offsetof(T, y));
293    __ vmov(s16, s0);
294    __ vmov(s0, s31);
295    __ vmov(s31, s16);
296    __ vstr(s0, r4, offsetof(T, x));
297    __ vstr(s31, r4, offsetof(T, y));
298
299    // Move a literal into a register that can be encoded in the instruction.
300    __ vmov(d4, 1.0);
301    __ vstr(d4, r4, offsetof(T, e));
302
303    // Move a literal into a register that requires 64 bits to encode.
304    // 0x3ff0000010000000 = 1.000000059604644775390625
305    __ vmov(d4, 1.000000059604644775390625);
306    __ vstr(d4, r4, offsetof(T, d));
307
308    // Convert from floating point to integer.
309    __ vmov(d4, 2.0);
310    __ vcvt_s32_f64(s31, d4);
311    __ vstr(s31, r4, offsetof(T, i));
312
313    // Convert from integer to floating point.
314    __ mov(lr, Operand(42));
315    __ vmov(s31, lr);
316    __ vcvt_f64_s32(d4, s31);
317    __ vstr(d4, r4, offsetof(T, f));
318
319    // Test vabs.
320    __ vldr(d1, r4, offsetof(T, g));
321    __ vabs(d0, d1);
322    __ vstr(d0, r4, offsetof(T, g));
323    __ vldr(d2, r4, offsetof(T, h));
324    __ vabs(d0, d2);
325    __ vstr(d0, r4, offsetof(T, h));
326
327    // Test vneg.
328    __ vldr(d1, r4, offsetof(T, m));
329    __ vneg(d0, d1);
330    __ vstr(d0, r4, offsetof(T, m));
331    __ vldr(d1, r4, offsetof(T, n));
332    __ vneg(d0, d1);
333    __ vstr(d0, r4, offsetof(T, n));
334
335    __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
336
337    CodeDesc desc;
338    assm.GetCode(&desc);
339    Object* code = isolate->heap()->CreateCode(
340        desc,
341        Code::ComputeFlags(Code::STUB),
342        Handle<Code>())->ToObjectChecked();
343    CHECK(code->IsCode());
344#ifdef DEBUG
345    Code::cast(code)->Print();
346#endif
347    F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
348    t.a = 1.5;
349    t.b = 2.75;
350    t.c = 17.17;
351    t.d = 0.0;
352    t.e = 0.0;
353    t.f = 0.0;
354    t.g = -2718.2818;
355    t.h = 31415926.5;
356    t.i = 0;
357    t.m = -2718.2818;
358    t.n = 123.456;
359    t.x = 4.5;
360    t.y = 9.0;
361    Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
362    USE(dummy);
363    CHECK_EQ(4.5, t.y);
364    CHECK_EQ(9.0, t.x);
365    CHECK_EQ(-123.456, t.n);
366    CHECK_EQ(2718.2818, t.m);
367    CHECK_EQ(2, t.i);
368    CHECK_EQ(2718.2818, t.g);
369    CHECK_EQ(31415926.5, t.h);
370    CHECK_EQ(42.0, t.f);
371    CHECK_EQ(1.0, t.e);
372    CHECK_EQ(1.000000059604644775390625, t.d);
373    CHECK_EQ(4.25, t.c);
374    CHECK_EQ(4.25, t.b);
375    CHECK_EQ(1.5, t.a);
376  }
377}
378
379
380TEST(5) {
381  // Test the ARMv7 bitfield instructions.
382  CcTest::InitializeVM();
383  Isolate* isolate = CcTest::i_isolate();
384  HandleScope scope(isolate);
385
386  Assembler assm(isolate, NULL, 0);
387
388  if (CpuFeatures::IsSupported(ARMv7)) {
389    CpuFeatures::Scope scope(ARMv7);
390    // On entry, r0 = 0xAAAAAAAA = 0b10..10101010.
391    __ ubfx(r0, r0, 1, 12);  // 0b00..010101010101 = 0x555
392    __ sbfx(r0, r0, 0, 5);   // 0b11..111111110101 = -11
393    __ bfc(r0, 1, 3);        // 0b11..111111110001 = -15
394    __ mov(r1, Operand(7));
395    __ bfi(r0, r1, 3, 3);    // 0b11..111111111001 = -7
396    __ mov(pc, Operand(lr));
397
398    CodeDesc desc;
399    assm.GetCode(&desc);
400    Object* code = isolate->heap()->CreateCode(
401        desc,
402        Code::ComputeFlags(Code::STUB),
403        Handle<Code>())->ToObjectChecked();
404    CHECK(code->IsCode());
405#ifdef DEBUG
406    Code::cast(code)->Print();
407#endif
408    F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
409    int res = reinterpret_cast<int>(
410                CALL_GENERATED_CODE(isolate, f, 0xAAAAAAAA, 0, 0, 0, 0));
411    ::printf("f() = %d\n", res);
412    CHECK_EQ(-7, res);
413  }
414}
415
416
417TEST(6) {
418  // Test saturating instructions.
419  CcTest::InitializeVM();
420  Isolate* isolate = CcTest::i_isolate();
421  HandleScope scope(isolate);
422
423  Assembler assm(isolate, NULL, 0);
424
425  if (CpuFeatures::IsSupported(ARMv7)) {
426    CpuFeatures::Scope scope(ARMv7);
427    __ usat(r1, 8, Operand(r0));           // Sat 0xFFFF to 0-255 = 0xFF.
428    __ usat(r2, 12, Operand(r0, ASR, 9));  // Sat (0xFFFF>>9) to 0-4095 = 0x7F.
429    __ usat(r3, 1, Operand(r0, LSL, 16));  // Sat (0xFFFF<<16) to 0-1 = 0x0.
430    __ addi(r0, r1, Operand(r2));
431    __ addi(r0, r0, Operand(r3));
432    __ mov(pc, Operand(lr));
433
434    CodeDesc desc;
435    assm.GetCode(&desc);
436    Object* code = isolate->heap()->CreateCode(
437        desc,
438        Code::ComputeFlags(Code::STUB),
439        Handle<Code>())->ToObjectChecked();
440    CHECK(code->IsCode());
441#ifdef DEBUG
442    Code::cast(code)->Print();
443#endif
444    F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
445    int res = reinterpret_cast<int>(
446                CALL_GENERATED_CODE(isolate, f, 0xFFFF, 0, 0, 0, 0));
447    ::printf("f() = %d\n", res);
448    CHECK_EQ(382, res);
449  }
450}
451
452enum VCVTTypes {
453  s32_f64,
454  u32_f64
455};
456
457static void TestRoundingMode(VCVTTypes types,
458                             VFPRoundingMode mode,
459                             double value,
460                             int expected,
461                             bool expected_exception = false) {
462  CcTest::InitializeVM();
463  Isolate* isolate = CcTest::i_isolate();
464  HandleScope scope(isolate);
465
466  Assembler assm(isolate, NULL, 0);
467
468  if (CpuFeatures::IsSupported(VFP3)) {
469    CpuFeatures::Scope scope(VFP3);
470
471    Label wrong_exception;
472
473    __ vmrs(r1);
474    // Set custom FPSCR.
475    __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask));
476    __ orr(r2, r2, Operand(mode));
477    __ vmsr(r2);
478
479    // Load value, convert, and move back result to r0 if everything went well.
480    __ vmov(d1, value);
481    switch (types) {
482      case s32_f64:
483        __ vcvt_s32_f64(s0, d1, kFPSCRRounding);
484        break;
485
486      case u32_f64:
487        __ vcvt_u32_f64(s0, d1, kFPSCRRounding);
488        break;
489
490      default:
491        UNREACHABLE();
492        break;
493    }
494    // Check for vfp exceptions
495    __ vmrs(r2);
496    __ tst(r2, Operand(kVFPExceptionMask));
497    // Check that we behaved as expected.
498    __ b(&wrong_exception,
499         expected_exception ? eq : ne);
500    // There was no exception. Retrieve the result and return.
501    __ vmov(r0, s0);
502    __ mov(pc, Operand(lr));
503
504    // The exception behaviour is not what we expected.
505    // Load a special value and return.
506    __ bind(&wrong_exception);
507    __ mov(r0, Operand(11223344));
508    __ mov(pc, Operand(lr));
509
510    CodeDesc desc;
511    assm.GetCode(&desc);
512    Object* code = isolate->heap()->CreateCode(
513        desc,
514        Code::ComputeFlags(Code::STUB),
515        Handle<Code>())->ToObjectChecked();
516    CHECK(code->IsCode());
517#ifdef DEBUG
518    Code::cast(code)->Print();
519#endif
520    F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
521    int res = reinterpret_cast<int>(
522                CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
523    ::printf("res = %d\n", res);
524    CHECK_EQ(expected, res);
525  }
526}
527
528
529TEST(7) {
530  // Test vfp rounding modes.
531
532  // s32_f64 (double to integer).
533
534  TestRoundingMode(s32_f64, RN,  0, 0);
535  TestRoundingMode(s32_f64, RN,  0.5, 0);
536  TestRoundingMode(s32_f64, RN, -0.5, 0);
537  TestRoundingMode(s32_f64, RN,  1.5, 2);
538  TestRoundingMode(s32_f64, RN, -1.5, -2);
539  TestRoundingMode(s32_f64, RN,  123.7, 124);
540  TestRoundingMode(s32_f64, RN, -123.7, -124);
541  TestRoundingMode(s32_f64, RN,  123456.2,  123456);
542  TestRoundingMode(s32_f64, RN, -123456.2, -123456);
543  TestRoundingMode(s32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
544  TestRoundingMode(s32_f64, RN, (kMaxInt + 0.49), kMaxInt);
545  TestRoundingMode(s32_f64, RN, (kMaxInt + 1.0), kMaxInt, true);
546  TestRoundingMode(s32_f64, RN, (kMaxInt + 0.5), kMaxInt, true);
547  TestRoundingMode(s32_f64, RN, static_cast<double>(kMinInt), kMinInt);
548  TestRoundingMode(s32_f64, RN, (kMinInt - 0.5), kMinInt);
549  TestRoundingMode(s32_f64, RN, (kMinInt - 1.0), kMinInt, true);
550  TestRoundingMode(s32_f64, RN, (kMinInt - 0.51), kMinInt, true);
551
552  TestRoundingMode(s32_f64, RM,  0, 0);
553  TestRoundingMode(s32_f64, RM,  0.5, 0);
554  TestRoundingMode(s32_f64, RM, -0.5, -1);
555  TestRoundingMode(s32_f64, RM,  123.7, 123);
556  TestRoundingMode(s32_f64, RM, -123.7, -124);
557  TestRoundingMode(s32_f64, RM,  123456.2,  123456);
558  TestRoundingMode(s32_f64, RM, -123456.2, -123457);
559  TestRoundingMode(s32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
560  TestRoundingMode(s32_f64, RM, (kMaxInt + 0.5), kMaxInt);
561  TestRoundingMode(s32_f64, RM, (kMaxInt + 1.0), kMaxInt, true);
562  TestRoundingMode(s32_f64, RM, static_cast<double>(kMinInt), kMinInt);
563  TestRoundingMode(s32_f64, RM, (kMinInt - 0.5), kMinInt, true);
564  TestRoundingMode(s32_f64, RM, (kMinInt + 0.5), kMinInt);
565
566  TestRoundingMode(s32_f64, RZ,  0, 0);
567  TestRoundingMode(s32_f64, RZ,  0.5, 0);
568  TestRoundingMode(s32_f64, RZ, -0.5, 0);
569  TestRoundingMode(s32_f64, RZ,  123.7,  123);
570  TestRoundingMode(s32_f64, RZ, -123.7, -123);
571  TestRoundingMode(s32_f64, RZ,  123456.2,  123456);
572  TestRoundingMode(s32_f64, RZ, -123456.2, -123456);
573  TestRoundingMode(s32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
574  TestRoundingMode(s32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
575  TestRoundingMode(s32_f64, RZ, (kMaxInt + 1.0), kMaxInt, true);
576  TestRoundingMode(s32_f64, RZ, static_cast<double>(kMinInt), kMinInt);
577  TestRoundingMode(s32_f64, RZ, (kMinInt - 0.5), kMinInt);
578  TestRoundingMode(s32_f64, RZ, (kMinInt - 1.0), kMinInt, true);
579
580
581  // u32_f64 (double to integer).
582
583  // Negative values.
584  TestRoundingMode(u32_f64, RN, -0.5, 0);
585  TestRoundingMode(u32_f64, RN, -123456.7, 0, true);
586  TestRoundingMode(u32_f64, RN, static_cast<double>(kMinInt), 0, true);
587  TestRoundingMode(u32_f64, RN, kMinInt - 1.0, 0, true);
588
589  TestRoundingMode(u32_f64, RM, -0.5, 0, true);
590  TestRoundingMode(u32_f64, RM, -123456.7, 0, true);
591  TestRoundingMode(u32_f64, RM, static_cast<double>(kMinInt), 0, true);
592  TestRoundingMode(u32_f64, RM, kMinInt - 1.0, 0, true);
593
594  TestRoundingMode(u32_f64, RZ, -0.5, 0);
595  TestRoundingMode(u32_f64, RZ, -123456.7, 0, true);
596  TestRoundingMode(u32_f64, RZ, static_cast<double>(kMinInt), 0, true);
597  TestRoundingMode(u32_f64, RZ, kMinInt - 1.0, 0, true);
598
599  // Positive values.
600  // kMaxInt is the maximum *signed* integer: 0x7fffffff.
601  static const uint32_t kMaxUInt = 0xffffffffu;
602  TestRoundingMode(u32_f64, RZ,  0, 0);
603  TestRoundingMode(u32_f64, RZ,  0.5, 0);
604  TestRoundingMode(u32_f64, RZ,  123.7,  123);
605  TestRoundingMode(u32_f64, RZ,  123456.2,  123456);
606  TestRoundingMode(u32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
607  TestRoundingMode(u32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
608  TestRoundingMode(u32_f64, RZ, (kMaxInt + 1.0),
609                                static_cast<uint32_t>(kMaxInt) + 1);
610  TestRoundingMode(u32_f64, RZ, (kMaxUInt + 0.5), kMaxUInt);
611  TestRoundingMode(u32_f64, RZ, (kMaxUInt + 1.0), kMaxUInt, true);
612
613  TestRoundingMode(u32_f64, RM,  0, 0);
614  TestRoundingMode(u32_f64, RM,  0.5, 0);
615  TestRoundingMode(u32_f64, RM,  123.7, 123);
616  TestRoundingMode(u32_f64, RM,  123456.2,  123456);
617  TestRoundingMode(u32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
618  TestRoundingMode(u32_f64, RM, (kMaxInt + 0.5), kMaxInt);
619  TestRoundingMode(u32_f64, RM, (kMaxInt + 1.0),
620                                static_cast<uint32_t>(kMaxInt) + 1);
621  TestRoundingMode(u32_f64, RM, (kMaxUInt + 0.5), kMaxUInt);
622  TestRoundingMode(u32_f64, RM, (kMaxUInt + 1.0), kMaxUInt, true);
623
624  TestRoundingMode(u32_f64, RN,  0, 0);
625  TestRoundingMode(u32_f64, RN,  0.5, 0);
626  TestRoundingMode(u32_f64, RN,  1.5, 2);
627  TestRoundingMode(u32_f64, RN,  123.7, 124);
628  TestRoundingMode(u32_f64, RN,  123456.2,  123456);
629  TestRoundingMode(u32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
630  TestRoundingMode(u32_f64, RN, (kMaxInt + 0.49), kMaxInt);
631  TestRoundingMode(u32_f64, RN, (kMaxInt + 0.5),
632                                static_cast<uint32_t>(kMaxInt) + 1);
633  TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.49), kMaxUInt);
634  TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.5), kMaxUInt, true);
635  TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true);
636}
637
638
639TEST(8) {
640  // Test VFP multi load/store with ia_w.
641  CcTest::InitializeVM();
642  Isolate* isolate = CcTest::i_isolate();
643  HandleScope scope(isolate);
644
645  typedef struct {
646    double a;
647    double b;
648    double c;
649    double d;
650    double e;
651    double f;
652    double g;
653    double h;
654  } D;
655  D d;
656
657  typedef struct {
658    float a;
659    float b;
660    float c;
661    float d;
662    float e;
663    float f;
664    float g;
665    float h;
666  } F;
667  F f;
668
669  // Create a function that uses vldm/vstm to move some double and
670  // single precision values around in memory.
671  Assembler assm(isolate, NULL, 0);
672
673  if (CpuFeatures::IsSupported(VFP2)) {
674    CpuFeatures::Scope scope(VFP2);
675
676    __ mov(ip, Operand(sp));
677    __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
678    __ sub(fp, ip, Operand(4));
679
680    __ addi(r4, r0, Operand(offsetof(D, a)));
681    __ vldm(ia_w, r4, d0, d3);
682    __ vldm(ia_w, r4, d4, d7);
683
684    __ addi(r4, r0, Operand(offsetof(D, a)));
685    __ vstm(ia_w, r4, d6, d7);
686    __ vstm(ia_w, r4, d0, d5);
687
688    __ addi(r4, r1, Operand(offsetof(F, a)));
689    __ vldm(ia_w, r4, s0, s3);
690    __ vldm(ia_w, r4, s4, s7);
691
692    __ addi(r4, r1, Operand(offsetof(F, a)));
693    __ vstm(ia_w, r4, s6, s7);
694    __ vstm(ia_w, r4, s0, s5);
695
696    __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
697
698    CodeDesc desc;
699    assm.GetCode(&desc);
700    Object* code = isolate->heap()->CreateCode(
701        desc,
702        Code::ComputeFlags(Code::STUB),
703        Handle<Code>())->ToObjectChecked();
704    CHECK(code->IsCode());
705#ifdef DEBUG
706    Code::cast(code)->Print();
707#endif
708    F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
709    d.a = 1.1;
710    d.b = 2.2;
711    d.c = 3.3;
712    d.d = 4.4;
713    d.e = 5.5;
714    d.f = 6.6;
715    d.g = 7.7;
716    d.h = 8.8;
717
718    f.a = 1.0;
719    f.b = 2.0;
720    f.c = 3.0;
721    f.d = 4.0;
722    f.e = 5.0;
723    f.f = 6.0;
724    f.g = 7.0;
725    f.h = 8.0;
726
727    Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0);
728    USE(dummy);
729
730    CHECK_EQ(7.7, d.a);
731    CHECK_EQ(8.8, d.b);
732    CHECK_EQ(1.1, d.c);
733    CHECK_EQ(2.2, d.d);
734    CHECK_EQ(3.3, d.e);
735    CHECK_EQ(4.4, d.f);
736    CHECK_EQ(5.5, d.g);
737    CHECK_EQ(6.6, d.h);
738
739    CHECK_EQ(7.0, f.a);
740    CHECK_EQ(8.0, f.b);
741    CHECK_EQ(1.0, f.c);
742    CHECK_EQ(2.0, f.d);
743    CHECK_EQ(3.0, f.e);
744    CHECK_EQ(4.0, f.f);
745    CHECK_EQ(5.0, f.g);
746    CHECK_EQ(6.0, f.h);
747  }
748}
749
750
751TEST(9) {
752  // Test VFP multi load/store with ia.
753  CcTest::InitializeVM();
754  Isolate* isolate = CcTest::i_isolate();
755  HandleScope scope(isolate);
756
757  typedef struct {
758    double a;
759    double b;
760    double c;
761    double d;
762    double e;
763    double f;
764    double g;
765    double h;
766  } D;
767  D d;
768
769  typedef struct {
770    float a;
771    float b;
772    float c;
773    float d;
774    float e;
775    float f;
776    float g;
777    float h;
778  } F;
779  F f;
780
781  // Create a function that uses vldm/vstm to move some double and
782  // single precision values around in memory.
783  Assembler assm(isolate, NULL, 0);
784
785  if (CpuFeatures::IsSupported(VFP2)) {
786    CpuFeatures::Scope scope(VFP2);
787
788    __ mov(ip, Operand(sp));
789    __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
790    __ sub(fp, ip, Operand(4));
791
792    __ addi(r4, r0, Operand(offsetof(D, a)));
793    __ vldm(ia, r4, d0, d3);
794    __ addi(r4, r4, Operand(4 * 8));
795    __ vldm(ia, r4, d4, d7);
796
797    __ addi(r4, r0, Operand(offsetof(D, a)));
798    __ vstm(ia, r4, d6, d7);
799    __ addi(r4, r4, Operand(2 * 8));
800    __ vstm(ia, r4, d0, d5);
801
802    __ addi(r4, r1, Operand(offsetof(F, a)));
803    __ vldm(ia, r4, s0, s3);
804    __ addi(r4, r4, Operand(4 * 4));
805    __ vldm(ia, r4, s4, s7);
806
807    __ addi(r4, r1, Operand(offsetof(F, a)));
808    __ vstm(ia, r4, s6, s7);
809    __ addi(r4, r4, Operand(2 * 4));
810    __ vstm(ia, r4, s0, s5);
811
812    __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
813
814    CodeDesc desc;
815    assm.GetCode(&desc);
816    Object* code = isolate->heap()->CreateCode(
817        desc,
818        Code::ComputeFlags(Code::STUB),
819        Handle<Code>())->ToObjectChecked();
820    CHECK(code->IsCode());
821#ifdef DEBUG
822    Code::cast(code)->Print();
823#endif
824    F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
825    d.a = 1.1;
826    d.b = 2.2;
827    d.c = 3.3;
828    d.d = 4.4;
829    d.e = 5.5;
830    d.f = 6.6;
831    d.g = 7.7;
832    d.h = 8.8;
833
834    f.a = 1.0;
835    f.b = 2.0;
836    f.c = 3.0;
837    f.d = 4.0;
838    f.e = 5.0;
839    f.f = 6.0;
840    f.g = 7.0;
841    f.h = 8.0;
842
843    Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0);
844    USE(dummy);
845
846    CHECK_EQ(7.7, d.a);
847    CHECK_EQ(8.8, d.b);
848    CHECK_EQ(1.1, d.c);
849    CHECK_EQ(2.2, d.d);
850    CHECK_EQ(3.3, d.e);
851    CHECK_EQ(4.4, d.f);
852    CHECK_EQ(5.5, d.g);
853    CHECK_EQ(6.6, d.h);
854
855    CHECK_EQ(7.0, f.a);
856    CHECK_EQ(8.0, f.b);
857    CHECK_EQ(1.0, f.c);
858    CHECK_EQ(2.0, f.d);
859    CHECK_EQ(3.0, f.e);
860    CHECK_EQ(4.0, f.f);
861    CHECK_EQ(5.0, f.g);
862    CHECK_EQ(6.0, f.h);
863  }
864}
865
866
867TEST(10) {
868  // Test VFP multi load/store with db_w.
869  CcTest::InitializeVM();
870  Isolate* isolate = CcTest::i_isolate();
871  HandleScope scope(isolate);
872
873  typedef struct {
874    double a;
875    double b;
876    double c;
877    double d;
878    double e;
879    double f;
880    double g;
881    double h;
882  } D;
883  D d;
884
885  typedef struct {
886    float a;
887    float b;
888    float c;
889    float d;
890    float e;
891    float f;
892    float g;
893    float h;
894  } F;
895  F f;
896
897  // Create a function that uses vldm/vstm to move some double and
898  // single precision values around in memory.
899  Assembler assm(isolate, NULL, 0);
900
901  if (CpuFeatures::IsSupported(VFP2)) {
902    CpuFeatures::Scope scope(VFP2);
903
904    __ mov(ip, Operand(sp));
905    __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
906    __ sub(fp, ip, Operand(4));
907
908    __ addi(r4, r0, Operand(offsetof(D, h) + 8));
909    __ vldm(db_w, r4, d4, d7);
910    __ vldm(db_w, r4, d0, d3);
911
912    __ addi(r4, r0, Operand(offsetof(D, h) + 8));
913    __ vstm(db_w, r4, d0, d5);
914    __ vstm(db_w, r4, d6, d7);
915
916    __ addi(r4, r1, Operand(offsetof(F, h) + 4));
917    __ vldm(db_w, r4, s4, s7);
918    __ vldm(db_w, r4, s0, s3);
919
920    __ addi(r4, r1, Operand(offsetof(F, h) + 4));
921    __ vstm(db_w, r4, s0, s5);
922    __ vstm(db_w, r4, s6, s7);
923
924    __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
925
926    CodeDesc desc;
927    assm.GetCode(&desc);
928    Object* code = isolate->heap()->CreateCode(
929        desc,
930        Code::ComputeFlags(Code::STUB),
931        Handle<Code>())->ToObjectChecked();
932    CHECK(code->IsCode());
933#ifdef DEBUG
934    Code::cast(code)->Print();
935#endif
936    F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
937    d.a = 1.1;
938    d.b = 2.2;
939    d.c = 3.3;
940    d.d = 4.4;
941    d.e = 5.5;
942    d.f = 6.6;
943    d.g = 7.7;
944    d.h = 8.8;
945
946    f.a = 1.0;
947    f.b = 2.0;
948    f.c = 3.0;
949    f.d = 4.0;
950    f.e = 5.0;
951    f.f = 6.0;
952    f.g = 7.0;
953    f.h = 8.0;
954
955    Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0);
956    USE(dummy);
957
958    CHECK_EQ(7.7, d.a);
959    CHECK_EQ(8.8, d.b);
960    CHECK_EQ(1.1, d.c);
961    CHECK_EQ(2.2, d.d);
962    CHECK_EQ(3.3, d.e);
963    CHECK_EQ(4.4, d.f);
964    CHECK_EQ(5.5, d.g);
965    CHECK_EQ(6.6, d.h);
966
967    CHECK_EQ(7.0, f.a);
968    CHECK_EQ(8.0, f.b);
969    CHECK_EQ(1.0, f.c);
970    CHECK_EQ(2.0, f.d);
971    CHECK_EQ(3.0, f.e);
972    CHECK_EQ(4.0, f.f);
973    CHECK_EQ(5.0, f.g);
974    CHECK_EQ(6.0, f.h);
975  }
976}
977
978
979TEST(11) {
980  // Test instructions using the carry flag.
981  CcTest::InitializeVM();
982  Isolate* isolate = CcTest::i_isolate();
983  HandleScope scope(isolate);
984
985  typedef struct {
986    int32_t a;
987    int32_t b;
988    int32_t c;
989    int32_t d;
990  } I;
991  I i;
992
993  i.a = 0xabcd0001;
994  i.b = 0xabcd0000;
995
996  Assembler assm(isolate, NULL, 0);
997
998  // Test HeapObject untagging.
999  __ ldr(r1, MemOperand(r0, offsetof(I, a)));
1000  __ mov(r1, Operand(r1, ASR, 1), SetCC);
1001  __ adc(r1, r1, Operand(r1), LeaveCC, cs);
1002  __ str(r1, MemOperand(r0, offsetof(I, a)));
1003
1004  __ ldr(r2, MemOperand(r0, offsetof(I, b)));
1005  __ mov(r2, Operand(r2, ASR, 1), SetCC);
1006  __ adc(r2, r2, Operand(r2), LeaveCC, cs);
1007  __ str(r2, MemOperand(r0, offsetof(I, b)));
1008
1009  // Test corner cases.
1010  __ mov(r1, Operand(0xffffffff));
1011  __ mov(r2, Operand::Zero());
1012  __ mov(r3, Operand(r1, ASR, 1), SetCC);  // Set the carry.
1013  __ adc(r3, r1, Operand(r2));
1014  __ str(r3, MemOperand(r0, offsetof(I, c)));
1015
1016  __ mov(r1, Operand(0xffffffff));
1017  __ mov(r2, Operand::Zero());
1018  __ mov(r3, Operand(r2, ASR, 1), SetCC);  // Unset the carry.
1019  __ adc(r3, r1, Operand(r2));
1020  __ str(r3, MemOperand(r0, offsetof(I, d)));
1021
1022  __ mov(pc, Operand(lr));
1023
1024  CodeDesc desc;
1025  assm.GetCode(&desc);
1026  Object* code = isolate->heap()->CreateCode(
1027      desc,
1028      Code::ComputeFlags(Code::STUB),
1029      Handle<Code>())->ToObjectChecked();
1030  CHECK(code->IsCode());
1031#ifdef DEBUG
1032  Code::cast(code)->Print();
1033#endif
1034  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1035  Object* dummy = CALL_GENERATED_CODE(isolate, f, &i, 0, 0, 0, 0);
1036  USE(dummy);
1037
1038  CHECK_EQ(0xabcd0001, i.a);
1039  CHECK_EQ(static_cast<int32_t>(0xabcd0000) >> 1, i.b);
1040  CHECK_EQ(0x00000000, i.c);
1041  CHECK_EQ(0xffffffff, i.d);
1042}
1043
1044
1045TEST(12) {
1046  // Test chaining of label usages within instructions (issue 1644).
1047  CcTest::InitializeVM();
1048  Isolate* isolate = CcTest::i_isolate();
1049  HandleScope scope(isolate);
1050
1051  Assembler assm(isolate, NULL, 0);
1052  Label target;
1053  __ b(eq, &target);
1054  __ b(ne, &target);
1055  __ bind(&target);
1056  __ nop();
1057}
1058#endif
1059
1060#undef __
1061