The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / test / cctest / test-assembler-arm.cc @ f230a1cf

History | View | Annotate | Download (40 KB)

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 "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

    
36
using namespace v8::internal;
37

    
38

    
39
// Define these function prototypes to match JSEntryFunction in execution.cc.
40
typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
41
typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
42
typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4);
43
typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4);
44

    
45

    
46
#define __ assm.
47

    
48
TEST(0) {
49
  CcTest::InitializeVM();
50
  Isolate* isolate = CcTest::i_isolate();
51
  HandleScope scope(isolate);
52

    
53
  Assembler assm(isolate, NULL, 0);
54

    
55
  __ add(r0, r0, Operand(r1));
56
  __ mov(pc, Operand(lr));
57

    
58
  CodeDesc desc;
59
  assm.GetCode(&desc);
60
  Object* code = isolate->heap()->CreateCode(
61
      desc,
62
      Code::ComputeFlags(Code::STUB),
63
      Handle<Code>())->ToObjectChecked();
64
  CHECK(code->IsCode());
65
#ifdef DEBUG
66
  Code::cast(code)->Print();
67
#endif
68
  F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
69
  int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 3, 4, 0, 0, 0));
70
  ::printf("f() = %d\n", res);
71
  CHECK_EQ(7, res);
72
}
73

    
74

    
75
TEST(1) {
76
  CcTest::InitializeVM();
77
  Isolate* isolate = CcTest::i_isolate();
78
  HandleScope scope(isolate);
79

    
80
  Assembler assm(isolate, NULL, 0);
81
  Label L, C;
82

    
83
  __ mov(r1, Operand(r0));
84
  __ mov(r0, Operand::Zero());
85
  __ b(&C);
86

    
87
  __ bind(&L);
88
  __ add(r0, r0, Operand(r1));
89
  __ sub(r1, r1, Operand(1));
90

    
91
  __ bind(&C);
92
  __ teq(r1, Operand::Zero());
93
  __ b(ne, &L);
94
  __ mov(pc, Operand(lr));
95

    
96
  CodeDesc desc;
97
  assm.GetCode(&desc);
98
  Object* code = isolate->heap()->CreateCode(
99
      desc,
100
      Code::ComputeFlags(Code::STUB),
101
      Handle<Code>())->ToObjectChecked();
102
  CHECK(code->IsCode());
103
#ifdef DEBUG
104
  Code::cast(code)->Print();
105
#endif
106
  F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
107
  int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 100, 0, 0, 0, 0));
108
  ::printf("f() = %d\n", res);
109
  CHECK_EQ(5050, res);
110
}
111

    
112

    
113
TEST(2) {
114
  CcTest::InitializeVM();
115
  Isolate* isolate = CcTest::i_isolate();
116
  HandleScope scope(isolate);
117

    
118
  Assembler assm(isolate, NULL, 0);
119
  Label L, C;
120

    
121
  __ mov(r1, Operand(r0));
122
  __ mov(r0, Operand(1));
123
  __ b(&C);
124

    
125
  __ bind(&L);
126
  __ mul(r0, r1, r0);
127
  __ sub(r1, r1, Operand(1));
128

    
129
  __ bind(&C);
130
  __ teq(r1, Operand::Zero());
131
  __ b(ne, &L);
132
  __ mov(pc, Operand(lr));
133

    
134
  // some relocated stuff here, not executed
135
  __ RecordComment("dead code, just testing relocations");
136
  __ mov(r0, Operand(isolate->factory()->true_value()));
137
  __ RecordComment("dead code, just testing immediate operands");
138
  __ mov(r0, Operand(-1));
139
  __ mov(r0, Operand(0xFF000000));
140
  __ mov(r0, Operand(0xF0F0F0F0));
141
  __ mov(r0, Operand(0xFFF0FFFF));
142

    
143
  CodeDesc desc;
144
  assm.GetCode(&desc);
145
  Object* code = isolate->heap()->CreateCode(
146
      desc,
147
      Code::ComputeFlags(Code::STUB),
148
      Handle<Code>())->ToObjectChecked();
149
  CHECK(code->IsCode());
150
#ifdef DEBUG
151
  Code::cast(code)->Print();
152
#endif
153
  F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
154
  int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 10, 0, 0, 0, 0));
155
  ::printf("f() = %d\n", res);
156
  CHECK_EQ(3628800, res);
157
}
158

    
159

    
160
TEST(3) {
161
  CcTest::InitializeVM();
162
  Isolate* isolate = CcTest::i_isolate();
163
  HandleScope scope(isolate);
164

    
165
  typedef struct {
166
    int i;
167
    char c;
168
    int16_t s;
169
  } T;
170
  T t;
171

    
172
  Assembler assm(isolate, NULL, 0);
173
  Label L, C;
174

    
175
  __ mov(ip, Operand(sp));
176
  __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
177
  __ sub(fp, ip, Operand(4));
178
  __ mov(r4, Operand(r0));
179
  __ ldr(r0, MemOperand(r4, OFFSET_OF(T, i)));
180
  __ mov(r2, Operand(r0, ASR, 1));
181
  __ str(r2, MemOperand(r4, OFFSET_OF(T, i)));
182
  __ ldrsb(r2, MemOperand(r4, OFFSET_OF(T, c)));
183
  __ add(r0, r2, Operand(r0));
184
  __ mov(r2, Operand(r2, LSL, 2));
185
  __ strb(r2, MemOperand(r4, OFFSET_OF(T, c)));
186
  __ ldrsh(r2, MemOperand(r4, OFFSET_OF(T, s)));
187
  __ add(r0, r2, Operand(r0));
188
  __ mov(r2, Operand(r2, ASR, 3));
189
  __ strh(r2, MemOperand(r4, OFFSET_OF(T, s)));
190
  __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
191

    
192
  CodeDesc desc;
193
  assm.GetCode(&desc);
194
  Object* code = isolate->heap()->CreateCode(
195
      desc,
196
      Code::ComputeFlags(Code::STUB),
197
      Handle<Code>())->ToObjectChecked();
198
  CHECK(code->IsCode());
199
#ifdef DEBUG
200
  Code::cast(code)->Print();
201
#endif
202
  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
203
  t.i = 100000;
204
  t.c = 10;
205
  t.s = 1000;
206
  int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0));
207
  ::printf("f() = %d\n", res);
208
  CHECK_EQ(101010, res);
209
  CHECK_EQ(100000/2, t.i);
210
  CHECK_EQ(10*4, t.c);
211
  CHECK_EQ(1000/8, t.s);
