blob: 815e618499f66ab3d1199e35c0efe178a03bdbbb [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +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];
Ben Murdoch8b112d22011-06-08 16:22:53 +010064 Assembler assm(Isolate::Current(), buffer, sizeof buffer);
Steve Blocka7e24c12009-10-30 11:49:00 +000065
66 __ mov(eax, Operand(esp, 4));
67 __ add(eax, Operand(esp, 8));
68 __ ret(0);
69
70 CodeDesc desc;
71 assm.GetCode(&desc);
Steve Block44f0eee2011-05-26 01:26:41 +010072 Object* code = HEAP->CreateCode(
73 desc,
74 Code::ComputeFlags(Code::STUB),
75 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000076 CHECK(code->IsCode());
Steve Block9fac8402011-05-12 15:51:54 +010077#ifdef OBJECT_PRINT
Steve Blocka7e24c12009-10-30 11:49:00 +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];
Ben Murdoch8b112d22011-06-08 16:22:53 +010092 Assembler assm(Isolate::Current(), buffer, sizeof buffer);
Steve Blocka7e24c12009-10-30 11:49:00 +000093 Label L, C;
94
95 __ mov(edx, Operand(esp, 4));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010096 __ xor_(eax, eax); // clear eax
Steve Blocka7e24c12009-10-30 11:49:00 +000097 __ jmp(&C);
98
99 __ bind(&L);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100100 __ add(eax, edx);
101 __ sub(edx, Immediate(1));
Steve Blocka7e24c12009-10-30 11:49:00 +0000102
103 __ bind(&C);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100104 __ test(edx, edx);
Ben Murdoch257744e2011-11-30 15:57:28 +0000105 __ j(not_zero, &L);
Steve Blocka7e24c12009-10-30 11:49:00 +0000106 __ ret(0);
107
108 CodeDesc desc;
109 assm.GetCode(&desc);
Steve Block44f0eee2011-05-26 01:26:41 +0100110 Object* code = HEAP->CreateCode(
111 desc,
112 Code::ComputeFlags(Code::STUB),
113 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000114 CHECK(code->IsCode());
Steve Block9fac8402011-05-12 15:51:54 +0100115#ifdef OBJECT_PRINT
Steve Blocka7e24c12009-10-30 11:49:00 +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];
Ben Murdoch8b112d22011-06-08 16:22:53 +0100130 Assembler assm(Isolate::Current(), buffer, sizeof buffer);
Steve Blocka7e24c12009-10-30 11:49:00 +0000131 Label L, C;
132
133 __ mov(edx, Operand(esp, 4));
134 __ mov(eax, 1);
135 __ jmp(&C);
136
137 __ bind(&L);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100138 __ imul(eax, edx);
139 __ sub(edx, Immediate(1));
Steve Blocka7e24c12009-10-30 11:49:00 +0000140
141 __ bind(&C);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100142 __ test(edx, edx);
Ben Murdoch257744e2011-11-30 15:57:28 +0000143 __ j(not_zero, &L);
Steve Blocka7e24c12009-10-30 11:49:00 +0000144 __ ret(0);
145
146 // some relocated stuff here, not executed
Steve Block44f0eee2011-05-26 01:26:41 +0100147 __ mov(eax, FACTORY->true_value());
Steve Blocka7e24c12009-10-30 11:49:00 +0000148 __ jmp(NULL, RelocInfo::RUNTIME_ENTRY);
149
150 CodeDesc desc;
151 assm.GetCode(&desc);
Steve Block44f0eee2011-05-26 01:26:41 +0100152 Object* code = HEAP->CreateCode(
John Reck59135872010-11-02 12:39:01 -0700153 desc,
154 Code::ComputeFlags(Code::STUB),
Steve Block44f0eee2011-05-26 01:26:41 +0100155 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000156 CHECK(code->IsCode());
Steve Block9fac8402011-05-12 15:51:54 +0100157#ifdef OBJECT_PRINT
Steve Blocka7e24c12009-10-30 11:49:00 +0000158 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();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100171 if (!CpuFeatures::IsSupported(SSE2)) return;
172
Steve Blocka7e24c12009-10-30 11:49:00 +0000173 v8::HandleScope scope;
174
175 v8::internal::byte buffer[256];
Ben Murdoch8b112d22011-06-08 16:22:53 +0100176 Assembler assm(Isolate::Current(), buffer, sizeof buffer);
Steve Blocka7e24c12009-10-30 11:49:00 +0000177
Ben Murdoch8b112d22011-06-08 16:22:53 +0100178 CHECK(CpuFeatures::IsSupported(SSE2));
Steve Blockd0582a62009-12-15 09:54:21 +0000179 { CpuFeatures::Scope fscope(SSE2);
Steve Blocka7e24c12009-10-30 11:49:00 +0000180 __ cvttss2si(eax, Operand(esp, 4));
181 __ ret(0);
182 }
183
184 CodeDesc desc;
185 assm.GetCode(&desc);
Steve Block44f0eee2011-05-26 01:26:41 +0100186 Code* code = Code::cast(HEAP->CreateCode(
John Reck59135872010-11-02 12:39:01 -0700187 desc,
188 Code::ComputeFlags(Code::STUB),
Steve Block44f0eee2011-05-26 01:26:41 +0100189 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +0000190 // don't print the code - our disassembler can't handle cvttss2si
191 // instead print bytes
192 Disassembler::Dump(stdout,
193 code->instruction_start(),
194 code->instruction_start() + code->instruction_size());
195 F3 f = FUNCTION_CAST<F3>(code->entry());
196 int res = f(static_cast<float>(-3.1415));
197 ::printf("f() = %d\n", res);
198 CHECK_EQ(-3, res);
199}
200
201
202typedef int (*F4)(double x);
203
204TEST(AssemblerIa324) {
205 InitializeVM();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100206 if (!CpuFeatures::IsSupported(SSE2)) return;
207
Steve Blocka7e24c12009-10-30 11:49:00 +0000208 v8::HandleScope scope;
209
210 v8::internal::byte buffer[256];
Ben Murdoch8b112d22011-06-08 16:22:53 +0100211 Assembler assm(Isolate::Current(), buffer, sizeof buffer);
Steve Blocka7e24c12009-10-30 11:49:00 +0000212
Ben Murdoch8b112d22011-06-08 16:22:53 +0100213 CHECK(CpuFeatures::IsSupported(SSE2));
Steve Blockd0582a62009-12-15 09:54:21 +0000214 CpuFeatures::Scope fscope(SSE2);
Steve Blocka7e24c12009-10-30 11:49:00 +0000215 __ cvttsd2si(eax, Operand(esp, 4));
216 __ ret(0);
217
218 CodeDesc desc;
219 assm.GetCode(&desc);
Steve Block44f0eee2011-05-26 01:26:41 +0100220 Code* code = Code::cast(HEAP->CreateCode(
John Reck59135872010-11-02 12:39:01 -0700221 desc,
222 Code::ComputeFlags(Code::STUB),
Steve Block44f0eee2011-05-26 01:26:41 +0100223 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +0000224 // don't print the code - our disassembler can't handle cvttsd2si
225 // instead print bytes
226 Disassembler::Dump(stdout,
227 code->instruction_start(),
228 code->instruction_start() + code->instruction_size());
229 F4 f = FUNCTION_CAST<F4>(code->entry());
230 int res = f(2.718281828);
231 ::printf("f() = %d\n", res);
232 CHECK_EQ(2, res);
233}
234
235
236static int baz = 42;
237TEST(AssemblerIa325) {
238 InitializeVM();
239 v8::HandleScope scope;
240
241 v8::internal::byte buffer[256];
Ben Murdoch8b112d22011-06-08 16:22:53 +0100242 Assembler assm(Isolate::Current(), buffer, sizeof buffer);
Steve Blocka7e24c12009-10-30 11:49:00 +0000243
244 __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE));
245 __ ret(0);
246
247 CodeDesc desc;
248 assm.GetCode(&desc);
Steve Block44f0eee2011-05-26 01:26:41 +0100249 Code* code = Code::cast(HEAP->CreateCode(
John Reck59135872010-11-02 12:39:01 -0700250 desc,
251 Code::ComputeFlags(Code::STUB),
Steve Block44f0eee2011-05-26 01:26:41 +0100252 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +0000253 F0 f = FUNCTION_CAST<F0>(code->entry());
254 int res = f();
255 CHECK_EQ(42, res);
256}
257
258
259typedef double (*F5)(double x, double y);
260
261TEST(AssemblerIa326) {
262 InitializeVM();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100263 if (!CpuFeatures::IsSupported(SSE2)) return;
264
Steve Blocka7e24c12009-10-30 11:49:00 +0000265 v8::HandleScope scope;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100266 CHECK(CpuFeatures::IsSupported(SSE2));
Steve Blockd0582a62009-12-15 09:54:21 +0000267 CpuFeatures::Scope fscope(SSE2);
Steve Blocka7e24c12009-10-30 11:49:00 +0000268 v8::internal::byte buffer[256];
Ben Murdoch8b112d22011-06-08 16:22:53 +0100269 Assembler assm(Isolate::Current(), buffer, sizeof buffer);
Steve Blocka7e24c12009-10-30 11:49:00 +0000270
271 __ movdbl(xmm0, Operand(esp, 1 * kPointerSize));
272 __ movdbl(xmm1, Operand(esp, 3 * kPointerSize));
273 __ addsd(xmm0, xmm1);
274 __ mulsd(xmm0, xmm1);
275 __ subsd(xmm0, xmm1);
276 __ divsd(xmm0, xmm1);
277 // Copy xmm0 to st(0) using eight bytes of stack.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100278 __ sub(esp, Immediate(8));
Steve Blocka7e24c12009-10-30 11:49:00 +0000279 __ movdbl(Operand(esp, 0), xmm0);
280 __ fld_d(Operand(esp, 0));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100281 __ add(esp, Immediate(8));
Steve Blocka7e24c12009-10-30 11:49:00 +0000282 __ ret(0);
283
284 CodeDesc desc;
285 assm.GetCode(&desc);
Steve Block44f0eee2011-05-26 01:26:41 +0100286 Code* code = Code::cast(HEAP->CreateCode(
John Reck59135872010-11-02 12:39:01 -0700287 desc,
288 Code::ComputeFlags(Code::STUB),
Steve Block44f0eee2011-05-26 01:26:41 +0100289 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +0000290#ifdef DEBUG
291 ::printf("\n---\n");
292 // don't print the code - our disassembler can't handle SSE instructions
293 // instead print bytes
294 Disassembler::Dump(stdout,
295 code->instruction_start(),
296 code->instruction_start() + code->instruction_size());
297#endif
298 F5 f = FUNCTION_CAST<F5>(code->entry());
299 double res = f(2.2, 1.1);
300 ::printf("f() = %f\n", res);
301 CHECK(2.29 < res && res < 2.31);
302}
303
304
305typedef double (*F6)(int x);
306
307TEST(AssemblerIa328) {
308 InitializeVM();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100309 if (!CpuFeatures::IsSupported(SSE2)) return;
310
Steve Blocka7e24c12009-10-30 11:49:00 +0000311 v8::HandleScope scope;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100312 CHECK(CpuFeatures::IsSupported(SSE2));
Steve Blockd0582a62009-12-15 09:54:21 +0000313 CpuFeatures::Scope fscope(SSE2);
Steve Blocka7e24c12009-10-30 11:49:00 +0000314 v8::internal::byte buffer[256];
Ben Murdoch8b112d22011-06-08 16:22:53 +0100315 Assembler assm(Isolate::Current(), buffer, sizeof buffer);
Steve Blocka7e24c12009-10-30 11:49:00 +0000316 __ mov(eax, Operand(esp, 4));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100317 __ cvtsi2sd(xmm0, eax);
Steve Blocka7e24c12009-10-30 11:49:00 +0000318 // Copy xmm0 to st(0) using eight bytes of stack.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100319 __ sub(esp, Immediate(8));
Steve Blocka7e24c12009-10-30 11:49:00 +0000320 __ movdbl(Operand(esp, 0), xmm0);
321 __ fld_d(Operand(esp, 0));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100322 __ add(esp, Immediate(8));
Steve Blocka7e24c12009-10-30 11:49:00 +0000323 __ ret(0);
324 CodeDesc desc;
325 assm.GetCode(&desc);
Steve Block44f0eee2011-05-26 01:26:41 +0100326 Code* code = Code::cast(HEAP->CreateCode(
John Reck59135872010-11-02 12:39:01 -0700327 desc,
328 Code::ComputeFlags(Code::STUB),
Steve Block44f0eee2011-05-26 01:26:41 +0100329 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +0000330 CHECK(code->IsCode());
Steve Block9fac8402011-05-12 15:51:54 +0100331#ifdef OBJECT_PRINT
Steve Blocka7e24c12009-10-30 11:49:00 +0000332 Code::cast(code)->Print();
333#endif
334 F6 f = FUNCTION_CAST<F6>(Code::cast(code)->entry());
335 double res = f(12);
336
337 ::printf("f() = %f\n", res);
338 CHECK(11.99 < res && res < 12.001);
339}
340
341
342typedef int (*F7)(double x, double y);
343
344TEST(AssemblerIa329) {
345 InitializeVM();
346 v8::HandleScope scope;
347 v8::internal::byte buffer[256];
Ben Murdoch8b112d22011-06-08 16:22:53 +0100348 MacroAssembler assm(Isolate::Current(), buffer, sizeof buffer);
Steve Blocka7e24c12009-10-30 11:49:00 +0000349 enum { kEqual = 0, kGreater = 1, kLess = 2, kNaN = 3, kUndefined = 4 };
350 Label equal_l, less_l, greater_l, nan_l;
351 __ fld_d(Operand(esp, 3 * kPointerSize));
352 __ fld_d(Operand(esp, 1 * kPointerSize));
353 __ FCmp();
Ben Murdoch257744e2011-11-30 15:57:28 +0000354 __ j(parity_even, &nan_l);
355 __ j(equal, &equal_l);
356 __ j(below, &less_l);
357 __ j(above, &greater_l);
Steve Blocka7e24c12009-10-30 11:49:00 +0000358
359 __ mov(eax, kUndefined);
360 __ ret(0);
361
362 __ bind(&equal_l);
363 __ mov(eax, kEqual);
364 __ ret(0);
365
366 __ bind(&greater_l);
367 __ mov(eax, kGreater);
368 __ ret(0);
369
370 __ bind(&less_l);
371 __ mov(eax, kLess);
372 __ ret(0);
373
374 __ bind(&nan_l);
375 __ mov(eax, kNaN);
376 __ ret(0);
377
378
379 CodeDesc desc;
380 assm.GetCode(&desc);
Steve Block44f0eee2011-05-26 01:26:41 +0100381 Code* code = Code::cast(HEAP->CreateCode(
John Reck59135872010-11-02 12:39:01 -0700382 desc,
383 Code::ComputeFlags(Code::STUB),
Steve Block44f0eee2011-05-26 01:26:41 +0100384 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +0000385 CHECK(code->IsCode());
Steve Block9fac8402011-05-12 15:51:54 +0100386#ifdef OBJECT_PRINT
Steve Blocka7e24c12009-10-30 11:49:00 +0000387 Code::cast(code)->Print();
388#endif
389
390 F7 f = FUNCTION_CAST<F7>(Code::cast(code)->entry());
391 CHECK_EQ(kLess, f(1.1, 2.2));
392 CHECK_EQ(kEqual, f(2.2, 2.2));
393 CHECK_EQ(kGreater, f(3.3, 2.2));
394 CHECK_EQ(kNaN, f(OS::nan_value(), 1.1));
395}
396
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000397
398TEST(AssemblerIa3210) {
399 // Test chaining of label usages within instructions (issue 1644).
400 InitializeVM();
401 v8::HandleScope scope;
402 Assembler assm(Isolate::Current(), NULL, 0);
403
404 Label target;
405 __ j(equal, &target);
406 __ j(not_equal, &target);
407 __ bind(&target);
408 __ nop();
409}
410
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100411
412TEST(AssemblerMultiByteNop) {
413 InitializeVM();
414 v8::HandleScope scope;
415 v8::internal::byte buffer[1024];
416 Assembler assm(Isolate::Current(), buffer, sizeof(buffer));
417 __ push(ebx);
418 __ push(ecx);
419 __ push(edx);
420 __ push(edi);
421 __ push(esi);
422 __ mov(eax, 1);
423 __ mov(ebx, 2);
424 __ mov(ecx, 3);
425 __ mov(edx, 4);
426 __ mov(edi, 5);
427 __ mov(esi, 6);
428 for (int i = 0; i < 16; i++) {
429 int before = assm.pc_offset();
430 __ Nop(i);
431 CHECK_EQ(assm.pc_offset() - before, i);
432 }
433
434 Label fail;
435 __ cmp(eax, 1);
436 __ j(not_equal, &fail);
437 __ cmp(ebx, 2);
438 __ j(not_equal, &fail);
439 __ cmp(ecx, 3);
440 __ j(not_equal, &fail);
441 __ cmp(edx, 4);
442 __ j(not_equal, &fail);
443 __ cmp(edi, 5);
444 __ j(not_equal, &fail);
445 __ cmp(esi, 6);
446 __ j(not_equal, &fail);
447 __ mov(eax, 42);
448 __ pop(esi);
449 __ pop(edi);
450 __ pop(edx);
451 __ pop(ecx);
452 __ pop(ebx);
453 __ ret(0);
454 __ bind(&fail);
455 __ mov(eax, 13);
456 __ pop(esi);
457 __ pop(edi);
458 __ pop(edx);
459 __ pop(ecx);
460 __ pop(ebx);
461 __ ret(0);
462
463 CodeDesc desc;
464 assm.GetCode(&desc);
465 Code* code = Code::cast(HEAP->CreateCode(
466 desc,
467 Code::ComputeFlags(Code::STUB),
468 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
469 CHECK(code->IsCode());
470
471 F0 f = FUNCTION_CAST<F0>(code->entry());
472 int res = f();
473 CHECK_EQ(42, res);
474}
475
476
477
478
Steve Blocka7e24c12009-10-30 11:49:00 +0000479#undef __