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