• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
InitializeVM()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 
TEST(MIPS0)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 
TEST(MIPS1)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 
TEST(MIPS2)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