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