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 "arm/simulator-arm.h"
     33 #include "arm/assembler-arm-inl.h"
     34 #include "cctest.h"
     35 
     36 using namespace v8::internal;
     37 
     38 
     39 // Define these function prototypes to match JSEntryFunction in execution.cc.
     40 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
     41 typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
     42 typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4);
     43 
     44 
     45 static v8::Persistent<v8::Context> env;
     46 
     47 
     48 // The test framework does not accept flags on the command line, so we set them
     49 static void InitializeVM() {
     50   // enable generation of comments
     51   FLAG_debug_code = true;
     52 
     53   if (env.IsEmpty()) {
     54     env = v8::Context::New();
     55   }
     56 }
     57 
     58 
     59 #define __ assm.
     60 
     61 TEST(0) {
     62   InitializeVM();
     63   v8::HandleScope scope;
     64 
     65   Assembler assm(NULL, 0);
     66 
     67   __ add(r0, r0, Operand(r1));
     68   __ mov(pc, Operand(lr));
     69 
     70   CodeDesc desc;
     71   assm.GetCode(&desc);
     72   Object* code = Heap::CreateCode(desc,
     73                                   NULL,
     74                                   Code::ComputeFlags(Code::STUB),
     75                                   Handle<Object>(Heap::undefined_value()));
     76   CHECK(code->IsCode());
     77 #ifdef DEBUG
     78   Code::cast(code)->Print();
     79 #endif
     80   F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
     81   int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 3, 4, 0, 0, 0));
     82   ::printf("f() = %d\n", res);
     83   CHECK_EQ(7, res);
     84 }
     85 
     86 
     87 TEST(1) {
     88   InitializeVM();
     89   v8::HandleScope scope;
     90 
     91   Assembler assm(NULL, 0);
     92   Label L, C;
     93 
     94   __ mov(r1, Operand(r0));
     95   __ mov(r0, Operand(0));
     96   __ b(&C);
     97 
     98   __ bind(&L);
     99   __ add(r0, r0, Operand(r1));
    100   __ sub(r1, r1, Operand(1));
    101 
    102   __ bind(&C);
    103   __ teq(r1, Operand(0));
    104   __ b(ne, &L);
    105   __ mov(pc, Operand(lr));
    106 
    107   CodeDesc desc;
    108   assm.GetCode(&desc);
    109   Object* code = Heap::CreateCode(desc,
    110                                   NULL,
    111                                   Code::ComputeFlags(Code::STUB),
    112                                   Handle<Object>(Heap::undefined_value()));
    113   CHECK(code->IsCode());
    114 #ifdef DEBUG
    115   Code::cast(code)->Print();
    116 #endif
    117   F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
    118   int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 100, 0, 0, 0, 0));
    119   ::printf("f() = %d\n", res);
    120   CHECK_EQ(5050, res);
    121 }
    122 
    123 
    124 TEST(2) {
    125   InitializeVM();
    126   v8::HandleScope scope;
    127 
    128   Assembler assm(NULL, 0);
    129   Label L, C;
    130 
    131   __ mov(r1, Operand(r0));
    132   __ mov(r0, Operand(1));
    133   __ b(&C);
    134 
    135   __ bind(&L);
    136   __ mul(r0, r1, r0);
    137   __ sub(r1, r1, Operand(1));
    138 
    139   __ bind(&C);
    140   __ teq(r1, Operand(0));
    141   __ b(ne, &L);
    142   __ mov(pc, Operand(lr));
    143 
    144   // some relocated stuff here, not executed
    145   __ RecordComment("dead code, just testing relocations");
    146   __ mov(r0, Operand(Factory::true_value()));
    147   __ RecordComment("dead code, just testing immediate operands");
    148   __ mov(r0, Operand(-1));
    149   __ mov(r0, Operand(0xFF000000));
    150   __ mov(r0, Operand(0xF0F0F0F0));
    151   __ mov(r0, Operand(0xFFF0FFFF));
    152 
    153   CodeDesc desc;
    154   assm.GetCode(&desc);
    155   Object* code = Heap::CreateCode(desc,
    156                                   NULL,
    157                                   Code::ComputeFlags(Code::STUB),
    158                                   Handle<Object>(Heap::undefined_value()));
    159   CHECK(code->IsCode());
    160 #ifdef DEBUG
    161   Code::cast(code)->Print();
    162 #endif
    163   F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
    164   int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 10, 0, 0, 0, 0));
    165   ::printf("f() = %d\n", res);
    166   CHECK_EQ(3628800, res);
    167 }
    168 
    169 
    170 TEST(3) {
    171   InitializeVM();
    172   v8::HandleScope scope;
    173 
    174   typedef struct {
    175     int i;
    176     char c;
    177     int16_t s;
    178   } T;
    179   T t;
    180 
    181   Assembler assm(NULL, 0);
    182   Label L, C;
    183 
    184   __ mov(ip, Operand(sp));
    185   __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
    186   __ sub(fp, ip, Operand(4));
    187   __ mov(r4, Operand(r0));
    188   __ ldr(r0, MemOperand(r4, OFFSET_OF(T, i)));
    189   __ mov(r2, Operand(r0, ASR, 1));
    190   __ str(r2, MemOperand(r4, OFFSET_OF(T, i)));
    191   __ ldrsb(r2, MemOperand(r4, OFFSET_OF(T, c)));
    192   __ add(r0, r2, Operand(r0));
    193   __ mov(r2, Operand(r2, LSL, 2));
    194   __ strb(r2, MemOperand(r4, OFFSET_OF(T, c)));
    195   __ ldrsh(r2, MemOperand(r4, OFFSET_OF(T, s)));
    196   __ add(r0, r2, Operand(r0));
    197   __ mov(r2, Operand(r2, ASR, 3));
    198   __ strh(r2, MemOperand(r4, OFFSET_OF(T, s)));
    199   __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
    200 
    201   CodeDesc desc;
    202   assm.GetCode(&desc);
    203   Object* code = Heap::CreateCode(desc,
    204                                   NULL,
    205                                   Code::ComputeFlags(Code::STUB),
    206                                   Handle<Object>(Heap::undefined_value()));
    207   CHECK(code->IsCode());
    208 #ifdef DEBUG
    209   Code::cast(code)->Print();
    210 #endif
    211   F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
    212   t.i = 100000;
    213   t.c = 10;
    214   t.s = 1000;
    215   int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0));
    216   ::printf("f() = %d\n", res);
    217   CHECK_EQ(101010, res);
    218   CHECK_EQ(100000/2, t.i);
    219   CHECK_EQ(10*4, t.c);
    220   CHECK_EQ(1000/8, t.s);
    221 }
    222 
    223 
    224 TEST(4) {
    225   // Test the VFP floating point instructions.
    226   InitializeVM();
    227   v8::HandleScope scope;
    228 
    229   typedef struct {
    230     double a;
    231     double b;
    232     double c;
    233   } T;
    234   T t;
    235 
    236   // Create a function that accepts &t, and loads, manipulates, and stores
    237   // the doubles t.a, t.b, and t.c.
    238   Assembler assm(NULL, 0);
    239   Label L, C;
    240 
    241 
    242   if (CpuFeatures::IsSupported(VFP3)) {
    243     CpuFeatures::Scope scope(VFP3);
    244 
    245     __ mov(ip, Operand(sp));
    246     __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
    247     __ sub(fp, ip, Operand(4));
    248 
    249     __ mov(r4, Operand(r0));
    250     __ vldr(d6, r4, OFFSET_OF(T, a));
    251     __ vldr(d7, r4, OFFSET_OF(T, b));
    252     __ vadd(d5, d6, d7);
    253     __ vstr(d5, r4, OFFSET_OF(T, c));
    254 
    255     __ vmov(r2, r3, d5);
    256     __ vmov(d4, r2, r3);
    257     __ vstr(d4, r4, OFFSET_OF(T, b));
    258 
    259     __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
    260 
    261     CodeDesc desc;
    262     assm.GetCode(&desc);
    263     Object* code = Heap::CreateCode(desc,
    264                                     NULL,
    265                                     Code::ComputeFlags(Code::STUB),
    266                                     Handle<Object>(Heap::undefined_value()));
    267     CHECK(code->IsCode());
    268 #ifdef DEBUG
    269     Code::cast(code)->Print();
    270 #endif
    271     F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
    272     t.a = 1.5;
    273     t.b = 2.75;
    274     t.c = 17.17;
    275     Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
    276     USE(dummy);
    277     CHECK_EQ(4.25, t.c);
    278     CHECK_EQ(4.25, t.b);
    279     CHECK_EQ(1.5, t.a);
    280   }
    281 }
    282 
    283 #undef __
    284