212
}
213

    
214

    
215
TEST(4) {
216
  // Test the VFP floating point instructions.
217
  CcTest::InitializeVM();
218
  Isolate* isolate = CcTest::i_isolate();
219
  HandleScope scope(isolate);
220

    
221
  typedef struct {
222
    double a;
223
    double b;
224
    double c;
225
    double d;
226
    double e;
227
    double f;
228
    double g;
229
    double h;
230
    int i;
231
    double j;
232
    double m;
233
    double n;
234
    float x;
235
    float y;
236
  } T;
237
  T t;
238

    
239
  // Create a function that accepts &t, and loads, manipulates, and stores
240
  // the doubles and floats.
241
  Assembler assm(isolate, NULL, 0);
242
  Label L, C;
243

    
244

    
245
  if (CpuFeatures::IsSupported(VFP3)) {
246
    CpuFeatureScope scope(&assm, VFP3);
247

    
248
    __ mov(ip, Operand(sp));
249
    __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
250
    __ sub(fp, ip, Operand(4));
251

    
252
    __ mov(r4, Operand(r0));
253
    __ vldr(d6, r4, OFFSET_OF(T, a));
254
    __ vldr(d7, r4, OFFSET_OF(T, b));
255
    __ vadd(d5, d6, d7);
256
    __ vstr(d5, r4, OFFSET_OF(T, c));
257

    
258
    __ vmla(d5, d6, d7);
259
    __ vmls(d5, d5, d6);
260

    
261
    __ vmov(r2, r3, d5);
262
    __ vmov(d4, r2, r3);
263
    __ vstr(d4, r4, OFFSET_OF(T, b));
264

    
265
    // Load t.x and t.y, switch values, and store back to the struct.
266
    __ vldr(s0, r4, OFFSET_OF(T, x));
267
    __ vldr(s31, r4, OFFSET_OF(T, y));
268
    __ vmov(s16, s0);
269
    __ vmov(s0, s31);
270
    __ vmov(s31, s16);
271
    __ vstr(s0, r4, OFFSET_OF(T, x));
272
    __ vstr(s31, r4, OFFSET_OF(T, y));
273

    
274
    // Move a literal into a register that can be encoded in the instruction.
275
    __ vmov(d4, 1.0);
276
    __ vstr(d4, r4, OFFSET_OF(T, e));
277

    
278
    // Move a literal into a register that requires 64 bits to encode.
279
    // 0x3ff0000010000000 = 1.000000059604644775390625
280
    __ vmov(d4, 1.000000059604644775390625);
281
    __ vstr(d4, r4, OFFSET_OF(T, d));
282

    
283
    // Convert from floating point to integer.
284
    __ vmov(d4, 2.0);
285
    __ vcvt_s32_f64(s31, d4);
286
    __ vstr(s31, r4, OFFSET_OF(T, i));
287

    
288
    // Convert from integer to floating point.
289
    __ mov(lr, Operand(42));
290
    __ vmov(s31, lr);
291
    __ vcvt_f64_s32(d4, s31);
292
    __ vstr(d4, r4, OFFSET_OF(T, f));
293

    
294
    // Convert from fixed point to floating point.
295
    __ mov(lr, Operand(1234));
296
    __ vmov(s8, lr);
297
    __ vcvt_f64_s32(d4, 1);
298
    __ vstr(d4, r4, OFFSET_OF(T, j));
299

    
300
    // Test vabs.
301
    __ vldr(d1, r4, OFFSET_OF(T, g));
302
    __ vabs(d0, d1);
303
    __ vstr(d0, r4, OFFSET_OF(T, g));
304
    __ vldr(d2, r4, OFFSET_OF(T, h));
305
    __ vabs(d0, d2);
306
    __ vstr(d0, r4, OFFSET_OF(T, h));
307

    
308
    // Test vneg.
309
    __ vldr(d1, r4, OFFSET_OF(T, m));
310
    __ vneg(d0, d1);
311
    __ vstr(d0, r4, OFFSET_OF(T, m));
312
    __ vldr(d1, r4, OFFSET_OF(T, n));
313
    __ vneg(d0, d1);
314
    __ vstr(d0, r4, OFFSET_OF(T, n));
315

    
316
    __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
317

    
318
    CodeDesc desc;
319
    assm.GetCode(&desc);
320
    Object* code = isolate->heap()->CreateCode(
321
        desc,
322
        Code::ComputeFlags(Code::STUB),
323
        Handle<Code>())->ToObjectChecked();
324
    CHECK(code->IsCode());
325
#ifdef DEBUG
326
    Code::cast(code)->Print();
327
#endif
328
    F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
329
    t.a = 1.5;
330
    t.b = 2.75;
331
    t.c = 17.17;
332
    t.d = 0.0;
333
    t.e = 0.0;
334
    t.f = 0.0;
335
    t.g = -2718.2818;
336
    t.h = 31415926.5;
337
    t.i = 0;
338
    t.j = 0;
339
    t.m = -2718.2818;
340
    t.n = 123.456;
341
    t.x = 4.5;
342
    t.y = 9.0;
343
    Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
344
    USE(dummy);
345
    CHECK_EQ(4.5, t.y);
346
    CHECK_EQ(9.0, t.x);
347
    CHECK_EQ(-123.456, t.n);
348
    CHECK_EQ(2718.2818, t.m);
349
    CHECK_EQ(2, t.i);
350
    CHECK_EQ(2718.2818, t.g);
351
    CHECK_EQ(31415926.5, t.h);
352
    CHECK_EQ(617.0, t.j);
353
    CHECK_EQ(42.0, t.f);
354
    CHECK_EQ(1.0, t.e);
355
    CHECK_EQ(1.000000059604644775390625, t.d);
356
    CHECK_EQ(4.25, t.c);
357
    CHECK_EQ(-4.1875, t.b);
358
    CHECK_EQ(1.5, t.a);
359
  }
360
}
361

    
362

    
363
TEST(5) {
364
  // Test the ARMv7 bitfield instructions.
365
  CcTest::InitializeVM();
366
  Isolate* isolate = CcTest::i_isolate();
367
  HandleScope scope(isolate);
368

    
369
  Assembler assm(isolate, NULL, 0);
370

    
371
  if (CpuFeatures::IsSupported(ARMv7)) {
372
    CpuFeatureScope scope(&assm, ARMv7);
373
    // On entry, r0 = 0xAAAAAAAA = 0b10..10101010.
374
    __ ubfx(r0, r0, 1, 12);  // 0b00..010101010101 = 0x555
375
    __ sbfx(r0, r0, 0, 5);   // 0b11..111111110101 = -11
376
    __ bfc(r0, 1, 3);        // 0b11..111111110001 = -15
377
    __ mov(r1, Operand(7));
378
    __ bfi(r0, r1, 3, 3);    // 0b11..111111111001 = -7
379
    __ mov(pc, Operand(lr));
380

    
381
    CodeDesc desc;
382
    assm.GetCode(&desc);
383
    Object* code = isolate->heap()->CreateCode(
384
        desc,
385
        Code::ComputeFlags(Code::STUB),
386
        Handle<Code>())->ToObjectChecked();
387
    CHECK(code->IsCode());
388
#ifdef DEBUG
389
    Code::cast(code)->Print();
390
#endif
391
    F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
392
    int res = reinterpret_cast<int>(
393
                CALL_GENERATED_CODE(f, 0xAAAAAAAA, 0, 0, 0, 0));
394
    ::printf("f() = %d\n", res);
395
    CHECK_EQ(-7, res);
396
  }
397
}
398

    
399

    
400
TEST(6) {
401
  // Test saturating instructions.
402
  CcTest::InitializeVM();
403
  Isolate* isolate = CcTest::i_isolate();
404
  HandleScope scope(isolate);
405

    
406
  Assembler assm(isolate, NULL, 0);
407

    
408
  if (CpuFeatures::IsSupported(ARMv7)) {
409
    CpuFeatureScope scope(&assm, ARMv7);
410
    __ usat(r1, 8, Operand(r0));           // Sat 0xFFFF to 0-255 = 0xFF.
411
    __ usat(r2, 12, Operand(r0, ASR, 9));  // Sat (0xFFFF>>9) to 0-4095 = 0x7F.
412
    __ usat(r3, 1, Operand(r0, LSL, 16));  // Sat (0xFFFF<<16) to 0-1 = 0x0.
413
    __ add(r0, r1, Operand(r2));
414
    __ add(r0, r0, Operand(r3));
415
    __ mov(pc, Operand(lr));
416

    
417
    CodeDesc desc;
418
    assm.GetCode(&desc);
419
    Object* code = isolate->heap()->CreateCode(
420
        desc,
421
        Code::ComputeFlags(Code::STUB),
422
        Handle<Code>())->ToObjectChecked();
423
    CHECK(code->IsCode());
424
#ifdef DEBUG
425
    Code::cast(code)->Print();
426
#endif
427
    F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
428
    int res = reinterpret_cast<int>(
429
                CALL_GENERATED_CODE(f, 0xFFFF, 0, 0, 0, 0));
430
    ::printf("f() = %d\n", res);
431
    CHECK_EQ(382, res);
432
  }
433
}
434

    
435

    
436
enum VCVTTypes {
437
  s32_f64,
438
  u32_f64
439
};
440

    
441
static void TestRoundingMode(VCVTTypes types,
442
                             VFPRoundingMode mode,
443
                             double value,
444
                             int expected,
445
                             bool expected_exception = false) {
446
  Isolate* isolate = CcTest::i_isolate();
447
  HandleScope scope(isolate);
448

    
449
  Assembler assm(isolate, NULL, 0);
450

    
451
  if (CpuFeatures::IsSupported(VFP3)) {
452
    CpuFeatureScope scope(&assm, VFP3);
453

    
454
    Label wrong_exception;
455

    
456
    __ vmrs(r1);
457
    // Set custom FPSCR.
458
    __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask));
