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