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