459
    __ orr(r2, r2, Operand(mode));
460
    __ vmsr(r2);
461

    
462
    // Load value, convert, and move back result to r0 if everything went well.
463
    __ vmov(d1, value);
464
    switch (types) {
465
      case s32_f64:
466
        __ vcvt_s32_f64(s0, d1, kFPSCRRounding);
467
        break;
468

    
469
      case u32_f64:
470
        __ vcvt_u32_f64(s0, d1, kFPSCRRounding);
471
        break;
472

    
473
      default:
474
        UNREACHABLE();
475
        break;
476
    }
477
    // Check for vfp exceptions
478
    __ vmrs(r2);
479
    __ tst(r2, Operand(kVFPExceptionMask));
480
    // Check that we behaved as expected.
481
    __ b(&wrong_exception,
482
         expected_exception ? eq : ne);
483
    // There was no exception. Retrieve the result and return.
484
    __ vmov(r0, s0);
485
    __ mov(pc, Operand(lr));
486

    
487
    // The exception behaviour is not what we expected.
488
    // Load a special value and return.
489
    __ bind(&wrong_exception);
490
    __ mov(r0, Operand(11223344));
491
    __ mov(pc, Operand(lr));
492

    
493
    CodeDesc desc;
494
    assm.GetCode(&desc);
495
    Object* code = isolate->heap()->CreateCode(
496
        desc,
497
        Code::ComputeFlags(Code::STUB),
498
        Handle<Code>())->ToObjectChecked();
499
    CHECK(code->IsCode());
500
#ifdef DEBUG
501
    Code::cast(code)->Print();
502
#endif
503
    F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
504
    int res = reinterpret_cast<int>(
505
                CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
506
    ::printf("res = %d\n", res);
507
    CHECK_EQ(expected, res);
508
  }
