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 // The test framework does not accept flags on the command line, so we set them.
     51 static void InitializeVM() {
     52   // Disable compilation of natives by specifying an empty natives file.
     53   FLAG_natives_file = "";
     54 
     55   // Enable generation of comments.
     56   FLAG_debug_code = true;
     57 
     58   if (env.IsEmpty()) {
     59     env = v8::Context::New();
     60   }
     61 }
     62 
     63 
     64 #define __ assm.
     65 
     66 TEST(MIPS0) {
     67   InitializeVM();
     68   v8::HandleScope scope;
     69 
     70   MacroAssembler assm(NULL, 0);
     71 
     72   // Addition.
     73   __ addu(v0, a0, a1);
     74   __ jr(ra);
     75   __ nop();
     76 
     77   CodeDesc desc;
     78   assm.GetCode(&desc);
     79   Object* code = Heap::CreateCode(desc,
     80                                   NULL,
     81                                   Code::ComputeFlags(Code::STUB),
     82                                   Handle<Object>(Heap::undefined_value()));
     83   CHECK(code->IsCode());
     84 #ifdef DEBUG
     85   Code::cast(code)->Print();
     86 #endif
     87   F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
     88   int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
     89   ::printf("f() = %d\n", res);
     90   CHECK_EQ(0xabc, res);
     91 }
     92 
     93 
     94 TEST(MIPS1) {
     95   InitializeVM();
     96   v8::HandleScope scope;
     97 
     98   MacroAssembler assm(NULL, 0);
     99   Label L, C;
    100 
    101   __ mov(a1, a0);
    102   __ li(v0, 0);
    103   __ b(&C);
    104   __ nop();
    105 
    106   __ bind(&L);
    107   __ add(v0, v0, a1);
    108   __ addiu(a1, a1, -1);
    109 
    110   __ bind(&C);
    111   __ xori(v1, a1, 0);
    112   __ Branch(ne, &L, v1, Operand(0));
    113   __ nop();
    114 
    115   __ jr(ra);
    116   __ nop();
    117 
    118   CodeDesc desc;
    119   assm.GetCode(&desc);
    120   Object* code = Heap::CreateCode(desc,
    121                                   NULL,
    122                                   Code::ComputeFlags(Code::STUB),
    123                                   Handle<Object>(Heap::undefined_value()));
    124   CHECK(code->IsCode());
    125 #ifdef DEBUG
    126   Code::cast(code)->Print();
    127 #endif
    128   F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
    129   int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 50, 0, 0, 0, 0));
    130   ::printf("f() = %d\n", res);
    131   CHECK_EQ(1275, res);
    132 }
    133 
    134 
    135 TEST(MIPS2) {
    136   InitializeVM();
    137   v8::HandleScope scope;
    138 
    139   MacroAssembler assm(NULL, 0);
    140 
    141   Label exit, error;
    142 
    143   // ----- Test all instructions.
    144 
    145   // Test lui, ori, and addiu, used in the li pseudo-instruction.
    146   // This way we can then safely load registers with chosen values.
    147 
    148   __ ori(t0, zero_reg, 0);
    149   __ lui(t0, 0x1234);
    150   __ ori(t0, t0, 0);
    151   __ ori(t0, t0, 0x0f0f);
    152   __ ori(t0, t0, 0xf0f0);
    153   __ addiu(t1, t0, 1);
    154   __ addiu(t2, t1, -0x10);
    155 
    156   // Load values in temporary registers.
    157   __ li(t0, 0x00000004);
    158   __ li(t1, 0x00001234);
    159   __ li(t2, 0x12345678);
    160   __ li(t3, 0x7fffffff);
    161   __ li(t4, 0xfffffffc);
    162   __ li(t5, 0xffffedcc);
    163   __ li(t6, 0xedcba988);
    164   __ li(t7, 0x80000000);
    165 
    166   // SPECIAL class.
    167   __ srl(v0, t2, 8);    // 0x00123456
    168   __ sll(v0, v0, 11);   // 0x91a2b000
    169   __ sra(v0, v0, 3);    // 0xf2345600
    170   __ srav(v0, v0, t0);  // 0xff234560
    171   __ sllv(v0, v0, t0);  // 0xf2345600
    172   __ srlv(v0, v0, t0);  // 0x0f234560
    173   __ Branch(ne, &error, v0, Operand(0x0f234560));
    174   __ nop();
    175 
    176   __ add(v0, t0, t1);   // 0x00001238
    177   __ sub(v0, v0, t0);   // 0x00001234
    178   __ Branch(ne, &error, v0, Operand(0x00001234));
    179   __ nop();
    180   __ addu(v1, t3, t0);
    181   __ Branch(ne, &error, v1, Operand(0x80000003));
    182   __ nop();
    183   __ subu(v1, t7, t0);  // 0x7ffffffc
    184   __ Branch(ne, &error, v1, Operand(0x7ffffffc));
    185   __ nop();
    186 
    187   __ and_(v0, t1, t2);  // 0x00001230
    188   __ or_(v0, v0, t1);   // 0x00001234
    189   __ xor_(v0, v0, t2);  // 0x1234444c
    190   __ nor(v0, v0, t2);   // 0xedcba987
    191   __ Branch(ne, &error, v0, Operand(0xedcba983));
    192   __ nop();
    193 
    194   __ slt(v0, t7, t3);
    195   __ Branch(ne, &error, v0, Operand(0x1));
    196   __ nop();
    197   __ sltu(v0, t7, t3);
    198   __ Branch(ne, &error, v0, Operand(0x0));
    199   __ nop();
    200   // End of SPECIAL class.
    201 
    202   __ addi(v0, zero_reg, 0x7421);  // 0x00007421
    203   __ addi(v0, v0, -0x1);  // 0x00007420
    204   __ addiu(v0, v0, -0x20);  // 0x00007400
    205   __ Branch(ne, &error, v0, Operand(0x00007400));
    206   __ nop();
    207   __ addiu(v1, t3, 0x1);  // 0x80000000
    208   __ Branch(ne, &error, v1, Operand(0x80000000));
    209   __ nop();
    210 
    211   __ slti(v0, t1, 0x00002000);  // 0x1
    212   __ slti(v0, v0, 0xffff8000);  // 0x0
    213   __ Branch(ne, &error, v0, Operand(0x0));
    214   __ nop();
    215   __ sltiu(v0, t1, 0x00002000);  // 0x1
    216   __ sltiu(v0, v0, 0x00008000);  // 0x1
    217   __ Branch(ne, &error, v0, Operand(0x1));
    218   __ nop();
    219 
    220   __ andi(v0, t1, 0xf0f0);  // 0x00001030
    221   __ ori(v0, v0, 0x8a00);  // 0x00009a30
    222   __ xori(v0, v0, 0x83cc);  // 0x000019fc
    223   __ Branch(ne, &error, v0, Operand(0x000019fc));
    224   __ nop();
    225   __ lui(v1, 0x8123);  // 0x81230000
    226   __ Branch(ne, &error, v1, Operand(0x81230000));
    227   __ nop();
    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 
    237   __ bind(&exit);
    238   __ jr(ra);
    239   __ nop();
    240 
    241   CodeDesc desc;
    242   assm.GetCode(&desc);
    243   Object* code = Heap::CreateCode(desc,
    244                                   NULL,
    245                                   Code::ComputeFlags(Code::STUB),
    246                                   Handle<Object>(Heap::undefined_value()));
    247   CHECK(code->IsCode());
    248 #ifdef DEBUG
    249   Code::cast(code)->Print();
    250 #endif
    251   F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
    252   int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
    253   ::printf("f() = %d\n", res);
    254   CHECK_EQ(0x31415926, res);
    255 }
    256 
    257 #undef __
    258