blob: 0a2310e3e80041f000ea0c35e71c0cd5c016a7a0 [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
50// The test framework does not accept flags on the command line, so we set them.
51static void InitializeVM() {
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000052 // Disable compilation of natives.
53 FLAG_disable_native_files = true;
ager@chromium.org5c838252010-02-19 08:53:10 +000054
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
66TEST(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
94TEST(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
135TEST(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 __