509
}
510

    
511

    
512
TEST(7) {
513
  CcTest::InitializeVM();
514
  // Test vfp rounding modes.
515

    
516
  // s32_f64 (double to integer).
517

    
518
  TestRoundingMode(s32_f64, RN,  0, 0);
519
  TestRoundingMode(s32_f64, RN,  0.5, 0);
520
  TestRoundingMode(s32_f64, RN, -0.5, 0);
521
  TestRoundingMode(s32_f64, RN,  1.5, 2);
522
  TestRoundingMode(s32_f64, RN, -1.5, -2);
523
  TestRoundingMode(s32_f64, RN,  123.7, 124);
524
  TestRoundingMode(s32_f64, RN, -123.7, -124);
525
  TestRoundingMode(s32_f64, RN,  123456.2,  123456);
526
  TestRoundingMode(s32_f64, RN, -123456.2, -123456);
527
  TestRoundingMode(s32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
528
  TestRoundingMode(s32_f64, RN, (kMaxInt + 0.49), kMaxInt);
529
  TestRoundingMode(s32_f64, RN, (kMaxInt + 1.0), kMaxInt, true);
530
  TestRoundingMode(s32_f64, RN, (kMaxInt + 0.5), kMaxInt, true);
531
  TestRoundingMode(s32_f64, RN, static_cast<double>(kMinInt), kMinInt);
532
  TestRoundingMode(s32_f64, RN, (kMinInt - 0.5), kMinInt);
533
  TestRoundingMode(s32_f64, RN, (kMinInt - 1.0), kMinInt, true);
534
  TestRoundingMode(s32_f64, RN, (kMinInt - 0.51), kMinInt, true);
535

    
536
  TestRoundingMode(s32_f64, RM,  0, 0);
537
  TestRoundingMode(s32_f64, RM,  0.5, 0);
538
  TestRoundingMode(s32_f64, RM, -0.5, -1);
539
  TestRoundingMode(s32_f64, RM,  123.7, 123);
540
  TestRoundingMode(s32_f64, RM, -123.7, -124);
541
  TestRoundingMode(s32_f64, RM,  123456.2,  123456);
542
  TestRoundingMode(s32_f64, RM, -123456.2, -123457);
543
  TestRoundingMode(s32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
544
  TestRoundingMode(s32_f64, RM, (kMaxInt + 0.5), kMaxInt);
545
  TestRoundingMode(s32_f64, RM, (kMaxInt + 1.0), kMaxInt, true);
546
  TestRoundingMode(s32_f64, RM, static_cast<double>(kMinInt), kMinInt);
547
  TestRoundingMode(s32_f64, RM, (kMinInt - 0.5), kMinInt, true);
548
  TestRoundingMode(s32_f64, RM, (kMinInt + 0.5), kMinInt);
549

    
550
  TestRoundingMode(s32_f64, RZ,  0, 0);
551
  TestRoundingMode(s32_f64, RZ,  0.5, 0);
552
  TestRoundingMode(s32_f64, RZ, -0.5, 0);
553
  TestRoundingMode(s32_f64, RZ,  123.7,  123);
554
  TestRoundingMode(s32_f64, RZ, -123.7, -123);
555
  TestRoundingMode(s32_f64, RZ,  123456.2,  123456);
556
  TestRoundingMode(s32_f64, RZ, -123456.2, -123456);
557
  TestRoundingMode(s32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
558
  TestRoundingMode(s32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
559
  TestRoundingMode(s32_f64, RZ, (kMaxInt + 1.0), kMaxInt, true);
560
  TestRoundingMode(s32_f64, RZ, static_cast<double>(kMinInt), kMinInt);
561
  TestRoundingMode(s32_f64, RZ, (kMinInt - 0.5), kMinInt);
562
  TestRoundingMode(s32_f64, RZ, (kMinInt - 1.0), kMinInt, true);
563

    
564

    
565
  // u32_f64 (double to integer).
566

    
567
  // Negative values.
568
  TestRoundingMode(u32_f64, RN, -0.5, 0);
569
  TestRoundingMode(u32_f64, RN, -123456.7, 0, true);
570
  TestRoundingMode(u32_f64, RN, static_cast<double>(kMinInt), 0, true);
571
  TestRoundingMode(u32_f64, RN, kMinInt - 1.0, 0, true);
572

    
573
  TestRoundingMode(u32_f64, RM, -0.5, 0, true);
574
  TestRoundingMode(u32_f64, RM, -123456.7, 0, true);
575
  TestRoundingMode(u32_f64, RM, static_cast<double>(kMinInt), 0, true);
576
  TestRoundingMode(u32_f64, RM, kMinInt - 1.0, 0, true);
577

    
578
  TestRoundingMode(u32_f64, RZ, -0.5, 0);
579
  TestRoundingMode(u32_f64, RZ, -123456.7, 0, true);
580
  TestRoundingMode(u32_f64, RZ, static_cast<double>(kMinInt), 0, true);
581
  TestRoundingMode(u32_f64, RZ, kMinInt - 1.0, 0, true);
582

    
583
  // Positive values.
584
  // kMaxInt is the maximum *signed* integer: 0x7fffffff.
585
  static const uint32_t kMaxUInt = 0xffffffffu;
586
  TestRoundingMode(u32_f64, RZ,  0, 0);
587
  TestRoundingMode(u32_f64, RZ,  0.5, 0);
588
  TestRoundingMode(u32_f64, RZ,  123.7,  123);
589
  TestRoundingMode(u32_f64, RZ,  123456.2,  123456);
590
  TestRoundingMode(u32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
591
  TestRoundingMode(u32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
592
  TestRoundingMode(u32_f64, RZ, (kMaxInt + 1.0),
593
                                static_cast<uint32_t>(kMaxInt) + 1);
594
  TestRoundingMode(u32_f64, RZ, (kMaxUInt + 0.5), kMaxUInt);
595
  TestRoundingMode(u32_f64, RZ, (kMaxUInt + 1.0), kMaxUInt, true);
596

    
597
  TestRoundingMode(u32_f64, RM,  0, 0);
598
  TestRoundingMode(u32_f64, RM,  0.5, 0);
599
  TestRoundingMode(u32_f64, RM,  123.7, 123);
600
  TestRoundingMode(u32_f64, RM,  123456.2,  123456);
601
  TestRoundingMode(u32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
602
  TestRoundingMode(u32_f64, RM, (kMaxInt + 0.5), kMaxInt);
603
  TestRoundingMode(u32_f64, RM, (kMaxInt + 1.0),
604
                                static_cast<uint32_t>(kMaxInt) + 1);
605
  TestRoundingMode(u32_f64, RM, (kMaxUInt + 0.5), kMaxUInt);
606
  TestRoundingMode(u32_f64, RM, (kMaxUInt + 1.0), kMaxUInt, true);
607

    
608
  TestRoundingMode(u32_f64, RN,  0, 0);
609
  TestRoundingMode(u32_f64, RN,  0.5, 0);
610
  TestRoundingMode(u32_f64, RN,  1.5, 2);
611
  TestRoundingMode(u32_f64, RN,  123.7, 124);
612
  TestRoundingMode(u32_f64, RN,  123456.2,  123456);
613
  TestRoundingMode(u32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
614
  TestRoundingMode(u32_f64, RN, (kMaxInt + 0.49), kMaxInt);
615
  TestRoundingMode(u32_f64, RN, (kMaxInt + 0.5),
616
                                static_cast<uint32_t>(kMaxInt) + 1);
617
  TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.49), kMaxUInt);
618
  TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.5), kMaxUInt, true);
619
  TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true);
620
}
621

    
622

    
623
TEST(8) {
624
  // Test VFP multi load/store with ia_w.
625
  CcTest::InitializeVM();
626
  Isolate* isolate = CcTest::i_isolate();
627
  HandleScope scope(isolate);
628

    
629
  typedef struct {
630
    double a;
631
    double b;
632
    double c;
633
    double d;
634
    double e;
635
    double f;
636
    double g;
637
    double h;
638
  } D;
639
  D d;
640

    
641
  typedef struct {
642
    float a;
643
    float b;
644
    float c;
645
    float d;
646
    float e;
647
    float f;
648
    float g;
649
    float h;
650
  } F;
651
  F f;
652

    
653
  // Create a function that uses vldm/vstm to move some double and
654
  // single precision values around in memory.
655
  Assembler assm(isolate, NULL, 0);
656

    
657
  __ mov(ip, Operand(sp));
658
  __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
659
  __ sub(fp, ip, Operand(4));
660

    
661
  __ add(r4, r0, Operand(OFFSET_OF(D, a)));
662
  __ vldm(ia_w, r4, d0, d3);
663
  __ vldm(ia_w, r4, d4, d7);
664

    
665
  __ add(r4, r0, Operand(OFFSET_OF(D, a)));
666
  __ vstm(ia_w, r4, d6, d7);
667
  __ vstm(ia_w, r4, d0, d5);
668

    
669
  __ add(r4, r1, Operand(OFFSET_OF(F, a)));
670
  __ vldm(ia_w, r4, s0, s3);
671
  __ vldm(ia_w, r4, s4, s7);
672

    
673
  __ add(r4, r1, Operand(OFFSET_OF(F, a)));
674
  __ vstm(ia_w, r4, s6, s7);
675
  __ vstm(ia_w, r4, s0, s5);
676

    
677
  __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
678

    
679
  CodeDesc desc;
680
  assm.GetCode(&desc);
681
  Object* code = isolate->heap()->CreateCode(
682
      desc,
683
      Code::ComputeFlags(Code::STUB),
684
      Handle<Code>())->ToObjectChecked();
685
  CHECK(code->IsCode());
686
#ifdef DEBUG
687
  Code::cast(code)->Print();
688
#endif
689
  F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
690
  d.a = 1.1;
691
  d.b = 2.2;
692
  d.c = 3.3;
693
  d.d = 4.4;
694
  d.e = 5.5;
695
  d.f = 6.6;
696
  d.g = 7.7;
697
  d.h = 8.8;
698

    
699
  f.a = 1.0;
700
  f.b = 2.0;
701
  f.c = 3.0;
702
  f.d = 4.0;
703
  f.e = 5.0;
704
  f.f = 6.0;
705
  f.g = 7.0;
706
  f.h = 8.0;
707

    
708
  Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
709
  USE(dummy);
710

    
711
  CHECK_EQ(7.7, d.a);
712
  CHECK_EQ(8.8, d.b);
713
  CHECK_EQ(1.1, d.c);
714
  CHECK_EQ(2.2, d.d);
715
  CHECK_EQ(3.3, d.e);
716
  CHECK_EQ(4.4, d.f);
717
  CHECK_EQ(5.5, d.g);
718
  CHECK_EQ(6.6, d.h);
719

    
720
  CHECK_EQ(7.0, f.a);
721
  CHECK_EQ(8.0, f.b);
722
  CHECK_EQ(1.0, f.c);
723
  CHECK_EQ(2.0, f.d);
724
  CHECK_EQ(3.0, f.e);
725
  CHECK_EQ(4.0, f.f);
726
  CHECK_EQ(5.0, f.g);
727
  CHECK_EQ(6.0, f.h);
728
}
729

    
730

    
731
TEST(9) {
732
  // Test VFP multi load/store with ia.
733
  CcTest::InitializeVM();
734
  Isolate* isolate = CcTest::i_isolate();
735
  HandleScope scope(isolate);
736

    
737
  typedef struct {
738
    double a;
739
    double b;
740
    double c;
741
    double d;
742
    double e;
743
    double f;
744
    double g;
745
    double h;
746
  } D;
747
  D d;
748

    
749
  typedef struct {
750
    float a;
751
    float b;
752
    float c;
753
    float d;
754
    float e;
755
    float f;
756
    float g;
757
    float h;
758
  } F;
759
  F f;
760

    
761
  // Create a function that uses vldm/vstm to move some double and
762
  // single precision values around in memory.
763
  Assembler assm(isolate, NULL, 0);
764

    
765
  __ mov(ip, Operand(sp));
766
  __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
767
  __ sub(fp, ip, Operand(4));
768

    
769
  __ add(r4, r0, Operand(OFFSET_OF(D, a)));
770
  __ vldm(ia, r4, d0, d3);
771
  __ add(r4, r4, Operand(4 * 8));
772
  __ vldm(ia, r4, d4, d7);
773

    
774
  __ add(r4, r0, Operand(OFFSET_OF(D, a)));
775
  __ vstm(ia, r4, d6, d7);
776
  __ add(r4, r4, Operand(2 * 8));
777
  __ vstm(ia, r4, d0, d5);
778

    
779
  __ add(r4, r1, Operand(OFFSET_OF(F, a)));
780
  __ vldm(ia, r4, s0, s3);
781
  __ add(r4, r4, Operand(4 * 4));
782
  __ vldm(ia, r4, s4, s7);
783

    
784
  __ add(r4, r1, Operand(OFFSET_OF(F, a)));
785
  __ vstm(ia, r4, s6, s7);
786
  __ add(r4, r4, Operand(2 * 4));
787
  __ vstm(ia, r4, s0, s5);
788

    
789
  __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
790

    
791
  CodeDesc desc;
792
  assm.GetCode(&desc);
793
  Object* code = isolate->heap()->CreateCode(
794
      desc,
795
      Code::ComputeFlags(Code::STUB),
796
      Handle<Code>())->ToObjectChecked();
797
  CHECK(code->IsCode());
798
#ifdef DEBUG
799
  Code::cast(code)->Print();
800
#endif
801
  F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
802
  d.a = 1.1;
803
  d.b = 2.2;
804
  d.c = 3.3;
805
  d.d = 4.4;
806
  d.e = 5.5;
807
  d.f = 6.6;
808
  d.g = 7.7;
809
  d.h = 8.8;
810

    
811
  f.a = 1.0;
812
  f.b = 2.0;
813
  f.c = 3.0;
814
  f.d = 4.0;
815
  f.e = 5.0;
816
  f.f = 6.0;
817
  f.g = 7.0;
818
  f.h = 8.0;
819

    
820
  Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
821
  USE(dummy);
822

    
823
  CHECK_EQ(7.7, d.a);
824
  CHECK_EQ(8.8, d.b);
825
  CHECK_EQ(1.1, d.c);
826
  CHECK_EQ(2.2, d.d);
827
  CHECK_EQ(3.3, d.e);
828
  CHECK_EQ(4.4, d.f);
829
  CHECK_EQ(5.5, d.g);
830
  CHECK_EQ(6.6, d.h);
831

    
832
  CHECK_EQ(7.0, f.a);
833
  CHECK_EQ(8.0, f.b);
834
  CHECK_EQ(1.0, f.c);
835
  CHECK_EQ(2.0, f.d);
836
  CHECK_EQ(3.0, f.e);
837
  CHECK_EQ(4.0, f.f);
838
  CHECK_EQ(5.0, f.g);
839
  CHECK_EQ(6.0, f.h);
840
}
841

    
842

    
843
TEST(10) {
844
  // Test VFP multi load/store with db_w.
845
  CcTest::InitializeVM();
846
  Isolate* isolate = CcTest::i_isolate();
847
  HandleScope scope(isolate);
848

    
849
  typedef struct {
850
    double a;
851
    double b;
852
    double c;
853
    double d;
854
    double e;
855
    double f;
856
    double g;
857
    double h;
858
  } D;
859
  D d;
860

    
861
  typedef struct {
862
    float a;
863
    float b;
864
    float c;
865
    float d;
866
    float e;
867
    float f;
868
    float g;
869
    float h;
870
  } F;
871
  F f;
872

    
873
  // Create a function that uses vldm/vstm to move some double and
874
  // single precision values around in memory.
875
  Assembler assm(isolate, NULL, 0);
876

    
877
  __ mov(ip, Operand(sp));
878
  __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
879
  __ sub(fp, ip, Operand(4));
880

    
881
  __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8));
882
  __ vldm(db_w, r4, d4, d7);
883
  __ vldm(db_w, r4, d0, d3);
884

    
885
  __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8));
