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 "v8.h"
     29 
     30 #include "disassembler.h"
     31 #include "factory.h"
     32 #include "macro-assembler.h"
     33 #include "mips/macro-assembler-mips.h"
     34 #include "mips/simulator-mips.h"
     35 
     36 #include "cctest.h"
     37 
     38 using namespace v8::internal;
     39 
     40 
     41 // Define these function prototypes to match JSEntryFunction in execution.cc.
     42 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
     43 typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
     44 typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4);
     45 
     46 
     47 #define __ assm.
     48 
     49 
     50 TEST(MIPS0) {
     51   CcTest::InitializeVM();
     52   Isolate* isolate = CcTest::i_isolate();
     53   HandleScope scope(isolate);
     54 
     55   MacroAssembler assm(isolate, NULL, 0);
     56 
     57   // Addition.
     58   __ addu(v0, a0, a1);
     59   __ jr(ra);
     60   __ nop();
     61 
     62   CodeDesc desc;
     63   assm.GetCode(&desc);
     64   Object* code = CcTest::heap()->CreateCode(
     65       desc,
     66       Code::ComputeFlags(Code::STUB),
     67       Handle<Code>())->ToObjectChecked();
     68   CHECK(code->IsCode());
     69   F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
     70   int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
     71   ::printf("f() = %d\n", res);
     72   CHECK_EQ(0xabc, res);
     73 }
     74 
     75 
     76 TEST(MIPS1) {
     77   CcTest::InitializeVM();
     78   Isolate* isolate = CcTest::i_isolate();
     79   HandleScope scope(isolate);
     80 
     81   MacroAssembler assm(isolate, NULL, 0);
     82   Label L, C;
     83 
     84   __ mov(a1, a0);
     85   __ li(v0, 0);
     86   __ b(&C);
     87   __ nop();
     88 
     89   __ bind(&L);
     90   __ addu(v0, v0, a1);
     91   __ addiu(a1, a1, -1);
     92 
     93   __ bind(&C);
     94   __ xori(v1, a1, 0);
     95   __ Branch(&L, ne, v1, Operand(0));
     96   __ nop();
     97 
     98   __ jr(ra);
     99   __ nop();
    100 
    101   CodeDesc desc;
    102   assm.GetCode(&desc);
    103   Object* code = CcTest::heap()->CreateCode(
    104       desc,
    105       Code::ComputeFlags(Code::STUB),
    106       Handle<Code>())->ToObjectChecked();
    107   CHECK(code->IsCode());
    108   F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
    109   int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 50, 0, 0, 0, 0));
    110   ::printf("f() = %d\n", res);
    111   CHECK_EQ(1275, res);
    112 }
    113 
    114 
    115 TEST(MIPS2) {
    116   CcTest::InitializeVM();
    117   Isolate* isolate = CcTest::i_isolate();
    118   HandleScope scope(isolate);
    119 
    120   MacroAssembler assm(isolate, NULL, 0);
    121 
    122   Label exit, error;
    123 
    124   // ----- Test all instructions.
    125 
    126   // Test lui, ori, and addiu, used in the li pseudo-instruction.
    127   // This way we can then safely load registers with chosen values.
    128 
    129   __ ori(t0, zero_reg, 0);
    130   __ lui(t0, 0x1234);
    131   __ ori(t0, t0, 0);
    132   __ ori(t0, t0, 0x0f0f);
    133   __ ori(t0, t0, 0xf0f0);
    134   __ addiu(t1, t0, 1);
    135   __ addiu(t2, t1, -0x10);
    136 
    137   // Load values in temporary registers.
    138   __ li(t0, 0x00000004);
    139   __ li(t1, 0x00001234);
    140   __ li(t2, 0x12345678);
    141   __ li(t3, 0x7fffffff);
    142   __ li(t4, 0xfffffffc);
    143   __ li(t5, 0xffffedcc);
    144   __ li(t6, 0xedcba988);
    145   __ li(t7, 0x80000000);
    146 
    147   // SPECIAL class.
    148   __ srl(v0, t2, 8);    // 0x00123456
    149   __ sll(v0, v0, 11);   // 0x91a2b000
    150   __ sra(v0, v0, 3);    // 0xf2345600
    151   __ srav(v0, v0, t0);  // 0xff234560
    152   __ sllv(v0, v0, t0);  // 0xf2345600
    153   __ srlv(v0, v0, t0);  // 0x0f234560
    154   __ Branch(&error, ne, v0, Operand(0x0f234560));
    155   __ nop();
    156 
    157   __ addu(v0, t0, t1);   // 0x00001238
    158   __ subu(v0, v0, t0);  // 0x00001234
    159   __ Branch(&error, ne, v0, Operand(0x00001234));
    160   __ nop();
    161   __ addu(v1, t3, t0);
    162   __ Branch(&error, ne, v1, Operand(0x80000003));
    163   __ nop();
    164   __ subu(v1, t7, t0);  // 0x7ffffffc
    165   __ Branch(&error, ne, v1, Operand(0x7ffffffc));
    166   __ nop();
    167 
    168   __ and_(v0, t1, t2);  // 0x00001230
    169   __ or_(v0, v0, t1);   // 0x00001234
    170   __ xor_(v0, v0, t2);  // 0x1234444c
    171   __ nor(v0, v0, t2);   // 0xedcba987
    172   __ Branch(&error, ne, v0, Operand(0xedcba983));
    173   __ nop();
    174 
    175   __ slt(v0, t7, t3);
    176   __ Branch(&error, ne, v0, Operand(0x1));
    177   __ nop();
    178   __ sltu(v0, t7, t3);
    179   __ Branch(&error, ne, v0, Operand(0x0));
    180   __ nop();
    181   // End of SPECIAL class.
    182 
    183   __ addiu(v0, zero_reg, 0x7421);  // 0x00007421
    184   __ addiu(v0, v0, -0x1);  // 0x00007420
    185   __ addiu(v0, v0, -0x20);  // 0x00007400
    186   __ Branch(&error, ne, v0, Operand(0x00007400));
    187   __ nop();
    188   __ addiu(v1, t3, 0x1);  // 0x80000000
    189   __ Branch(&error, ne, v1, Operand(0x80000000));
    190   __ nop();
    191 
    192   __ slti(v0, t1, 0x00002000);  // 0x1
    193   __ slti(v0, v0, 0xffff8000);  // 0x0
    194   __ Branch(&error, ne, v0, Operand(0x0));
    195   __ nop();
    196   __ sltiu(v0, t1, 0x00002000);  // 0x1
    197   __ sltiu(v0, v0, 0x00008000);  // 0x1
    198   __ Branch(&error, ne, v0, Operand(0x1));
    199   __ nop();
    200 
    201   __ andi(v0, t1, 0xf0f0);  // 0x00001030
    202   __ ori(v0, v0, 0x8a00);  // 0x00009a30
    203   __ xori(v0, v0, 0x83cc);  // 0x000019fc
    204   __ Branch(&error, ne, v0, Operand(0x000019fc));
    205   __ nop();
    206   __ lui(v1, 0x8123);  // 0x81230000
    207   __ Branch(&error, ne, v1, Operand(0x81230000));
    208   __ nop();
    209 
    210   // Bit twiddling instructions & conditional moves.
    211   // Uses t0-t7 as set above.
    212   __ Clz(v0, t0);       // 29
    213   __ Clz(v1, t1);       // 19
    214   __ addu(v0, v0, v1);  // 48
    215   __ Clz(v1, t2);       // 3
    216   __ addu(v0, v0, v1);  // 51
    217   __ Clz(v1, t7);       // 0
    218   __ addu(v0, v0, v1);  // 51
    219   __ Branch(&error, ne, v0, Operand(51));
    220   __ Movn(a0, t3, t0);  // Move a0<-t3 (t0 is NOT 0).
    221   __ Ins(a0, t1, 12, 8);  // 0x7ff34fff
    222   __ Branch(&error, ne, a0, Operand(0x7ff34fff));
    223   __ Movz(a0, t6, t7);    // a0 not updated (t7 is NOT 0).
    224   __ Ext(a1, a0, 8, 12);  // 0x34f
    225   __ Branch(&error, ne, a1, Operand(0x34f));
    226   __ Movz(a0, t6, v1);    // a0<-t6, v0 is 0, from 8 instr back.
    227   __ Branch(&error, ne, a0, Operand(t6));
    228 
    229   // Everything was correctly executed. Load the expected result.
    230   __ li(v0, 0x31415926);
    231   __ b(&exit);
    232   __ nop();
    233 
    234   __ bind(&error);
    235   // Got an error. Return a wrong result.
    236   __ li(v0, 666);
    237 
    238   __ bind(&exit);
    239   __ jr(ra);
    240   __ nop();
    241 
    242   CodeDesc desc;
    243   assm.GetCode(&desc);
    244   Object* code = CcTest::heap()->CreateCode(
    245       desc,
    246       Code::ComputeFlags(Code::STUB),
    247       Handle<Code>())->ToObjectChecked();
    248   CHECK(code->IsCode());
    249   F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
    250   int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
    251   ::printf("f() = %d\n", res);
    252   CHECK_EQ(0x31415926, res);
    253 }
    254 
    255 
    256 TEST(MIPS3) {
    257   // Test floating point instructions.
    258   CcTest::InitializeVM();
    259   Isolate* isolate = CcTest::i_isolate();
    260   HandleScope scope(isolate);
    261 
    262   typedef struct {
    263     double a;
    264     double b;
    265     double c;
    266     double d;
    267     double e;
    268     double f;
    269     double g;
    270     double h;
    271     double i;
    272   } T;
    273   T t;
    274 
    275   // Create a function that accepts &t, and loads, manipulates, and stores
    276   // the doubles t.a ... t.f.
    277   MacroAssembler assm(isolate, NULL, 0);
    278   Label L, C;
    279 
    280   __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
    281   __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
    282   __ add_d(f8, f4, f6);
    283   __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, c)) );  // c = a + b.
    284 
    285   __ mov_d(f10, f8);  // c
    286   __ neg_d(f12, f6);  // -b
    287   __ sub_d(f10, f10, f12);
    288   __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, d)) );  // d = c - (-b).
    289 
    290   __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, b)) );   // b = a.
    291 
    292   __ li(t0, 120);
    293   __ mtc1(t0, f14);
    294   __ cvt_d_w(f14, f14);   // f14 = 120.0.
    295   __ mul_d(f10, f10, f14);
    296   __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, e)) );  // e = d * 120 = 1.8066e16.
    297 
    298   __ div_d(f12, f10, f4);
    299   __ sdc1(f12, MemOperand(a0, OFFSET_OF(T, f)) );  // f = e / a = 120.44.
    300 
    301   __ sqrt_d(f14, f12);
    302   __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, g)) );
    303   // g = sqrt(f) = 10.97451593465515908537
    304 
    305   if (kArchVariant == kMips32r2) {
    306     __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, h)) );
    307     __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, i)) );
    308     __ madd_d(f14, f6, f4, f6);
    309     __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, h)) );
    310   }
    311 
    312   __ jr(ra);
    313   __ nop();
    314 
    315   CodeDesc desc;
    316   assm.GetCode(&desc);
    317   Object* code = CcTest::heap()->CreateCode(
    318       desc,
    319       Code::ComputeFlags(Code::STUB),
    320       Handle<Code>())->ToObjectChecked();
    321   CHECK(code->IsCode());
    322   F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
    323   t.a = 1.5e14;
    324   t.b = 2.75e11;
    325   t.c = 0.0;
    326   t.d = 0.0;
    327   t.e = 0.0;
    328   t.f = 0.0;
    329   t.h = 1.5;
    330   t.i = 2.75;
    331   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
    332   USE(dummy);
    333   CHECK_EQ(1.5e14, t.a);
    334   CHECK_EQ(1.5e14, t.b);
    335   CHECK_EQ(1.50275e14, t.c);
    336   CHECK_EQ(1.50550e14, t.d);
    337   CHECK_EQ(1.8066e16, t.e);
    338   CHECK_EQ(120.44, t.f);
    339   CHECK_EQ(10.97451593465515908537, t.g);
    340   if (kArchVariant == kMips32r2) {
    341     CHECK_EQ(6.875, t.h);
    342   }
    343 }
    344 
    345 
    346 TEST(MIPS4) {
    347   // Test moves between floating point and integer registers.
    348   CcTest::InitializeVM();
    349   Isolate* isolate = CcTest::i_isolate();
    350   HandleScope scope(isolate);
    351 
    352   typedef struct {
    353     double a;
    354     double b;
    355     double c;
    356   } T;
    357   T t;
    358 
    359   Assembler assm(isolate, NULL, 0);
    360   Label L, C;
    361 
    362   __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
    363   __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
    364 
    365   // Swap f4 and f6, by using four integer registers, t0-t3.
    366   __ mfc1(t0, f4);
    367   __ mfc1(t1, f5);
    368   __ mfc1(t2, f6);
    369   __ mfc1(t3, f7);
    370 
    371   __ mtc1(t0, f6);
    372   __ mtc1(t1, f7);
    373   __ mtc1(t2, f4);
    374   __ mtc1(t3, f5);
    375 
    376   // Store the swapped f4 and f5 back to memory.
    377   __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
    378   __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, c)) );
    379 
    380   __ jr(ra);
    381   __ nop();
    382 
    383   CodeDesc desc;
    384   assm.GetCode(&desc);
    385   Object* code = CcTest::heap()->CreateCode(
    386       desc,
    387       Code::ComputeFlags(Code::STUB),
    388       Handle<Code>())->ToObjectChecked();
    389   CHECK(code->IsCode());
    390   F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
    391   t.a = 1.5e22;
    392   t.b = 2.75e11;
    393   t.c = 17.17;
    394   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
    395   USE(dummy);
    396 
    397   CHECK_EQ(2.75e11, t.a);
    398   CHECK_EQ(2.75e11, t.b);
    399   CHECK_EQ(1.5e22, t.c);
    400 }
    401 
    402 
    403 TEST(MIPS5) {
    404   // Test conversions between doubles and integers.
    405   CcTest::InitializeVM();
    406   Isolate* isolate = CcTest::i_isolate();
    407   HandleScope scope(isolate);
    408 
    409   typedef struct {
    410     double a;
    411     double b;
    412     int i;
    413     int j;
    414   } T;
    415   T t;
    416 
    417   Assembler assm(isolate, NULL, 0);
    418   Label L, C;
    419 
    420   // Load all structure elements to registers.
    421   __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
    422   __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
    423   __ lw(t0, MemOperand(a0, OFFSET_OF(T, i)) );
    424   __ lw(t1, MemOperand(a0, OFFSET_OF(T, j)) );
    425 
    426   // Convert double in f4 to int in element i.
    427   __ cvt_w_d(f8, f4);
    428   __ mfc1(t2, f8);
    429   __ sw(t2, MemOperand(a0, OFFSET_OF(T, i)) );
    430 
    431   // Convert double in f6 to int in element j.
    432   __ cvt_w_d(f10, f6);
    433   __ mfc1(t3, f10);
    434   __ sw(t3, MemOperand(a0, OFFSET_OF(T, j)) );
    435 
    436   // Convert int in original i (t0) to double in a.
    437   __ mtc1(t0, f12);
    438   __ cvt_d_w(f0, f12);
    439   __ sdc1(f0, MemOperand(a0, OFFSET_OF(T, a)) );
    440 
    441   // Convert int in original j (t1) to double in b.
    442   __ mtc1(t1, f14);
    443   __ cvt_d_w(f2, f14);
    444   __ sdc1(f2, MemOperand(a0, OFFSET_OF(T, b)) );
    445 
    446   __ jr(ra);
    447   __ nop();
    448 
    449   CodeDesc desc;
    450   assm.GetCode(&desc);
    451   Object* code = CcTest::heap()->CreateCode(
    452       desc,
    453       Code::ComputeFlags(Code::STUB),
    454       Handle<Code>())->ToObjectChecked();
    455   CHECK(code->IsCode());
    456   F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
    457   t.a = 1.5e4;
    458   t.b = 2.75e8;
    459   t.i = 12345678;
    460   t.j = -100000;
    461   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
    462   USE(dummy);
    463 
    464   CHECK_EQ(12345678.0, t.a);
    465   CHECK_EQ(-100000.0, t.b);
    466   CHECK_EQ(15000, t.i);
    467   CHECK_EQ(275000000, t.j);
    468 }
    469 
    470 
    471 TEST(MIPS6) {
    472   // Test simple memory loads and stores.
    473   CcTest::InitializeVM();
    474   Isolate* isolate = CcTest::i_isolate();
    475   HandleScope scope(isolate);
    476 
    477   typedef struct {
    478     uint32_t ui;
    479     int32_t si;
    480     int32_t r1;
    481     int32_t r2;
    482     int32_t r3;
    483     int32_t r4;
    484     int32_t r5;
    485     int32_t r6;
    486   } T;
    487   T t;
    488 
    489   Assembler assm(isolate, NULL, 0);
    490   Label L, C;
    491 
    492   // Basic word load/store.
    493   __ lw(t0, MemOperand(a0, OFFSET_OF(T, ui)) );
    494   __ sw(t0, MemOperand(a0, OFFSET_OF(T, r1)) );
    495 
    496   // lh with positive data.
    497   __ lh(t1, MemOperand(a0, OFFSET_OF(T, ui)) );
    498   __ sw(t1, MemOperand(a0, OFFSET_OF(T, r2)) );
    499 
    500   // lh with negative data.
    501   __ lh(t2, MemOperand(a0, OFFSET_OF(T, si)) );
    502   __ sw(t2, MemOperand(a0, OFFSET_OF(T, r3)) );
    503 
    504   // lhu with negative data.
    505   __ lhu(t3, MemOperand(a0, OFFSET_OF(T, si)) );
    506   __ sw(t3, MemOperand(a0, OFFSET_OF(T, r4)) );
    507 
    508   // lb with negative data.
    509   __ lb(t4, MemOperand(a0, OFFSET_OF(T, si)) );
    510   __ sw(t4, MemOperand(a0, OFFSET_OF(T, r5)) );
    511 
    512   // sh writes only 1/2 of word.
    513   __ lui(t5, 0x3333);
    514   __ ori(t5, t5, 0x3333);
    515   __ sw(t5, MemOperand(a0, OFFSET_OF(T, r6)) );
    516   __ lhu(t5, MemOperand(a0, OFFSET_OF(T, si)) );
    517   __ sh(t5, MemOperand(a0, OFFSET_OF(T, r6)) );
    518 
    519   __ jr(ra);
    520   __ nop();
    521 
    522   CodeDesc desc;
    523   assm.GetCode(&desc);
    524   Object* code = CcTest::heap()->CreateCode(
    525       desc,
    526       Code::ComputeFlags(Code::STUB),
    527       Handle<Code>())->ToObjectChecked();
    528   CHECK(code->IsCode());
    529   F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
    530   t.ui = 0x11223344;
    531   t.si = 0x99aabbcc;
    532   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
    533   USE(dummy);
    534 
    535   CHECK_EQ(0x11223344, t.r1);
    536   CHECK_EQ(0x3344, t.r2);
    537   CHECK_EQ(0xffffbbcc, t.r3);
    538   CHECK_EQ(0x0000bbcc, t.r4);
    539   CHECK_EQ(0xffffffcc, t.r5);
    540   CHECK_EQ(0x3333bbcc, t.r6);
    541 }
    542 
    543 
    544 TEST(MIPS7) {
    545   // Test floating point compare and branch instructions.
    546   CcTest::InitializeVM();
    547   Isolate* isolate = CcTest::i_isolate();
    548   HandleScope scope(isolate);
    549 
    550   typedef struct {
    551     double a;
    552     double b;
    553     double c;
    554     double d;
    555     double e;
    556     double f;
    557     int32_t result;
    558   } T;
    559   T t;
    560 
    561   // Create a function that accepts &t, and loads, manipulates, and stores
    562   // the doubles t.a ... t.f.
    563   MacroAssembler assm(isolate, NULL, 0);
    564   Label neither_is_nan, less_than, outa_here;
    565 
    566   __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
    567   __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
    568   __ c(UN, D, f4, f6);
    569   __ bc1f(&neither_is_nan);
    570   __ nop();
    571   __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
    572   __ Branch(&outa_here);
    573 
    574   __ bind(&neither_is_nan);
    575 
    576   if (kArchVariant == kLoongson) {
    577     __ c(OLT, D, f6, f4);
    578     __ bc1t(&less_than);
    579   } else {
    580     __ c(OLT, D, f6, f4, 2);
    581     __ bc1t(&less_than, 2);
    582   }
    583   __ nop();
    584   __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
    585   __ Branch(&outa_here);
    586 
    587   __ bind(&less_than);
    588   __ Addu(t0, zero_reg, Operand(1));
    589   __ sw(t0, MemOperand(a0, OFFSET_OF(T, result)) );  // Set true.
    590 
    591 
    592   // This test-case should have additional tests.
    593 
    594   __ bind(&outa_here);
    595 
    596   __ jr(ra);
    597   __ nop();
    598 
    599   CodeDesc desc;
    600   assm.GetCode(&desc);
    601   Object* code = CcTest::heap()->CreateCode(
    602       desc,
    603       Code::ComputeFlags(Code::STUB),
    604       Handle<Code>())->ToObjectChecked();
    605   CHECK(code->IsCode());
    606   F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
    607   t.a = 1.5e14;
    608   t.b = 2.75e11;
    609   t.c = 2.0;
    610   t.d = -4.0;
    611   t.e = 0.0;
    612   t.f = 0.0;
    613   t.result = 0;
    614   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
    615   USE(dummy);
    616   CHECK_EQ(1.5e14, t.a);
    617   CHECK_EQ(2.75e11, t.b);
    618   CHECK_EQ(1, t.result);
    619 }
    620 
    621 
    622 TEST(MIPS8) {
    623   // Test ROTR and ROTRV instructions.
    624   CcTest::InitializeVM();
    625   Isolate* isolate = CcTest::i_isolate();
    626   HandleScope scope(isolate);
    627 
    628   typedef struct {
    629     int32_t input;
    630     int32_t result_rotr_4;
    631     int32_t result_rotr_8;
    632     int32_t result_rotr_12;
    633     int32_t result_rotr_16;
    634     int32_t result_rotr_20;
    635     int32_t result_rotr_24;
    636     int32_t result_rotr_28;
    637     int32_t result_rotrv_4;
    638     int32_t result_rotrv_8;
    639     int32_t result_rotrv_12;
    640     int32_t result_rotrv_16;
    641     int32_t result_rotrv_20;
    642     int32_t result_rotrv_24;
    643     int32_t result_rotrv_28;
    644   } T;
    645   T t;
    646 
    647   MacroAssembler assm(isolate, NULL, 0);
    648 
    649   // Basic word load.
    650   __ lw(t0, MemOperand(a0, OFFSET_OF(T, input)) );
    651 
    652   // ROTR instruction (called through the Ror macro).
    653   __ Ror(t1, t0, 0x0004);
    654   __ Ror(t2, t0, 0x0008);
    655   __ Ror(t3, t0, 0x000c);
    656   __ Ror(t4, t0, 0x0010);
    657   __ Ror(t5, t0, 0x0014);
    658   __ Ror(t6, t0, 0x0018);
    659   __ Ror(t7, t0, 0x001c);
    660 
    661   // Basic word store.
    662   __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotr_4)) );
    663   __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotr_8)) );
    664   __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotr_12)) );
    665   __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotr_16)) );
    666   __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotr_20)) );
    667   __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotr_24)) );
    668   __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotr_28)) );
    669 
    670   // ROTRV instruction (called through the Ror macro).
    671   __ li(t7, 0x0004);
    672   __ Ror(t1, t0, t7);
    673   __ li(t7, 0x0008);
    674   __ Ror(t2, t0, t7);
    675   __ li(t7, 0x000C);
    676   __ Ror(t3, t0, t7);
    677   __ li(t7, 0x0010);
    678   __ Ror(t4, t0, t7);
    679   __ li(t7, 0x0014);
    680   __ Ror(t5, t0, t7);
    681   __ li(t7, 0x0018);
    682   __ Ror(t6, t0, t7);
    683   __ li(t7, 0x001C);
    684   __ Ror(t7, t0, t7);
    685 
    686   // Basic word store.
    687   __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotrv_4)) );
    688   __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotrv_8)) );
    689   __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotrv_12)) );
    690   __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotrv_16)) );
    691   __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotrv_20)) );
    692   __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotrv_24)) );
    693   __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotrv_28)) );
    694 
    695   __ jr(ra);
    696   __ nop();
    697 
    698   CodeDesc desc;
    699   assm.GetCode(&desc);
    700   Object* code = CcTest::heap()->CreateCode(
    701       desc,
    702       Code::ComputeFlags(Code::STUB),
    703       Handle<Code>())->ToObjectChecked();
    704   CHECK(code->IsCode());
    705   F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
    706   t.input = 0x12345678;
    707   Object* dummy = CALL_GENERATED_CODE(f, &t, 0x0, 0, 0, 0);
    708   USE(dummy);
    709   CHECK_EQ(0x81234567, t.result_rotr_4);
    710   CHECK_EQ(0x78123456, t.result_rotr_8);
    711   CHECK_EQ(0x67812345, t.result_rotr_12);
    712   CHECK_EQ(0x56781234, t.result_rotr_16);
    713   CHECK_EQ(0x45678123, t.result_rotr_20);
    714   CHECK_EQ(0x34567812, t.result_rotr_24);
    715   CHECK_EQ(0x23456781, t.result_rotr_28);
    716 
    717   CHECK_EQ(0x81234567, t.result_rotrv_4);
    718   CHECK_EQ(0x78123456, t.result_rotrv_8);
    719   CHECK_EQ(0x67812345, t.result_rotrv_12);
    720   CHECK_EQ(0x56781234, t.result_rotrv_16);
    721   CHECK_EQ(0x45678123, t.result_rotrv_20);
    722   CHECK_EQ(0x34567812, t.result_rotrv_24);
    723   CHECK_EQ(0x23456781, t.result_rotrv_28);
    724 }
    725 
    726 
    727 TEST(MIPS9) {
    728   // Test BRANCH improvements.
    729   CcTest::InitializeVM();
    730   Isolate* isolate = CcTest::i_isolate();
    731   HandleScope scope(isolate);
    732 
    733   MacroAssembler assm(isolate, NULL, 0);
    734   Label exit, exit2, exit3;
    735 
    736   __ Branch(&exit, ge, a0, Operand(0x00000000));
    737   __ Branch(&exit2, ge, a0, Operand(0x00001FFF));
    738   __ Branch(&exit3, ge, a0, Operand(0x0001FFFF));
    739 
    740   __ bind(&exit);
    741   __ bind(&exit2);
    742   __ bind(&exit3);
    743   __ jr(ra);
    744   __ nop();
    745 
    746   CodeDesc desc;
    747   assm.GetCode(&desc);
    748   Object* code = CcTest::heap()->CreateCode(
    749       desc,
    750       Code::ComputeFlags(Code::STUB),
    751       Handle<Code>())->ToObjectChecked();
    752   CHECK(code->IsCode());
    753 }
    754 
    755 
    756 TEST(MIPS10) {
    757   // Test conversions between doubles and long integers.
    758   // Test hos the long ints map to FP regs pairs.
    759   CcTest::InitializeVM();
    760   Isolate* isolate = CcTest::i_isolate();
    761   HandleScope scope(isolate);
    762 
    763   typedef struct {
    764     double a;
    765     double b;
    766     int32_t dbl_mant;
    767     int32_t dbl_exp;
    768     int32_t long_hi;
    769     int32_t long_lo;
    770     int32_t b_long_hi;
    771     int32_t b_long_lo;
    772   } T;
    773   T t;
    774 
    775   Assembler assm(isolate, NULL, 0);
    776   Label L, C;
    777 
    778   if (kArchVariant == kMips32r2) {
    779     // Load all structure elements to registers.
    780     __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, a)));
    781 
    782     // Save the raw bits of the double.
    783     __ mfc1(t0, f0);
    784     __ mfc1(t1, f1);
    785     __ sw(t0, MemOperand(a0, OFFSET_OF(T, dbl_mant)));
    786     __ sw(t1, MemOperand(a0, OFFSET_OF(T, dbl_exp)));
    787 
    788     // Convert double in f0 to long, save hi/lo parts.
    789     __ cvt_l_d(f0, f0);
    790     __ mfc1(t0, f0);  // f0 has LS 32 bits of long.
    791     __ mfc1(t1, f1);  // f1 has MS 32 bits of long.
    792     __ sw(t0, MemOperand(a0, OFFSET_OF(T, long_lo)));
    793     __ sw(t1, MemOperand(a0, OFFSET_OF(T, long_hi)));
    794 
    795     // Convert the b long integers to double b.
    796     __ lw(t0, MemOperand(a0, OFFSET_OF(T, b_long_lo)));
    797     __ lw(t1, MemOperand(a0, OFFSET_OF(T, b_long_hi)));
    798     __ mtc1(t0, f8);  // f8 has LS 32-bits.
    799     __ mtc1(t1, f9);  // f9 has MS 32-bits.
    800     __ cvt_d_l(f10, f8);
    801     __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, b)));
    802 
    803     __ jr(ra);
    804     __ nop();
    805 
    806     CodeDesc desc;
    807     assm.GetCode(&desc);
    808     Object* code = CcTest::heap()->CreateCode(
    809         desc,
    810         Code::ComputeFlags(Code::STUB),
    811         Handle<Code>())->ToObjectChecked();
    812     CHECK(code->IsCode());
    813     F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
    814     t.a = 2.147483647e9;       // 0x7fffffff -> 0x41DFFFFFFFC00000 as double.
    815     t.b_long_hi = 0x000000ff;  // 0xFF00FF00FF -> 0x426FE01FE01FE000 as double.
    816     t.b_long_lo = 0x00ff00ff;
    817     Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
    818     USE(dummy);
    819 
    820     CHECK_EQ(0x41DFFFFF, t.dbl_exp);
    821     CHECK_EQ(0xFFC00000, t.dbl_mant);
    822     CHECK_EQ(0, t.long_hi);
    823     CHECK_EQ(0x7fffffff, t.long_lo);
    824     // 0xFF00FF00FF -> 1.095233372415e12.
    825     CHECK_EQ(1.095233372415e12, t.b);
    826   }
    827 }
    828 
    829 
    830 TEST(MIPS11) {
    831   // Test LWL, LWR, SWL and SWR instructions.
    832   CcTest::InitializeVM();
    833   Isolate* isolate = CcTest::i_isolate();
    834   HandleScope scope(isolate);
    835 
    836   typedef struct {
    837     int32_t reg_init;
    838     int32_t mem_init;
    839     int32_t lwl_0;
    840     int32_t lwl_1;
    841     int32_t lwl_2;
    842     int32_t lwl_3;
    843     int32_t lwr_0;
    844     int32_t lwr_1;
    845     int32_t lwr_2;
    846     int32_t lwr_3;
    847     int32_t swl_0;
    848     int32_t swl_1;
    849     int32_t swl_2;
    850     int32_t swl_3;
    851     int32_t swr_0;
    852     int32_t swr_1;
    853     int32_t swr_2;
    854     int32_t swr_3;
    855   } T;
    856   T t;
    857 
    858   Assembler assm(isolate, NULL, 0);
    859 
    860   // Test all combinations of LWL and vAddr.
    861   __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
    862   __ lwl(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
    863   __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwl_0)) );
    864 
    865   __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
    866   __ lwl(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) );
    867   __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwl_1)) );
    868 
    869   __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
    870   __ lwl(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) );
    871   __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwl_2)) );
    872 
    873   __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
    874   __ lwl(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) );
    875   __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwl_3)) );
    876 
    877   // Test all combinations of LWR and vAddr.
    878   __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
    879   __ lwr(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
    880   __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwr_0)) );
    881 
    882   __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
    883   __ lwr(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) );
    884   __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwr_1)) );
    885 
    886   __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
    887   __ lwr(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) );
    888   __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwr_2)) );
    889 
    890   __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
    891   __ lwr(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) );
    892   __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwr_3)) );
    893 
    894   // Test all combinations of SWL and vAddr.
    895   __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
    896   __ sw(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) );
    897   __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
    898   __ swl(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) );
    899 
    900   __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) );
    901   __ sw(t1, MemOperand(a0, OFFSET_OF(T, swl_1)) );
    902   __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
    903   __ swl(t1, MemOperand(a0, OFFSET_OF(T, swl_1) + 1) );
    904 
    905   __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) );
    906   __ sw(t2, MemOperand(a0, OFFSET_OF(T, swl_2)) );
    907   __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
    908   __ swl(t2, MemOperand(a0, OFFSET_OF(T, swl_2) + 2) );
    909 
    910   __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) );
    911   __ sw(t3, MemOperand(a0, OFFSET_OF(T, swl_3)) );
    912   __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
    913   __ swl(t3, MemOperand(a0, OFFSET_OF(T, swl_3) + 3) );
    914 
    915   // Test all combinations of SWR and vAddr.
    916   __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
    917   __ sw(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) );
    918   __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
    919   __ swr(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) );
    920 
    921   __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) );
    922   __ sw(t1, MemOperand(a0, OFFSET_OF(T, swr_1)) );
    923   __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
    924   __ swr(t1, MemOperand(a0, OFFSET_OF(T, swr_1) + 1) );
    925 
    926   __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) );
    927   __ sw(t2, MemOperand(a0, OFFSET_OF(T, swr_2)) );
    928   __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
    929   __ swr(t2, MemOperand(a0, OFFSET_OF(T, swr_2) + 2) );
    930 
    931   __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) );
    932   __ sw(t3, MemOperand(a0, OFFSET_OF(T, swr_3)) );
    933   __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
    934   __ swr(t3, MemOperand(a0, OFFSET_OF(T, swr_3) + 3) );
    935 
    936   __ jr(ra);
    937   __ nop();
    938 
    939   CodeDesc desc;
    940   assm.GetCode(&desc);
    941   Object* code = CcTest::heap()->CreateCode(
    942       desc,
    943       Code::ComputeFlags(Code::STUB),
    944       Handle<Code>())->ToObjectChecked();
    945   CHECK(code->IsCode());
    946   F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
    947   t.reg_init = 0xaabbccdd;
    948   t.mem_init = 0x11223344;
    949 
    950   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
    951   USE(dummy);
    952 
    953   CHECK_EQ(0x44bbccdd, t.lwl_0);
    954   CHECK_EQ(0x3344ccdd, t.lwl_1);
    955   CHECK_EQ(0x223344dd, t.lwl_2);
    956   CHECK_EQ(0x11223344, t.lwl_3);
    957 
    958   CHECK_EQ(0x11223344, t.lwr_0);
    959   CHECK_EQ(0xaa112233, t.lwr_1);
    960   CHECK_EQ(0xaabb1122, t.lwr_2);
    961   CHECK_EQ(0xaabbcc11, t.lwr_3);
    962 
    963   CHECK_EQ(0x112233aa, t.swl_0);
    964   CHECK_EQ(0x1122aabb, t.swl_1);
    965   CHECK_EQ(0x11aabbcc, t.swl_2);
    966   CHECK_EQ(0xaabbccdd, t.swl_3);
    967 
    968   CHECK_EQ(0xaabbccdd, t.swr_0);
    969   CHECK_EQ(0xbbccdd44, t.swr_1);
    970   CHECK_EQ(0xccdd3344, t.swr_2);
    971   CHECK_EQ(0xdd223344, t.swr_3);
    972 }
    973 
    974 
    975 TEST(MIPS12) {
    976   CcTest::InitializeVM();
    977   Isolate* isolate = CcTest::i_isolate();
    978   HandleScope scope(isolate);
    979 
    980   typedef struct {
    981       int32_t  x;
    982       int32_t  y;
    983       int32_t  y1;
    984       int32_t  y2;
    985       int32_t  y3;
    986       int32_t  y4;
    987   } T;
    988   T t;
    989 
    990   MacroAssembler assm(isolate, NULL, 0);
    991 
    992   __ mov(t6, fp);  // Save frame pointer.
    993   __ mov(fp, a0);  // Access struct T by fp.
    994   __ lw(t0, MemOperand(a0, OFFSET_OF(T, y)) );
    995   __ lw(t3, MemOperand(a0, OFFSET_OF(T, y4)) );
    996 
    997   __ addu(t1, t0, t3);
    998   __ subu(t4, t0, t3);
    999   __ nop();
   1000   __ push(t0);  // These instructions disappear after opt.
   1001   __ Pop();
   1002   __ addu(t0, t0, t0);
   1003   __ nop();
   1004   __ Pop();     // These instructions disappear after opt.
   1005   __ push(t3);
   1006   __ nop();
   1007   __ push(t3);  // These instructions disappear after opt.
   1008   __ pop(t3);
   1009   __ nop();
   1010   __ push(t3);
   1011   __ pop(t4);
   1012   __ nop();
   1013   __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
   1014   __ lw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
   1015   __ nop();
   1016   __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
   1017   __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
   1018   __ nop();
   1019   __ push(t1);
   1020   __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
   1021   __ pop(t1);
   1022   __ nop();
   1023   __ push(t1);
   1024   __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
   1025   __ pop(t1);
   1026   __ nop();
   1027   __ push(t1);
   1028   __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
   1029   __ pop(t2);
   1030   __ nop();
   1031   __ push(t2);
   1032   __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
   1033   __ pop(t1);
   1034   __ nop();
   1035   __ push(t1);
   1036   __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
   1037   __ pop(t3);
   1038   __ nop();
   1039 
   1040   __ mov(fp, t6);
   1041   __ jr(ra);
   1042   __ nop();
   1043 
   1044   CodeDesc desc;
   1045   assm.GetCode(&desc);
   1046   Object* code = CcTest::heap()->CreateCode(
   1047       desc,
   1048       Code::ComputeFlags(Code::STUB),
   1049       Handle<Code>())->ToObjectChecked();
   1050   CHECK(code->IsCode());
   1051   F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
   1052   t.x = 1;
   1053   t.y = 2;
   1054   t.y1 = 3;
   1055   t.y2 = 4;
   1056   t.y3 = 0XBABA;
   1057   t.y4 = 0xDEDA;
   1058 
   1059   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
   1060   USE(dummy);
   1061 
   1062   CHECK_EQ(3, t.y1);
   1063 }
   1064 
   1065 
   1066 TEST(MIPS13) {
   1067   // Test Cvt_d_uw and Trunc_uw_d macros.
   1068   CcTest::InitializeVM();
   1069   Isolate* isolate = CcTest::i_isolate();
   1070   HandleScope scope(isolate);
   1071 
   1072   typedef struct {
   1073     double cvt_big_out;
   1074     double cvt_small_out;
   1075     uint32_t trunc_big_out;
   1076     uint32_t trunc_small_out;
   1077     uint32_t cvt_big_in;
   1078     uint32_t cvt_small_in;
   1079   } T;
   1080   T t;
   1081 
   1082   MacroAssembler assm(isolate, NULL, 0);
   1083 
   1084   __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_small_in)));
   1085   __ Cvt_d_uw(f10, t0, f22);
   1086   __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, cvt_small_out)));
   1087 
   1088   __ Trunc_uw_d(f10, f10, f22);
   1089   __ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out)));
   1090 
   1091   __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_big_in)));
   1092   __ Cvt_d_uw(f8, t0, f22);
   1093   __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, cvt_big_out)));
   1094 
   1095   __ Trunc_uw_d(f8, f8, f22);
   1096   __ swc1(f8, MemOperand(a0, OFFSET_OF(T, trunc_big_out)));
   1097 
   1098   __ jr(ra);
   1099   __ nop();
   1100 
   1101   CodeDesc desc;
   1102   assm.GetCode(&desc);
   1103   Object* code = CcTest::heap()->CreateCode(
   1104       desc,
   1105       Code::ComputeFlags(Code::STUB),
   1106       Handle<Code>())->ToObjectChecked();
   1107   CHECK(code->IsCode());
   1108   F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
   1109 
   1110   t.cvt_big_in = 0xFFFFFFFF;
   1111   t.cvt_small_in  = 333;
   1112 
   1113   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
   1114   USE(dummy);
   1115 
   1116   CHECK_EQ(t.cvt_big_out, static_cast<double>(t.cvt_big_in));
   1117   CHECK_EQ(t.cvt_small_out, static_cast<double>(t.cvt_small_in));
   1118 
   1119   CHECK_EQ(static_cast<int>(t.trunc_big_out), static_cast<int>(t.cvt_big_in));
   1120   CHECK_EQ(static_cast<int>(t.trunc_small_out),
   1121            static_cast<int>(t.cvt_small_in));
   1122 }
   1123 
   1124 
   1125 TEST(MIPS14) {
   1126   // Test round, floor, ceil, trunc, cvt.
   1127   CcTest::InitializeVM();
   1128   Isolate* isolate = CcTest::i_isolate();
   1129   HandleScope scope(isolate);
   1130 
   1131 #define ROUND_STRUCT_ELEMENT(x) \
   1132   int32_t x##_up_out; \
   1133   int32_t x##_down_out; \
   1134   int32_t neg_##x##_up_out; \
   1135   int32_t neg_##x##_down_out; \
   1136   uint32_t x##_err1_out; \
   1137   uint32_t x##_err2_out; \
   1138   uint32_t x##_err3_out; \
   1139   uint32_t x##_err4_out; \
   1140   int32_t x##_invalid_result;
   1141 
   1142   typedef struct {
   1143     double round_up_in;
   1144     double round_down_in;
   1145     double neg_round_up_in;
   1146     double neg_round_down_in;
   1147     double err1_in;
   1148     double err2_in;
   1149     double err3_in;
   1150     double err4_in;
   1151 
   1152     ROUND_STRUCT_ELEMENT(round)
   1153     ROUND_STRUCT_ELEMENT(floor)
   1154     ROUND_STRUCT_ELEMENT(ceil)
   1155     ROUND_STRUCT_ELEMENT(trunc)
   1156     ROUND_STRUCT_ELEMENT(cvt)
   1157   } T;
   1158   T t;
   1159 
   1160 #undef ROUND_STRUCT_ELEMENT
   1161 
   1162   MacroAssembler assm(isolate, NULL, 0);
   1163 
   1164   // Save FCSR.
   1165   __ cfc1(a1, FCSR);
   1166   // Disable FPU exceptions.
   1167   __ ctc1(zero_reg, FCSR);
   1168 #define RUN_ROUND_TEST(x) \
   1169   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_up_in))); \
   1170   __ x##_w_d(f0, f0); \
   1171   __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_up_out))); \
   1172   \
   1173   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_down_in))); \
   1174   __ x##_w_d(f0, f0); \
   1175   __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_down_out))); \
   1176   \
   1177   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_up_in))); \
   1178   __ x##_w_d(f0, f0); \
   1179   __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_up_out))); \
   1180   \
   1181   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_down_in))); \
   1182   __ x##_w_d(f0, f0); \
   1183   __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_down_out))); \
   1184   \
   1185   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err1_in))); \
   1186   __ ctc1(zero_reg, FCSR); \
   1187   __ x##_w_d(f0, f0); \
   1188   __ cfc1(a2, FCSR); \
   1189   __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err1_out))); \
   1190   \
   1191   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err2_in))); \
   1192   __ ctc1(zero_reg, FCSR); \
   1193   __ x##_w_d(f0, f0); \
   1194   __ cfc1(a2, FCSR); \
   1195   __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err2_out))); \
   1196   \
   1197   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err3_in))); \
   1198   __ ctc1(zero_reg, FCSR); \
   1199   __ x##_w_d(f0, f0); \
   1200   __ cfc1(a2, FCSR); \
   1201   __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err3_out))); \
   1202   \
   1203   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err4_in))); \
   1204   __ ctc1(zero_reg, FCSR); \
   1205   __ x##_w_d(f0, f0); \
   1206   __ cfc1(a2, FCSR); \
   1207   __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err4_out))); \
   1208   __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_invalid_result)));
   1209 
   1210   RUN_ROUND_TEST(round)
   1211   RUN_ROUND_TEST(floor)
   1212   RUN_ROUND_TEST(ceil)
   1213   RUN_ROUND_TEST(trunc)
   1214   RUN_ROUND_TEST(cvt)
   1215 
   1216   // Restore FCSR.
   1217   __ ctc1(a1, FCSR);
   1218 
   1219   __ jr(ra);
   1220   __ nop();
   1221 
   1222   CodeDesc desc;
   1223   assm.GetCode(&desc);
   1224   Object* code = CcTest::heap()->CreateCode(
   1225       desc,
   1226       Code::ComputeFlags(Code::STUB),
   1227       Handle<Code>())->ToObjectChecked();
   1228   CHECK(code->IsCode());
   1229   F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
   1230 
   1231   t.round_up_in = 123.51;
   1232   t.round_down_in = 123.49;
   1233   t.neg_round_up_in = -123.5;
   1234   t.neg_round_down_in = -123.49;
   1235   t.err1_in = 123.51;
   1236   t.err2_in = 1;
   1237   t.err3_in = static_cast<double>(1) + 0xFFFFFFFF;
   1238   t.err4_in = NAN;
   1239 
   1240   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
   1241   USE(dummy);
   1242 
   1243 #define GET_FPU_ERR(x) (static_cast<int>(x & kFCSRFlagMask))
   1244 #define CHECK_ROUND_RESULT(type) \
   1245   CHECK(GET_FPU_ERR(t.type##_err1_out) & kFCSRInexactFlagMask); \
   1246   CHECK_EQ(0, GET_FPU_ERR(t.type##_err2_out)); \
   1247   CHECK(GET_FPU_ERR(t.type##_err3_out) & kFCSRInvalidOpFlagMask); \
   1248   CHECK(GET_FPU_ERR(t.type##_err4_out) & kFCSRInvalidOpFlagMask); \
   1249   CHECK_EQ(kFPUInvalidResult, t.type##_invalid_result);
   1250 
   1251   CHECK_ROUND_RESULT(round);
   1252   CHECK_ROUND_RESULT(floor);
   1253   CHECK_ROUND_RESULT(ceil);
   1254   CHECK_ROUND_RESULT(cvt);
   1255 }
   1256 
   1257 
   1258 TEST(MIPS15) {
   1259   // Test chaining of label usages within instructions (issue 1644).
   1260   CcTest::InitializeVM();
   1261   Isolate* isolate = CcTest::i_isolate();
   1262   HandleScope scope(isolate);
   1263   Assembler assm(isolate, NULL, 0);
   1264 
   1265   Label target;
   1266   __ beq(v0, v1, &target);
   1267   __ nop();
   1268   __ bne(v0, v1, &target);
   1269   __ nop();
   1270   __ bind(&target);
   1271   __ nop();
   1272 }
   1273 
   1274 #undef __
   1275