blob: 14692ff1eb4bfd689cdd3286586d69c5adb1d788 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002// 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);
kasperl@chromium.org061ef742009-02-27 12:16:20 +000072 Object* code = Heap::CreateCode(desc,
kasperl@chromium.org061ef742009-02-27 12:16:20 +000073 Code::ComputeFlags(Code::STUB),
lrn@chromium.org303ada72010-10-27 09:33:13 +000074 Handle<Object>(Heap::undefined_value()))->
75 ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000076 CHECK(code->IsCode());
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +000077#ifdef OBJECT_PRINT
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000078 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);
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000110 Object* code = Heap::CreateCode(desc,
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000111 Code::ComputeFlags(Code::STUB),
lrn@chromium.org303ada72010-10-27 09:33:13 +0000112 Handle<Object>(Heap::undefined_value()))->
113 ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000114 CHECK(code->IsCode());
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000115#ifdef OBJECT_PRINT
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000116 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());
ager@chromium.org236ad962008-09-25 09:45:57 +0000148 __ jmp(NULL, RelocInfo::RUNTIME_ENTRY);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000149
150 CodeDesc desc;
151 assm.GetCode(&desc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000152 Object* code = Heap::CreateCode(
153 desc,
154 Code::ComputeFlags(Code::STUB),
155 Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
156
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000157 CHECK(code->IsCode());
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000158#ifdef OBJECT_PRINT
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000159 Code::cast(code)->Print();
160#endif
161 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
162 int res = f(10);
163 ::printf("f() = %d\n", res);
164 CHECK_EQ(3628800, res);
165}
166
167
168typedef int (*F3)(float x);
169
170TEST(AssemblerIa323) {
fschneider@chromium.org086aac62010-03-17 13:18:24 +0000171 if (!CpuFeatures::IsSupported(SSE2)) return;
172
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000173 InitializeVM();
174 v8::HandleScope scope;
175
176 v8::internal::byte buffer[256];
177 Assembler assm(buffer, sizeof buffer);
178
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000179 CHECK(CpuFeatures::IsSupported(SSE2));
180 { CpuFeatures::Scope fscope(SSE2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000181 __ cvttss2si(eax, Operand(esp, 4));
182 __ ret(0);
183 }
184
185 CodeDesc desc;
186 assm.GetCode(&desc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000187 Code* code = Code::cast(Heap::CreateCode(
188 desc,
189 Code::ComputeFlags(Code::STUB),
190 Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000191 // don't print the code - our disassembler can't handle cvttss2si
192 // instead print bytes
193 Disassembler::Dump(stdout,
194 code->instruction_start(),
195 code->instruction_start() + code->instruction_size());
196 F3 f = FUNCTION_CAST<F3>(code->entry());
197 int res = f(static_cast<float>(-3.1415));
198 ::printf("f() = %d\n", res);
199 CHECK_EQ(-3, res);
200}
201
202
203typedef int (*F4)(double x);
204
205TEST(AssemblerIa324) {
fschneider@chromium.org086aac62010-03-17 13:18:24 +0000206 if (!CpuFeatures::IsSupported(SSE2)) return;
207
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000208 InitializeVM();
209 v8::HandleScope scope;
210
211 v8::internal::byte buffer[256];
212 Assembler assm(buffer, sizeof buffer);
213
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000214 CHECK(CpuFeatures::IsSupported(SSE2));
215 CpuFeatures::Scope fscope(SSE2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000216 __ cvttsd2si(eax, Operand(esp, 4));
217 __ ret(0);
218
219 CodeDesc desc;
220 assm.GetCode(&desc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000221 Code* code = Code::cast(Heap::CreateCode(
222 desc,
223 Code::ComputeFlags(Code::STUB),
224 Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000225 // don't print the code - our disassembler can't handle cvttsd2si
226 // instead print bytes
227 Disassembler::Dump(stdout,
228 code->instruction_start(),
229 code->instruction_start() + code->instruction_size());
230 F4 f = FUNCTION_CAST<F4>(code->entry());
231 int res = f(2.718281828);
232 ::printf("f() = %d\n", res);
233 CHECK_EQ(2, res);
234}
235
236
237static int baz = 42;
238TEST(AssemblerIa325) {
239 InitializeVM();
240 v8::HandleScope scope;
241
242 v8::internal::byte buffer[256];
243 Assembler assm(buffer, sizeof buffer);
244
ager@chromium.org236ad962008-09-25 09:45:57 +0000245 __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000246 __ ret(0);
247
248 CodeDesc desc;
249 assm.GetCode(&desc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000250 Code* code = Code::cast(Heap::CreateCode(
251 desc,
252 Code::ComputeFlags(Code::STUB),
253 Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000254 F0 f = FUNCTION_CAST<F0>(code->entry());
255 int res = f();
256 CHECK_EQ(42, res);
257}
258
259
260typedef double (*F5)(double x, double y);
261
262TEST(AssemblerIa326) {
fschneider@chromium.org086aac62010-03-17 13:18:24 +0000263 if (!CpuFeatures::IsSupported(SSE2)) return;
264
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000265 InitializeVM();
266 v8::HandleScope scope;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000267 CHECK(CpuFeatures::IsSupported(SSE2));
268 CpuFeatures::Scope fscope(SSE2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000269 v8::internal::byte buffer[256];
270 Assembler assm(buffer, sizeof buffer);
271
272 __ movdbl(xmm0, Operand(esp, 1 * kPointerSize));
273 __ movdbl(xmm1, Operand(esp, 3 * kPointerSize));
274 __ addsd(xmm0, xmm1);
275 __ mulsd(xmm0, xmm1);
276 __ subsd(xmm0, xmm1);
277 __ divsd(xmm0, xmm1);
278 // Copy xmm0 to st(0) using eight bytes of stack.
279 __ sub(Operand(esp), Immediate(8));
280 __ movdbl(Operand(esp, 0), xmm0);
281 __ fld_d(Operand(esp, 0));
282 __ add(Operand(esp), Immediate(8));
283 __ ret(0);
284
285 CodeDesc desc;
286 assm.GetCode(&desc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000287 Code* code = Code::cast(Heap::CreateCode(
288 desc,
289 Code::ComputeFlags(Code::STUB),
290 Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000291#ifdef DEBUG
292 ::printf("\n---\n");
293 // don't print the code - our disassembler can't handle SSE instructions
294 // instead print bytes
295 Disassembler::Dump(stdout,
296 code->instruction_start(),
297 code->instruction_start() + code->instruction_size());
298#endif
299 F5 f = FUNCTION_CAST<F5>(code->entry());
300 double res = f(2.2, 1.1);
301 ::printf("f() = %f\n", res);
302 CHECK(2.29 < res && res < 2.31);
303}
304
305
306typedef double (*F6)(int x);
307
308TEST(AssemblerIa328) {
fschneider@chromium.org086aac62010-03-17 13:18:24 +0000309 if (!CpuFeatures::IsSupported(SSE2)) return;
310
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000311 InitializeVM();
312 v8::HandleScope scope;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000313 CHECK(CpuFeatures::IsSupported(SSE2));
314 CpuFeatures::Scope fscope(SSE2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000315 v8::internal::byte buffer[256];
316 Assembler assm(buffer, sizeof buffer);
317 __ mov(eax, Operand(esp, 4));
318 __ cvtsi2sd(xmm0, Operand(eax));
319 // Copy xmm0 to st(0) using eight bytes of stack.
320 __ sub(Operand(esp), Immediate(8));
321 __ movdbl(Operand(esp, 0), xmm0);
322 __ fld_d(Operand(esp, 0));
323 __ add(Operand(esp), Immediate(8));
324 __ ret(0);
325 CodeDesc desc;
326 assm.GetCode(&desc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000327 Code* code = Code::cast(Heap::CreateCode(
328 desc,
329 Code::ComputeFlags(Code::STUB),
330 Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000331 CHECK(code->IsCode());
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000332#ifdef OBJECT_PRINT
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000333 Code::cast(code)->Print();
334#endif
335 F6 f = FUNCTION_CAST<F6>(Code::cast(code)->entry());
336 double res = f(12);
337
338 ::printf("f() = %f\n", res);
339 CHECK(11.99 < res && res < 12.001);
340}
341
342
343typedef int (*F7)(double x, double y);
344
345TEST(AssemblerIa329) {
346 InitializeVM();
347 v8::HandleScope scope;
348 v8::internal::byte buffer[256];
349 MacroAssembler assm(buffer, sizeof buffer);
350 enum { kEqual = 0, kGreater = 1, kLess = 2, kNaN = 3, kUndefined = 4 };
351 Label equal_l, less_l, greater_l, nan_l;
352 __ fld_d(Operand(esp, 3 * kPointerSize));
353 __ fld_d(Operand(esp, 1 * kPointerSize));
354 __ FCmp();
355 __ j(parity_even, &nan_l, taken);
356 __ j(equal, &equal_l, taken);
357 __ j(below, &less_l, taken);
358 __ j(above, &greater_l, taken);
359
360 __ mov(eax, kUndefined);
361 __ ret(0);
362
363 __ bind(&equal_l);
364 __ mov(eax, kEqual);
365 __ ret(0);
366
367 __ bind(&greater_l);
368 __ mov(eax, kGreater);
369 __ ret(0);
370
371 __ bind(&less_l);
372 __ mov(eax, kLess);
373 __ ret(0);
374
375 __ bind(&nan_l);
376 __ mov(eax, kNaN);
377 __ ret(0);
378
379
380 CodeDesc desc;
381 assm.GetCode(&desc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000382 Code* code = Code::cast(Heap::CreateCode(
383 desc,
384 Code::ComputeFlags(Code::STUB),
385 Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000386 CHECK(code->IsCode());
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000387#ifdef OBJECT_PRINT
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000388 Code::cast(code)->Print();
389#endif
390
391 F7 f = FUNCTION_CAST<F7>(Code::cast(code)->entry());
392 CHECK_EQ(kLess, f(1.1, 2.2));
393 CHECK_EQ(kEqual, f(2.2, 2.2));
394 CHECK_EQ(kGreater, f(3.3, 2.2));
395 CHECK_EQ(kNaN, f(OS::nan_value(), 1.1));
396}
397
398#undef __