886
  __ vstm(db_w, r4, d0, d5);
887
  __ vstm(db_w, r4, d6, d7);
888

    
889
  __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4));
890
  __ vldm(db_w, r4, s4, s7);
891
  __ vldm(db_w, r4, s0, s3);
892

    
893
  __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4));
894
  __ vstm(db_w, r4, s0, s5);
895
  __ vstm(db_w, r4, s6, s7);
896

    
897
  __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
898

    
899
  CodeDesc desc;
900
  assm.GetCode(&desc);
901
  Object* code = isolate->heap()->CreateCode(
902
      desc,
903
      Code::ComputeFlags(Code::STUB),
904
      Handle<Code>())->ToObjectChecked();
905
  CHECK(code->IsCode());
906
#ifdef DEBUG
907
  Code::cast(code)->Print();
908
#endif
909
  F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
910
  d.a = 1.1;
911
  d.b = 2.2;
912
  d.c = 3.3;
913
  d.d = 4.4;
914
  d.e = 5.5;
915
  d.f = 6.6;
916
  d.g = 7.7;
917
  d.h = 8.8;
918

    
919
  f.a = 1.0;
920
  f.b = 2.0;
921
  f.c = 3.0;
922
  f.d = 4.0;
923
  f.e = 5.0;
924
  f.f = 6.0;
925
  f.g = 7.0;
926
  f.h = 8.0;
927

    
928
  Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
929
  USE(dummy);
930

    
931
  CHECK_EQ(7.7, d.a);
932
  CHECK_EQ(8.8, d.b);
933
  CHECK_EQ(1.1, d.c);
934
  CHECK_EQ(2.2, d.d);
935
  CHECK_EQ(3.3, d.e);
936
  CHECK_EQ(4.4, d.f);
937
  CHECK_EQ(5.5, d.g);
938
  CHECK_EQ(6.6, d.h);
939

    
940
  CHECK_EQ(7.0, f.a);
941
  CHECK_EQ(8.0, f.b);
942
  CHECK_EQ(1.0, f.c);
943
  CHECK_EQ(2.0, f.d);
944
  CHECK_EQ(3.0, f.e);
945
  CHECK_EQ(4.0, f.f);
946
  CHECK_EQ(5.0, f.g);
947
  CHECK_EQ(6.0, f.h);
