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