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