948
}
949

    
950

    
951
TEST(11) {
952
  // Test instructions using the carry flag.
953
  CcTest::InitializeVM();
954
  Isolate* isolate = CcTest::i_isolate();
955
  HandleScope scope(isolate);
956

    
957
  typedef struct {
958
    int32_t a;
959
    int32_t b;
960
    int32_t c;
961
    int32_t d;
962
  } I;
963
  I i;
964

    
965
  i.a = 0xabcd0001;
966
  i.b = 0xabcd0000;
967

    
968
  Assembler assm(isolate, NULL, 0);
969

    
970
  // Test HeapObject untagging.
971
  __ ldr(r1, MemOperand(r0, OFFSET_OF(I, a)));
972
  __ mov(r1, Operand(r1, ASR, 1), SetCC);
973
  __ adc(r1, r1, Operand(r1), LeaveCC, cs);
974
  __ str(r1, MemOperand(r0, OFFSET_OF(I, a)));
975

    
976
  __ ldr(r2, MemOperand(r0, OFFSET_OF(I, b)));
977
  __ mov(r2, Operand(r2, ASR, 1), SetCC);
978
  __ adc(r2, r2, Operand(r2), LeaveCC, cs);
979
  __ str(r2, MemOperand(r0, OFFSET_OF(I, b)));
980

    
981
  // Test corner cases.
982
  __ mov(r1, Operand(0xffffffff));
983
  __ mov(r2, Operand::Zero());
984
  __ mov(r3, Operand(r1, ASR, 1), SetCC);  // Set the carry.
985
  __ adc(r3, r1, Operand(r2));
986
  __ str(r3, MemOperand(r0, OFFSET_OF(I, c)));
987

    
988
  __ mov(r1, Operand(0xffffffff));
989
  __ mov(r2, Operand::Zero());
990
  __ mov(r3, Operand(r2, ASR, 1), SetCC);  // Unset the carry.
991
  __ adc(r3, r1, Operand(r2));
992
  __ str(r3, MemOperand(r0, OFFSET_OF(I, d)));
993

    
994
  __ mov(pc, Operand(lr));
995

    
996
  CodeDesc desc;
997
  assm.GetCode(&desc);
998
  Object* code = isolate->heap()->CreateCode(
999
      desc,
1000
      Code::ComputeFlags(Code::STUB),
1001
      Handle<Code>())->ToObjectChecked();
1002
  CHECK(code->IsCode());
1003
#ifdef DEBUG
1004
  Code::cast(code)->Print();
1005
#endif
1006
  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1007
  Object* dummy = CALL_GENERATED_CODE(f, &i, 0, 0, 0, 0);
1008
  USE(dummy);
1009

    
1010
  CHECK_EQ(0xabcd0001, i.a);
1011
  CHECK_EQ(static_cast<int32_t>(0xabcd0000) >> 1, i.b);
1012
  CHECK_EQ(0x00000000, i.c);
1013
  CHECK_EQ(0xffffffff, i.d);
1014
}
1015

    
1016

    
1017
TEST(12) {
1018
  // Test chaining of label usages within instructions (issue 1644).
1019
  CcTest::InitializeVM();
1020
  Isolate* isolate = CcTest::i_isolate();
1021
  HandleScope scope(isolate);
1022

    
1023
  Assembler assm(isolate, NULL, 0);
1024
  Label target;
1025
  __ b(eq, &target);
1026
  __ b(ne, &target);
1027
  __ bind(&target);
1028
  __ nop();
1029
}
1030

    
1031

    
1032
TEST(13) {
1033
  // Test VFP instructions using registers d16-d31.
1034
  CcTest::InitializeVM();
1035
  Isolate* isolate = CcTest::i_isolate();
1036
  HandleScope scope(isolate);
1037

    
1038
  if (!CpuFeatures::IsSupported(VFP32DREGS)) {
1039
    return;
1040
  }
1041

    
1042
  typedef struct {
1043
    double a;
1044
    double b;
1045
    double c;
1046
    double x;
1047
    double y;
1048
    double z;
1049
    double i;
1050
    double j;
1051
    double k;
1052
    uint32_t low;
1053
    uint32_t high;
1054
  } T;
1055
  T t;
1056

    
1057
  // Create a function that accepts &t, and loads, manipulates, and stores
1058
  // the doubles and floats.
1059
  Assembler assm(isolate, NULL, 0);
1060
  Label L, C;
1061

    
1062

    
1063
  if (CpuFeatures::IsSupported(VFP3)) {
1064
    CpuFeatureScope scope(&assm, VFP3);
1065

    
1066
    __ stm(db_w, sp, r4.bit() | lr.bit());
1067

    
1068
    // Load a, b, c into d16, d17, d18.
1069
    __ mov(r4, Operand(r0));
1070
    __ vldr(d16, r4, OFFSET_OF(T, a));
1071
    __ vldr(d17, r4, OFFSET_OF(T, b));
1072
    __ vldr(d18, r4, OFFSET_OF(T, c));
1073

    
1074
    __ vneg(d25, d16);
1075
    __ vadd(d25, d25, d17);
1076
    __ vsub(d25, d25, d18);
1077
    __ vmul(d25, d25, d25);
1078
    __ vdiv(d25, d25, d18);
1079

    
1080
    __ vmov(d16, d25);
1081
    __ vsqrt(d17, d25);
1082
    __ vneg(d17, d17);
1083
    __ vabs(d17, d17);
1084
    __ vmla(d18, d16, d17);
1085

    
1086
    // Store d16, d17, d18 into a, b, c.
1087
    __ mov(r4, Operand(r0));
1088
    __ vstr(d16, r4, OFFSET_OF(T, a));
1089
    __ vstr(d17, r4, OFFSET_OF(T, b));
1090
    __ vstr(d18, r4, OFFSET_OF(T, c));
1091

    
1092
    // Load x, y, z into d29-d31.
1093
    __ add(r4, r0, Operand(OFFSET_OF(T, x)));
1094
    __ vldm(ia_w, r4, d29, d31);
1095

    
1096
    // Swap d29 and d30 via r registers.
1097
    __ vmov(r1, r2, d29);
1098
    __ vmov(d29, d30);
1099
    __ vmov(d30, r1, r2);
1100

    
1101
    // Convert to and from integer.
1102
    __ vcvt_s32_f64(s1, d31);
1103
    __ vcvt_f64_u32(d31, s1);
1104

    
1105
    // Store d29-d31 into x, y, z.
1106
    __ add(r4, r0, Operand(OFFSET_OF(T, x)));
1107
    __ vstm(ia_w, r4, d29, d31);
1108

    
1109
    // Move constants into d20, d21, d22 and store into i, j, k.
1110
    __ vmov(d20, 14.7610017472335499);
1111
    __ vmov(d21, 16.0);
1112
    __ mov(r1, Operand(372106121));
1113
    __ mov(r2, Operand(1079146608));
1114
    __ vmov(d22, VmovIndexLo, r1);
1115
    __ vmov(d22, VmovIndexHi, r2);
1116
    __ add(r4, r0, Operand(OFFSET_OF(T, i)));
1117
    __ vstm(ia_w, r4, d20, d22);
1118
    // Move d22 into low and high.
1119
    __ vmov(r4, VmovIndexLo, d22);
1120
    __ str(r4, MemOperand(r0, OFFSET_OF(T, low)));
1121
    __ vmov(r4, VmovIndexHi, d22);
1122
    __ str(r4, MemOperand(r0, OFFSET_OF(T, high)));
1123

    
1124
    __ ldm(ia_w, sp, r4.bit() | pc.bit());
1125

    
1126
    CodeDesc desc;
1127
    assm.GetCode(&desc);
1128
    Object* code = isolate->heap()->CreateCode(
1129
        desc,
1130
        Code::ComputeFlags(Code::STUB),
1131
        Handle<Code>())->ToObjectChecked();
1132
    CHECK(code->IsCode());
1133
#ifdef DEBUG
1134
    Code::cast(code)->Print();
1135
#endif
1136
    F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1137
    t.a = 1.5;
1138
    t.b = 2.75;
1139
    t.c = 17.17;
1140
    t.x = 1.5;
1141
    t.y = 2.75;
1142
    t.z = 17.17;
1143
    Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1144
    USE(dummy);
1145
    CHECK_EQ(14.7610017472335499, t.a);
1146
    CHECK_EQ(3.84200491244266251, t.b);
1147
    CHECK_EQ(73.8818412254460241, t.c);
1148
    CHECK_EQ(2.75, t.x);
1149
    CHECK_EQ(1.5, t.y);
1150
    CHECK_EQ(17.0, t.z);
1151
    CHECK_EQ(14.7610017472335499, t.i);
1152
    CHECK_EQ(16.0, t.j);
1153
    CHECK_EQ(73.8818412254460241, t.k);
1154
    CHECK_EQ(372106121, t.low);
1155
    CHECK_EQ(1079146608, t.high);
1156
  }
1157
}
1158

    
1159

    
1160
TEST(14) {
1161
  // Test the VFP Canonicalized Nan mode.
1162
  CcTest::InitializeVM();
1163
  Isolate* isolate = CcTest::i_isolate();
1164
  HandleScope scope(isolate);
1165

    
1166
  typedef struct {
1167
    double left;
1168
    double right;
1169
    double add_result;
1170
    double sub_result;
1171
    double mul_result;
1172
    double div_result;
1173
  } T;
1174
  T t;
1175

    
1176
  // Create a function that makes the four basic operations.
1177
  Assembler assm(isolate, NULL, 0);
1178

    
1179
  // Ensure FPSCR state (as JSEntryStub does).
1180
  Label fpscr_done;
1181
  __ vmrs(r1);
1182
  __ tst(r1, Operand(kVFPDefaultNaNModeControlBit));
1183
  __ b(ne, &fpscr_done);
1184
  __ orr(r1, r1, Operand(kVFPDefaultNaNModeControlBit));
1185
  __ vmsr(r1);
1186
  __ bind(&fpscr_done);
1187

    
1188
  __ vldr(d0, r0, OFFSET_OF(T, left));
1189
  __ vldr(d1, r0, OFFSET_OF(T, right));
1190
  __ vadd(d2, d0, d1);
1191
  __ vstr(d2, r0, OFFSET_OF(T, add_result));
1192
  __ vsub(d2, d0, d1);
1193
  __ vstr(d2, r0, OFFSET_OF(T, sub_result));
1194
  __ vmul(d2, d0, d1);
1195
  __ vstr(d2, r0, OFFSET_OF(T, mul_result));
1196
  __ vdiv(d2, d0, d1);
1197
  __ vstr(d2, r0, OFFSET_OF(T, div_result));
1198

    
1199
  __ mov(pc, Operand(lr));
1200

    
1201
  CodeDesc desc;
1202
  assm.GetCode(&desc);
1203
  Object* code = isolate->heap()->CreateCode(
1204
      desc,
1205
      Code::ComputeFlags(Code::STUB),
1206
      Handle<Code>())->ToObjectChecked();
1207
  CHECK(code->IsCode());
1208
#ifdef DEBUG
1209
  Code::cast(code)->Print();
1210
#endif
1211
  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1212
  t.left = BitCast<double>(kHoleNanInt64);
1213
  t.right = 1;
1214
  t.add_result = 0;
1215
  t.sub_result = 0;
1216
  t.mul_result = 0;
1217
  t.div_result = 0;
1218
  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1219
  USE(dummy);
1220
  const uint32_t kArmNanUpper32 = 0x7ff80000;
1221
  const uint32_t kArmNanLower32 = 0x00000000;
1222
#ifdef DEBUG
1223
  const uint64_t kArmNanInt64 =
1224
      (static_cast<uint64_t>(kArmNanUpper32) << 32) | kArmNanLower32;
1225
  ASSERT(kArmNanInt64 != kHoleNanInt64);
1226
#endif
1227
  // With VFP2 the sign of the canonicalized Nan is undefined. So
1228
  // we remove the sign bit for the upper tests.
1229
  CHECK_EQ(kArmNanUpper32, (BitCast<int64_t>(t.add_result) >> 32) & 0x7fffffff);
1230
  CHECK_EQ(kArmNanLower32, BitCast<int64_t>(t.add_result) & 0xffffffffu);
1231
  CHECK_EQ(kArmNanUpper32, (BitCast<int64_t>(t.sub_result) >> 32) & 0x7fffffff);
1232
  CHECK_EQ(kArmNanLower32, BitCast<int64_t>(t.sub_result) & 0xffffffffu);
1233
  CHECK_EQ(kArmNanUpper32, (BitCast<int64_t>(t.mul_result) >> 32) & 0x7fffffff);
1234
  CHECK_EQ(kArmNanLower32, BitCast<int64_t>(t.mul_result) & 0xffffffffu);
1235
  CHECK_EQ(kArmNanUpper32, (BitCast<int64_t>(t.div_result) >> 32) & 0x7fffffff);
1236
  CHECK_EQ(kArmNanLower32, BitCast<int64_t>(t.div_result) & 0xffffffffu);
1237
}
1238

    
1239

    
1240
TEST(15) {
1241
  // Test the Neon instructions.
1242
  CcTest::InitializeVM();
1243
  Isolate* isolate = CcTest::i_isolate();
1244
  HandleScope scope(isolate);
1245

    
1246
  typedef struct {
1247
    uint32_t src0;
1248
    uint32_t src1;
1249
    uint32_t src2;
1250
    uint32_t src3;
1251
    uint32_t src4;
1252
    uint32_t src5;
1253
    uint32_t src6;
1254
    uint32_t src7;
1255
    uint32_t dst0;
1256
    uint32_t dst1;
1257
    uint32_t dst2;
1258
    uint32_t dst3;
1259
    uint32_t dst4;
1260
    uint32_t dst5;
1261
    uint32_t dst6;
1262
    uint32_t dst7;
1263
    uint32_t srcA0;
1264
    uint32_t srcA1;
1265
    uint32_t dstA0;
1266
    uint32_t dstA1;
1267
    uint32_t dstA2;
1268
    uint32_t dstA3;
1269
  } T;
1270
  T t;
1271

    
1272
  // Create a function that accepts &t, and loads, manipulates, and stores
1273
  // the doubles and floats.
1274
  Assembler assm(isolate, NULL, 0);
1275

    
1276

    
1277
  if (CpuFeatures::IsSupported(NEON)) {
1278
    CpuFeatureScope scope(&assm, NEON);
1279

    
1280
    __ stm(db_w, sp, r4.bit() | lr.bit());
1281
    // Move 32 bytes with neon.
1282
    __ add(r4, r0, Operand(OFFSET_OF(T, src0)));
1283
    __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4));
