blob: ecb42e2f7b9f376fdfd3c1a9e3f08ce94c642148 [file] [log] [blame]
ager@chromium.org5c838252010-02-19 08:53:10 +00001// 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
38using namespace v8::internal;
39
40
41// Define these function prototypes to match JSEntryFunction in execution.cc.
42typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
43typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
44typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4);
45
46
47static v8::Persistent<v8::Context> env;
48
49
ager@chromium.org5c838252010-02-19 08:53:10 +000050static void InitializeVM() {
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000051 // Disable compilation of natives.
52 FLAG_disable_native_files = true;
ager@chromium.org5c838252010-02-19 08:53:10 +000053
ager@chromium.org5c838252010-02-19 08:53:10 +000054 if (env.IsEmpty()) {
55 env = v8::Context::New();
56 }
57}
58
59
60#define __ assm.
61
62TEST(MIPS0) {
63 InitializeVM();
64 v8::HandleScope scope;
65
66 MacroAssembler assm(NULL, 0);
67
68 // Addition.
69 __ addu(v0, a0, a1);
70 __ jr(ra);
71 __ nop();
72
73 CodeDesc desc;
74 assm.GetCode(&desc);
75 Object* code = Heap::CreateCode(desc,
76 NULL,
77 Code::ComputeFlags(Code::STUB),
78 Handle<Object>(Heap::undefined_value()));
79 CHECK(code->IsCode());
80#ifdef DEBUG
81 Code::cast(code)->Print();
82#endif
83 F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
84 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
85 ::printf("f() = %d\n", res);
86 CHECK_EQ(0xabc, res);
87}
88
89
90TEST(MIPS1) {
91 InitializeVM();
92 v8::HandleScope scope;
93
94 MacroAssembler assm(NULL, 0);
95 Label L, C;
96
97 __ mov(a1, a0);
98 __ li(v0, 0);
99 __ b(&C);
100 __ nop();
101
102 __ bind(&L);
103 __ add(v0, v0, a1);
104 __ addiu(a1, a1, -1);
105
106 __ bind(&C);
107 __ xori(v1, a1, 0);
ager@chromium.org5b2fbee2010-09-08 06:38:15 +0000108 __ Branch(ne, &L, v1, Operand(0, RelocInfo::NONE));
ager@chromium.org5c838252010-02-19 08:53:10 +0000109 __ nop();
110
111 __ jr(ra);
112 __ nop();
113
114 CodeDesc desc;
115 assm.GetCode(&desc);
116 Object* code = Heap::CreateCode(desc,
117 NULL,
118 Code::ComputeFlags(Code::STUB),
119 Handle<Object>(Heap::undefined_value()));
120 CHECK(code->IsCode());
121#ifdef DEBUG
122 Code::cast(code)->Print();
123#endif
124 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
125 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 50, 0, 0, 0, 0));
126 ::printf("f() = %d\n", res);
127 CHECK_EQ(1275, res);
128}
129
130
131TEST(MIPS2) {
132 InitializeVM();
133 v8::HandleScope scope;
134
135 MacroAssembler assm(NULL, 0);
136
137 Label exit, error;
138
139 // ----- Test all instructions.
140
141 // Test lui, ori, and addiu, used in the li pseudo-instruction.
142 // This way we can then safely load registers with chosen values.
143
144 __ ori(t0, zero_reg, 0);
145 __ lui(t0, 0x1234);
146 __ ori(t0, t0, 0);
147 __ ori(t0, t0, 0x0f0f);
148 __ ori(t0, t0, 0xf0f0);
149 __ addiu(t1, t0, 1);
150 __ addiu(t2, t1, -0x10);
151
152 // Load values in temporary registers.
153 __ li(t0, 0x00000004);
154 __ li(t1, 0x00001234);
155 __ li(t2, 0x12345678);
156 __ li(t3, 0x7fffffff);
157 __ li(t4, 0xfffffffc);
158 __ li(t5, 0xffffedcc);
159 __ li(t6, 0xedcba988);
160 __ li(t7, 0x80000000);
161
162 // SPECIAL class.
163 __ srl(v0, t2, 8); // 0x00123456
164 __ sll(v0, v0, 11); // 0x91a2b000
165 __ sra(v0, v0, 3); // 0xf2345600
166 __ srav(v0, v0, t0); // 0xff234560
167 __ sllv(v0, v0, t0); // 0xf2345600
168 __ srlv(v0, v0, t0); // 0x0f234560
169 __ Branch(ne, &error, v0, Operand(0x0f234560));
170 __ nop();
171
172 __ add(v0, t0, t1); // 0x00001238
173 __ sub(v0, v0, t0); // 0x00001234
174 __ Branch(ne, &error, v0, Operand(0x00001234));
175 __ nop();
176 __ addu(v1, t3, t0);
177 __ Branch(ne, &error, v1, Operand(0x80000003));
178 __ nop();
179 __ subu(v1, t7, t0); // 0x7ffffffc
180 __ Branch(ne, &error, v1, Operand(0x7ffffffc));
181 __ nop();
182
183 __ and_(v0, t1, t2); // 0x00001230
184 __ or_(v0, v0, t1); // 0x00001234
185 __ xor_(v0, v0, t2); // 0x1234444c
186 __ nor(v0, v0, t2); // 0xedcba987
187 __ Branch(ne, &error, v0, Operand(0xedcba983));
188 __ nop();
189
190 __ slt(v0, t7, t3);
191 __ Branch(ne, &error, v0, Operand(0x1));
192 __ nop();
193 __ sltu(v0, t7, t3);
194 __ Branch(ne, &error, v0, Operand(0x0));
195 __ nop();
196 // End of SPECIAL class.
197
198 __ addi(v0, zero_reg, 0x7421); // 0x00007421
199 __ addi(v0, v0, -0x1); // 0x00007420
200 __ addiu(v0, v0, -0x20); // 0x00007400
201 __ Branch(ne, &error, v0, Operand(0x00007400));
202 __ nop();
203 __ addiu(v1, t3, 0x1); // 0x80000000
204 __ Branch(ne, &error, v1, Operand(0x80000000));
205 __ nop();
206
207 __ slti(v0, t1, 0x00002000); // 0x1
208 __ slti(v0, v0, 0xffff8000); // 0x0
209 __ Branch(ne, &error, v0, Operand(0x0));
210 __ nop();
211 __ sltiu(v0, t1, 0x00002000); // 0x1
212 __ sltiu(v0, v0, 0x00008000); // 0x1
213 __ Branch(ne, &error, v0, Operand(0x1));
214 __ nop();
215
216 __ andi(v0, t1, 0xf0f0); // 0x00001030
217 __ ori(v0, v0, 0x8a00); // 0x00009a30
218 __ xori(v0, v0, 0x83cc); // 0x000019fc
219 __ Branch(ne, &error, v0, Operand(0x000019fc));
220 __ nop();
221 __ lui(v1, 0x8123); // 0x81230000
222 __ Branch(ne, &error, v1, Operand(0x81230000));
223 __ nop();
224
225 // Everything was correctly executed. Load the expected result.
226 __ li(v0, 0x31415926);
227 __ b(&exit);
228 __ nop();
229
230 __ bind(&error);
231 // Got an error. Return a wrong result.
232
233 __ bind(&exit);
234 __ jr(ra);
235 __ nop();
236
237 CodeDesc desc;
238 assm.GetCode(&desc);
239 Object* code = Heap::CreateCode(desc,
240 NULL,
241 Code::ComputeFlags(Code::STUB),
242 Handle<Object>(Heap::undefined_value()));
243 CHECK(code->IsCode());
244#ifdef DEBUG
245 Code::cast(code)->Print();
246#endif
247 F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
248 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
249 ::printf("f() = %d\n", res);
250 CHECK_EQ(0x31415926, res);
251}
252
253#undef __