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