1284
    __ add(r4, r0, Operand(OFFSET_OF(T, dst0)));
1285
    __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4));
1286

    
1287
    // Expand 8 bytes into 8 words(16 bits).
1288
    __ add(r4, r0, Operand(OFFSET_OF(T, srcA0)));
1289
    __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(r4));
1290
    __ vmovl(NeonU8, q0, d0);
1291
    __ add(r4, r0, Operand(OFFSET_OF(T, dstA0)));
1292
    __ vst1(Neon8, NeonListOperand(d0, 2), NeonMemOperand(r4));
1293

    
1294
  __ ldm(ia_w, sp, r4.bit() | pc.bit());
1295

    
1296
    CodeDesc desc;
1297
    assm.GetCode(&desc);
1298
    Object* code = isolate->heap()->CreateCode(
1299
        desc,
1300
        Code::ComputeFlags(Code::STUB),
1301
        Handle<Code>())->ToObjectChecked();
1302
    CHECK(code->IsCode());
1303
#ifdef DEBUG
1304
    Code::cast(code)->Print();
1305
#endif
1306
    F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1307
    t.src0 = 0x01020304;
1308
    t.src1 = 0x11121314;
1309
    t.src2 = 0x21222324;
1310
    t.src3 = 0x31323334;
1311
    t.src4 = 0x41424344;
1312
    t.src5 = 0x51525354;
1313
    t.src6 = 0x61626364;
1314
    t.src7 = 0x71727374;
1315
    t.dst0 = 0;
1316
    t.dst1 = 0;
1317
    t.dst2 = 0;
1318
    t.dst3 = 0;
1319
    t.dst4 = 0;
1320
    t.dst5 = 0;
1321
    t.dst6 = 0;
1322
    t.dst7 = 0;
1323
    t.srcA0 = 0x41424344;
1324
    t.srcA1 = 0x81828384;
1325
    t.dstA0 = 0;
1326
    t.dstA1 = 0;
1327
    t.dstA2 = 0;
1328
    t.dstA3 = 0;
1329
    Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1330
    USE(dummy);
1331
    CHECK_EQ(0x01020304, t.dst0);
1332
    CHECK_EQ(0x11121314, t.dst1);
1333
    CHECK_EQ(0x21222324, t.dst2);
1334
    CHECK_EQ(0x31323334, t.dst3);
1335
    CHECK_EQ(0x41424344, t.dst4);
1336
    CHECK_EQ(0x51525354, t.dst5);
1337
    CHECK_EQ(0x61626364, t.dst6);
1338
    CHECK_EQ(0x71727374, t.dst7);
