blob: 9ad7c76f11299c7ec2722e5c2113de71b727e4c0 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2006-2008 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 <stdlib.h>
29
30#include "v8.h"
31
32#include "disassembler.h"
33#include "factory.h"
34#include "macro-assembler.h"
35#include "platform.h"
36#include "serialize.h"
37#include "cctest.h"
38
39using namespace v8::internal;
40
41
42typedef int (*F0)();
43typedef int (*F1)(int x);
44typedef int (*F2)(int x, int y);
45
46
47static v8::Persistent<v8::Context> env;
48
49
50static void InitializeVM() {
51 if (env.IsEmpty()) {
52 env = v8::Context::New();
53 }
54}
55
56
57#define __ assm.
58
59TEST(AssemblerIa320) {
60 InitializeVM();
61 v8::HandleScope scope;
62
63 v8::internal::byte buffer[256];
64 Assembler assm(buffer, sizeof buffer);
65
66 __ mov(eax, Operand(esp, 4));
67 __ add(eax, Operand(esp, 8));
68 __ ret(0);
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 = f(3, 4);
82 ::printf("f() = %d\n", res);
83 CHECK_EQ(7, res);
84}
85
86
87TEST(AssemblerIa321) {
88 InitializeVM();
89 v8::HandleScope scope;
90
91 v8::internal::byte buffer[256];
92 Assembler assm(buffer, sizeof buffer);
93 Label L, C;
94
95 __ mov(edx, Operand(esp, 4));
96 __ xor_(eax, Operand(eax)); // clear eax
97 __ jmp(&C);
98
99 __ bind(&L);
100 __ add(eax, Operand(edx));
101 __ sub(Operand(edx), Immediate(1));
102
103 __ bind(&C);
104 __ test(edx, Operand(edx));
105 __ j(not_zero, &L, taken);
106 __ ret(0);
107
108 CodeDesc desc;
109 assm.GetCode(&desc);
110 Object* code = Heap::CreateCode(desc,
111 NULL,
112 Code::ComputeFlags(Code::STUB),
113 Handle<Object>(Heap::undefined_value()));
114 CHECK(code->IsCode());
115#ifdef DEBUG
116 Code::cast(code)->Print();
117#endif
118 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
119 int res = f(100);
120 ::printf("f() = %d\n", res);
121 CHECK_EQ(5050, res);
122}
123
124
125TEST(AssemblerIa322) {
126 InitializeVM();
127 v8::HandleScope scope;
128
129 v8::internal::byte buffer[256];
130 Assembler assm(buffer, sizeof buffer);
131 Label L, C;
132
133 __ mov(edx, Operand(esp, 4));
134 __ mov(eax, 1);
135 __ jmp(&C);
136
137 __ bind(&L);
138 __ imul(eax, Operand(edx));
139 __ sub(Operand(edx), Immediate(1));
140
141 __ bind(&C);
142 __ test(edx, Operand(edx));
143 __ j(not_zero, &L, taken);
144 __ ret(0);
145
146 // some relocated stuff here, not executed
147 __ mov(eax, Factory::true_value());
148 __ jmp(NULL, RelocInfo::RUNTIME_ENTRY);
149
150 CodeDesc desc;
151 assm.GetCode(&desc);
152 Object* code = Heap::CreateCode(desc,
153 NULL,
154 Code::ComputeFlags(Code::STUB),
155 Handle<Object>(Heap::undefined_value()));
156 CHECK(code->IsCode());
157#ifdef DEBUG
158 Code::cast(code)->Print();
159#endif
160 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
161 int res = f(10);
162 ::printf("f() = %d\n", res);
163 CHECK_EQ(3628800, res);
164}
165
166
167typedef int (*F3)(float x);
168
169TEST(AssemblerIa323) {
170 InitializeVM();
171 v8::HandleScope scope;
172
173 v8::internal::byte buffer[256];
174 Assembler assm(buffer, sizeof buffer);
175
176 CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2));
177 { CpuFeatures::Scope fscope(CpuFeatures::SSE2);
178 __ cvttss2si(eax, Operand(esp, 4));
179 __ ret(0);
180 }
181
182 CodeDesc desc;
183 assm.GetCode(&desc);
184 Code* code =
185 Code::cast(Heap::CreateCode(desc,
186 NULL,
187 Code::ComputeFlags(Code::STUB),
188 Handle<Object>(Heap::undefined_value())));
189 // don't print the code - our disassembler can't handle cvttss2si
190 // instead print bytes
191 Disassembler::Dump(stdout,
192 code->instruction_start(),
193 code->instruction_start() + code->instruction_size());
194 F3 f = FUNCTION_CAST<F3>(code->entry());
195 int res = f(static_cast<float>(-3.1415));
196 ::printf("f() = %d\n", res);
197 CHECK_EQ(-3, res);
198}
199
200
201typedef int (*F4)(double x);
202
203TEST(AssemblerIa324) {
204 InitializeVM();
205 v8::HandleScope scope;
206
207 v8::internal::byte buffer[256];
208 Assembler assm(buffer, sizeof buffer);
209
210 CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2));
211 CpuFeatures::Scope fscope(CpuFeatures::SSE2);
212 __ cvttsd2si(eax, Operand(esp, 4));
213 __ ret(0);
214
215 CodeDesc desc;
216 assm.GetCode(&desc);
217 Code* code =
218 Code::cast(Heap::CreateCode(desc,
219 NULL,
220 Code::ComputeFlags(Code::STUB),
221 Handle<Object>(Heap::undefined_value())));
222 // don't print the code - our disassembler can't handle cvttsd2si
223 // instead print bytes
224 Disassembler::Dump(stdout,
225 code->instruction_start(),
226 code->instruction_start() + code->instruction_size());
227 F4 f = FUNCTION_CAST<F4>(code->entry());
228 int res = f(2.718281828);
229 ::printf("f() = %d\n", res);
230 CHECK_EQ(2, res);
231}
232
233
234static int baz = 42;
235TEST(AssemblerIa325) {
236 InitializeVM();
237 v8::HandleScope scope;
238
239 v8::internal::byte buffer[256];
240 Assembler assm(buffer, sizeof buffer);
241
242 __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE));
243 __ ret(0);
244
245 CodeDesc desc;
246 assm.GetCode(&desc);
247 Code* code =
248 Code::cast(Heap::CreateCode(desc,
249 NULL,
250 Code::ComputeFlags(Code::STUB),
251 Handle<Object>(Heap::undefined_value())));
252 F0 f = FUNCTION_CAST<F0>(code->entry());
253 int res = f();
254 CHECK_EQ(42, res);
255}
256
257
258typedef double (*F5)(double x, double y);
259
260TEST(AssemblerIa326) {
261 InitializeVM();
262 v8::HandleScope scope;
263 CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2));
264 CpuFeatures::Scope fscope(CpuFeatures::SSE2);
265 v8::internal::byte buffer[256];
266 Assembler assm(buffer, sizeof buffer);
267
268 __ movdbl(xmm0, Operand(esp, 1 * kPointerSize));
269 __ movdbl(xmm1, Operand(esp, 3 * kPointerSize));
270 __ addsd(xmm0, xmm1);
271 __ mulsd(xmm0, xmm1);
272 __ subsd(xmm0, xmm1);
273 __ divsd(xmm0, xmm1);
274 // Copy xmm0 to st(0) using eight bytes of stack.
275 __ sub(Operand(esp), Immediate(8));
276 __ movdbl(Operand(esp, 0), xmm0);
277 __ fld_d(Operand(esp, 0));
278 __ add(Operand(esp), Immediate(8));
279 __ ret(0);
280
281 CodeDesc desc;
282 assm.GetCode(&desc);
283 Code* code =
284 Code::cast(Heap::CreateCode(desc,
285 NULL,
286 Code::ComputeFlags(Code::STUB),
287 Handle<Object>(Heap::undefined_value())));
288#ifdef DEBUG
289 ::printf("\n---\n");
290 // don't print the code - our disassembler can't handle SSE instructions
291 // instead print bytes
292 Disassembler::Dump(stdout,
293 code->instruction_start(),
294 code->instruction_start() + code->instruction_size());
295#endif
296 F5 f = FUNCTION_CAST<F5>(code->entry());
297 double res = f(2.2, 1.1);
298 ::printf("f() = %f\n", res);
299 CHECK(2.29 < res && res < 2.31);
300}
301
302
303typedef double (*F6)(int x);
304
305TEST(AssemblerIa328) {
306 InitializeVM();
307 v8::HandleScope scope;
308 CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2));
309 CpuFeatures::Scope fscope(CpuFeatures::SSE2);
310 v8::internal::byte buffer[256];
311 Assembler assm(buffer, sizeof buffer);
312 __ mov(eax, Operand(esp, 4));
313 __ cvtsi2sd(xmm0, Operand(eax));
314 // Copy xmm0 to st(0) using eight bytes of stack.
315 __ sub(Operand(esp), Immediate(8));
316 __ movdbl(Operand(esp, 0), xmm0);
317 __ fld_d(Operand(esp, 0));
318 __ add(Operand(esp), Immediate(8));
319 __ ret(0);
320 CodeDesc desc;
321 assm.GetCode(&desc);
322 Code* code =
323 Code::cast(Heap::CreateCode(desc,
324 NULL,
325 Code::ComputeFlags(Code::STUB),
326 Handle<Object>(Heap::undefined_value())));
327 CHECK(code->IsCode());
328#ifdef DEBUG
329 Code::cast(code)->Print();
330#endif
331 F6 f = FUNCTION_CAST<F6>(Code::cast(code)->entry());
332 double res = f(12);
333
334 ::printf("f() = %f\n", res);
335 CHECK(11.99 < res && res < 12.001);
336}
337
338
339typedef int (*F7)(double x, double y);
340
341TEST(AssemblerIa329) {
342 InitializeVM();
343 v8::HandleScope scope;
344 v8::internal::byte buffer[256];
345 MacroAssembler assm(buffer, sizeof buffer);
346 enum { kEqual = 0, kGreater = 1, kLess = 2, kNaN = 3, kUndefined = 4 };
347 Label equal_l, less_l, greater_l, nan_l;
348 __ fld_d(Operand(esp, 3 * kPointerSize));
349 __ fld_d(Operand(esp, 1 * kPointerSize));
350 __ FCmp();
351 __ j(parity_even, &nan_l, taken);
352 __ j(equal, &equal_l, taken);
353 __ j(below, &less_l, taken);
354 __ j(above, &greater_l, taken);
355
356 __ mov(eax, kUndefined);
357 __ ret(0);
358
359 __ bind(&equal_l);
360 __ mov(eax, kEqual);
361 __ ret(0);
362
363 __ bind(&greater_l);
364 __ mov(eax, kGreater);
365 __ ret(0);
366
367 __ bind(&less_l);
368 __ mov(eax, kLess);
369 __ ret(0);
370
371 __ bind(&nan_l);
372 __ mov(eax, kNaN);
373 __ ret(0);
374
375
376 CodeDesc desc;
377 assm.GetCode(&desc);
378 Code* code =
379 Code::cast(Heap::CreateCode(desc,
380 NULL,
381 Code::ComputeFlags(Code::STUB),
382 Handle<Object>(Heap::undefined_value())));
383 CHECK(code->IsCode());
384#ifdef DEBUG
385 Code::cast(code)->Print();
386#endif
387
388 F7 f = FUNCTION_CAST<F7>(Code::cast(code)->entry());
389 CHECK_EQ(kLess, f(1.1, 2.2));
390 CHECK_EQ(kEqual, f(2.2, 2.2));
391 CHECK_EQ(kGreater, f(3.3, 2.2));
392 CHECK_EQ(kNaN, f(OS::nan_value(), 1.1));
393}
394
395#undef __