1// Copyright 2011 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 "src/v8.h"
31
32#include "src/disassembler.h"
33#include "src/factory.h"
34#include "src/macro-assembler.h"
35#include "src/platform.h"
36#include "src/serialize.h"
37#include "test/cctest/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
47#define __ assm.
48
49TEST(AssemblerIa320) {
50  CcTest::InitializeVM();
51  Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
52  HandleScope scope(isolate);
53
54  v8::internal::byte buffer[256];
55  Assembler assm(isolate, buffer, sizeof buffer);
56
57  __ mov(eax, Operand(esp, 4));
58  __ add(eax, Operand(esp, 8));
59  __ ret(0);
60
61  CodeDesc desc;
62  assm.GetCode(&desc);
63  Handle<Code> code = isolate->factory()->NewCode(
64      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
65#ifdef OBJECT_PRINT
66  code->Print();
67#endif
68  F2 f = FUNCTION_CAST<F2>(code->entry());
69  int res = f(3, 4);
70  ::printf("f() = %d\n", res);
71  CHECK_EQ(7, res);
72}
73
74
75TEST(AssemblerIa321) {
76  CcTest::InitializeVM();
77  Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
78  HandleScope scope(isolate);
79
80  v8::internal::byte buffer[256];
81  Assembler assm(isolate, buffer, sizeof buffer);
82  Label L, C;
83
84  __ mov(edx, Operand(esp, 4));
85  __ xor_(eax, eax);  // clear eax
86  __ jmp(&C);
87
88  __ bind(&L);
89  __ add(eax, edx);
90  __ sub(edx, Immediate(1));
91
92  __ bind(&C);
93  __ test(edx, edx);
94  __ j(not_zero, &L);
95  __ ret(0);
96
97  CodeDesc desc;
98  assm.GetCode(&desc);
99  Handle<Code> code = isolate->factory()->NewCode(
100      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
101#ifdef OBJECT_PRINT
102  code->Print();
103#endif
104  F1 f = FUNCTION_CAST<F1>(code->entry());
105  int res = f(100);
106  ::printf("f() = %d\n", res);
107  CHECK_EQ(5050, res);
108}
109
110
111TEST(AssemblerIa322) {
112  CcTest::InitializeVM();
113  Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
114  HandleScope scope(isolate);
115
116  v8::internal::byte buffer[256];
117  Assembler assm(isolate, buffer, sizeof buffer);
118  Label L, C;
119
120  __ mov(edx, Operand(esp, 4));
121  __ mov(eax, 1);
122  __ jmp(&C);
123
124  __ bind(&L);
125  __ imul(eax, edx);
126  __ sub(edx, Immediate(1));
127
128  __ bind(&C);
129  __ test(edx, edx);
130  __ j(not_zero, &L);
131  __ ret(0);
132
133  // some relocated stuff here, not executed
134  __ mov(eax, isolate->factory()->true_value());
135  __ jmp(NULL, RelocInfo::RUNTIME_ENTRY);
136
137  CodeDesc desc;
138  assm.GetCode(&desc);
139  Handle<Code> code = isolate->factory()->NewCode(
140      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
141#ifdef OBJECT_PRINT
142  code->Print();
143#endif
144  F1 f = FUNCTION_CAST<F1>(code->entry());
145  int res = f(10);
146  ::printf("f() = %d\n", res);
147  CHECK_EQ(3628800, res);
148}
149
150
151typedef int (*F3)(float x);
152
153typedef int (*F4)(double x);
154
155static int baz = 42;
156TEST(AssemblerIa325) {
157  CcTest::InitializeVM();
158  Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
159  HandleScope scope(isolate);
160
161  v8::internal::byte buffer[256];
162  Assembler assm(isolate, buffer, sizeof buffer);
163
164  __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE32));
165  __ ret(0);
166
167  CodeDesc desc;
168  assm.GetCode(&desc);
169  Handle<Code> code = isolate->factory()->NewCode(
170      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
171  F0 f = FUNCTION_CAST<F0>(code->entry());
172  int res = f();
173  CHECK_EQ(42, res);
174}
175
176
177typedef int (*F7)(double x, double y);
178
179TEST(AssemblerIa329) {
180  CcTest::InitializeVM();
181  Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
182  HandleScope scope(isolate);
183  v8::internal::byte buffer[256];
184  MacroAssembler assm(isolate, buffer, sizeof buffer);
185  enum { kEqual = 0, kGreater = 1, kLess = 2, kNaN = 3, kUndefined = 4 };
186  Label equal_l, less_l, greater_l, nan_l;
187  __ fld_d(Operand(esp, 3 * kPointerSize));
188  __ fld_d(Operand(esp, 1 * kPointerSize));
189  __ FCmp();
190  __ j(parity_even, &nan_l);
191  __ j(equal, &equal_l);
192  __ j(below, &less_l);
193  __ j(above, &greater_l);
194
195  __ mov(eax, kUndefined);
196  __ ret(0);
197
198  __ bind(&equal_l);
199  __ mov(eax, kEqual);
200  __ ret(0);
201
202  __ bind(&greater_l);
203  __ mov(eax, kGreater);
204  __ ret(0);
205
206  __ bind(&less_l);
207  __ mov(eax, kLess);
208  __ ret(0);
209
210  __ bind(&nan_l);
211  __ mov(eax, kNaN);
212  __ ret(0);
213
214
215  CodeDesc desc;
216  assm.GetCode(&desc);
217  Handle<Code> code = isolate->factory()->NewCode(
218      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
219#ifdef OBJECT_PRINT
220  code->Print();
221#endif
222
223  F7 f = FUNCTION_CAST<F7>(code->entry());
224  CHECK_EQ(kLess, f(1.1, 2.2));
225  CHECK_EQ(kEqual, f(2.2, 2.2));
226  CHECK_EQ(kGreater, f(3.3, 2.2));
227  CHECK_EQ(kNaN, f(OS::nan_value(), 1.1));
228}
229
230
231TEST(AssemblerIa3210) {
232  // Test chaining of label usages within instructions (issue 1644).
233  CcTest::InitializeVM();
234  Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
235  HandleScope scope(isolate);
236  Assembler assm(isolate, NULL, 0);
237
238  Label target;
239  __ j(equal, &target);
240  __ j(not_equal, &target);
241  __ bind(&target);
242  __ nop();
243}
244
245
246TEST(AssemblerMultiByteNop) {
247  CcTest::InitializeVM();
248  Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
249  HandleScope scope(isolate);
250  v8::internal::byte buffer[1024];
251  Assembler assm(isolate, buffer, sizeof(buffer));
252  __ push(ebx);
253  __ push(ecx);
254  __ push(edx);
255  __ push(edi);
256  __ push(esi);
257  __ mov(eax, 1);
258  __ mov(ebx, 2);
259  __ mov(ecx, 3);
260  __ mov(edx, 4);
261  __ mov(edi, 5);
262  __ mov(esi, 6);
263  for (int i = 0; i < 16; i++) {
264    int before = assm.pc_offset();
265    __ Nop(i);
266    CHECK_EQ(assm.pc_offset() - before, i);
267  }
268
269  Label fail;
270  __ cmp(eax, 1);
271  __ j(not_equal, &fail);
272  __ cmp(ebx, 2);
273  __ j(not_equal, &fail);
274  __ cmp(ecx, 3);
275  __ j(not_equal, &fail);
276  __ cmp(edx, 4);
277  __ j(not_equal, &fail);
278  __ cmp(edi, 5);
279  __ j(not_equal, &fail);
280  __ cmp(esi, 6);
281  __ j(not_equal, &fail);
282  __ mov(eax, 42);
283  __ pop(esi);
284  __ pop(edi);
285  __ pop(edx);
286  __ pop(ecx);
287  __ pop(ebx);
288  __ ret(0);
289  __ bind(&fail);
290  __ mov(eax, 13);
291  __ pop(esi);
292  __ pop(edi);
293  __ pop(edx);
294  __ pop(ecx);
295  __ pop(ebx);
296  __ ret(0);
297
298  CodeDesc desc;
299  assm.GetCode(&desc);
300  Handle<Code> code = isolate->factory()->NewCode(
301      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
302  CHECK(code->IsCode());
303
304  F0 f = FUNCTION_CAST<F0>(code->entry());
305  int res = f();
306  CHECK_EQ(42, res);
307}
308
309
310#undef __
311