1339
    CHECK_EQ(0x00430044, t.dstA0);
1340
    CHECK_EQ(0x00410042, t.dstA1);
1341
    CHECK_EQ(0x00830084, t.dstA2);
1342
    CHECK_EQ(0x00810082, t.dstA3);
1343
  }
1344
}
1345

    
1346

    
1347
TEST(16) {
1348
  // Test the pkh, uxtb, uxtab and uxtb16 instructions.
1349
  CcTest::InitializeVM();
1350
  Isolate* isolate = CcTest::i_isolate();
1351
  HandleScope scope(isolate);
1352

    
1353
  typedef struct {
1354
    uint32_t src0;
1355
    uint32_t src1;
1356
    uint32_t src2;
1357
    uint32_t dst0;
1358
    uint32_t dst1;
1359
    uint32_t dst2;
1360
    uint32_t dst3;
1361
    uint32_t dst4;
1362
  } T;
1363
  T t;
1364

    
1365
  // Create a function that accepts &t, and loads, manipulates, and stores
1366
  // the doubles and floats.
1367
  Assembler assm(isolate, NULL, 0);
1368

    
1369
  __ stm(db_w, sp, r4.bit() | lr.bit());
1370

    
1371
  __ mov(r4, Operand(r0));
1372
  __ ldr(r0, MemOperand(r4, OFFSET_OF(T, src0)));
1373
  __ ldr(r1, MemOperand(r4, OFFSET_OF(T, src1)));
1374

    
1375
  __ pkhbt(r2, r0, Operand(r1, LSL, 8));
1376
  __ str(r2, MemOperand(r4, OFFSET_OF(T, dst0)));
1377

    
1378
  __ pkhtb(r2, r0, Operand(r1, ASR, 8));
1379
  __ str(r2, MemOperand(r4, OFFSET_OF(T, dst1)));
1380

    
1381
  __ uxtb16(r2, Operand(r0, ROR, 8));
1382
  __ str(r2, MemOperand(r4, OFFSET_OF(T, dst2)));
1383

    
1384
  __ uxtb(r2, Operand(r0, ROR, 8));
1385
  __ str(r2, MemOperand(r4, OFFSET_OF(T, dst3)));
1386

    
1387
  __ ldr(r0, MemOperand(r4, OFFSET_OF(T, src2)));
1388
  __ uxtab(r2, r0, Operand(r1, ROR, 8));
1389
  __ str(r2, MemOperand(r4, OFFSET_OF(T, dst4)));
1390

    
1391
  __ ldm(ia_w, sp, r4.bit() | pc.bit());
1392

    
1393
  CodeDesc desc;
1394
  assm.GetCode(&desc);
1395
  Object* code = isolate->heap()->CreateCode(
1396
      desc,
1397
      Code::ComputeFlags(Code::STUB),
1398
      Handle<Code>())->ToObjectChecked();
1399
  CHECK(code->IsCode());
1400
#ifdef DEBUG
1401
  Code::cast(code)->Print();
1402
#endif
1403
  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1404
  t.src0 = 0x01020304;
1405
  t.src1 = 0x11121314;
1406
  t.src2 = 0x11121300;
1407
  t.dst0 = 0;
1408
  t.dst1 = 0;
1409
  t.dst2 = 0;
1410
  t.dst3 = 0;
1411
  t.dst4 = 0;
1412
  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1413
  USE(dummy);
1414
  CHECK_EQ(0x12130304, t.dst0);
1415
  CHECK_EQ(0x01021213, t.dst1);
1416
  CHECK_EQ(0x00010003, t.dst2);
1417
  CHECK_EQ(0x00000003, t.dst3);
1418
  CHECK_EQ(0x11121313, t.dst4);
1419
}
1420

    
1421

    
1422
TEST(17) {
1423
  // Test generating labels at high addresses.
1424
  // Should not assert.
1425
  CcTest::InitializeVM();
1426
  Isolate* isolate = CcTest::i_isolate();
1427
  HandleScope scope(isolate);
1428

    
1429
  // Generate a code segment that will be longer than 2^24 bytes.
1430
  Assembler assm(isolate, NULL, 0);
1431
  for (size_t i = 0; i < 1 << 23 ; ++i) {  // 2^23
1432
    __ nop();
1433
  }
1434

    
1435
  Label target;
1436
  __ b(eq, &target);
1437
  __ bind(&target);
1438
  __ nop();
1439
}
1440

    
1441

    
1442
TEST(code_relative_offset) {
1443
  // Test extracting the offset of a label from the beginning of the code
1444
  // in a register.
1445
  CcTest::InitializeVM();
1446
  Isolate* isolate = CcTest::i_isolate();
1447
  HandleScope scope(isolate);
1448
  // Initialize a code object that will contain the code.
1449
  Handle<Object> code_object(isolate->heap()->undefined_value(), isolate);
1450

    
1451
  Assembler assm(isolate, NULL, 0);
1452

    
1453
  Label start, target_away, target_faraway;
1454

    
1455
  __ stm(db_w, sp, r4.bit() | r5.bit() | lr.bit());
1456

    
1457
  // r3 is used as the address zero, the test will crash when we load it.
1458
  __ mov(r3, Operand::Zero());
1459

    
1460
  // r5 will be a pointer to the start of the code.
1461
  __ mov(r5, Operand(code_object));
1462
  __ mov_label_offset(r4, &start);
1463

    
1464
  __ mov_label_offset(r1, &target_faraway);
1465
  __ str(r1, MemOperand(sp, kPointerSize, NegPreIndex));
1466

    
1467
  __ mov_label_offset(r1, &target_away);
1468

    
1469
  // Jump straight to 'target_away' the first time and use the relative
1470
  // position the second time. This covers the case when extracting the
1471
  // position of a label which is linked.
1472
  __ mov(r2, Operand::Zero());
1473
  __ bind(&start);
1474
  __ cmp(r2, Operand::Zero());
1475
  __ b(eq, &target_away);
1476
  __ add(pc, r5, r1);
1477
  // Emit invalid instructions to push the label between 2^8 and 2^16
1478
  // instructions away. The test will crash if they are reached.
1479
  for (int i = 0; i < (1 << 10); i++) {
1480
    __ ldr(r3, MemOperand(r3));
1481
  }
1482
  __ bind(&target_away);
1483
  // This will be hit twice: r0 = r0 + 5 + 5.
1484
  __ add(r0, r0, Operand(5));
1485

    
1486
  __ ldr(r1, MemOperand(sp, kPointerSize, PostIndex), ne);
1487
  __ add(pc, r5, r4, LeaveCC, ne);
1488

    
1489
  __ mov(r2, Operand(1));
1490
  __ b(&start);
1491
  // Emit invalid instructions to push the label between 2^16 and 2^24
1492
  // instructions away. The test will crash if they are reached.
1493
  for (int i = 0; i < (1 << 21); i++) {
1494
    __ ldr(r3, MemOperand(r3));
1495
  }
1496
  __ bind(&target_faraway);
1497
  // r0 = r0 + 5 + 5 + 11
1498
  __ add(r0, r0, Operand(11));
1499

    
1500
  __ ldm(ia_w, sp, r4.bit() | r5.bit() | pc.bit());
1501

    
1502
  CodeDesc desc;
1503
  assm.GetCode(&desc);
1504
  Handle<Code> code = isolate->factory()->NewCode(desc,
1505
      Code::ComputeFlags(Code::STUB), code_object);
1506
  CHECK(code->IsCode());
1507
  F1 f = FUNCTION_CAST<F1>(code->entry());
1508
  int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 21, 0, 0, 0, 0));
1509
  ::printf("f() = %d\n", res);
1510
  CHECK_EQ(42, res);
1511
}
1512

    
1513
#undef __