blob: a831a0b2f1a8658f14c995029354eeb649ed70c5 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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/base/platform/platform.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000033#include "src/base/utils/random-number-generator.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034#include "src/disassembler.h"
35#include "src/factory.h"
36#include "src/macro-assembler.h"
37#include "src/ostreams.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000038#include "test/cctest/cctest.h"
39
40using namespace v8::internal;
41
42
43typedef int (*F0)();
44typedef int (*F1)(int x);
45typedef int (*F2)(int x, int y);
46
47
48#define __ assm.
49
50TEST(AssemblerIa320) {
51 CcTest::InitializeVM();
52 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
53 HandleScope scope(isolate);
54
55 v8::internal::byte buffer[256];
56 Assembler assm(isolate, buffer, sizeof buffer);
57
58 __ mov(eax, Operand(esp, 4));
59 __ add(eax, Operand(esp, 8));
60 __ ret(0);
61
62 CodeDesc desc;
63 assm.GetCode(&desc);
64 Handle<Code> code = isolate->factory()->NewCode(
65 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
66#ifdef OBJECT_PRINT
67 OFStream os(stdout);
68 code->Print(os);
69#endif
70 F2 f = FUNCTION_CAST<F2>(code->entry());
71 int res = f(3, 4);
72 ::printf("f() = %d\n", res);
73 CHECK_EQ(7, res);
74}
75
76
77TEST(AssemblerIa321) {
78 CcTest::InitializeVM();
79 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
80 HandleScope scope(isolate);
81
82 v8::internal::byte buffer[256];
83 Assembler assm(isolate, buffer, sizeof buffer);
84 Label L, C;
85
86 __ mov(edx, Operand(esp, 4));
87 __ xor_(eax, eax); // clear eax
88 __ jmp(&C);
89
90 __ bind(&L);
91 __ add(eax, edx);
92 __ sub(edx, Immediate(1));
93
94 __ bind(&C);
95 __ test(edx, edx);
96 __ j(not_zero, &L);
97 __ ret(0);
98
99 CodeDesc desc;
100 assm.GetCode(&desc);
101 Handle<Code> code = isolate->factory()->NewCode(
102 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
103#ifdef OBJECT_PRINT
104 OFStream os(stdout);
105 code->Print(os);
106#endif
107 F1 f = FUNCTION_CAST<F1>(code->entry());
108 int res = f(100);
109 ::printf("f() = %d\n", res);
110 CHECK_EQ(5050, res);
111}
112
113
114TEST(AssemblerIa322) {
115 CcTest::InitializeVM();
116 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
117 HandleScope scope(isolate);
118
119 v8::internal::byte buffer[256];
120 Assembler assm(isolate, buffer, sizeof buffer);
121 Label L, C;
122
123 __ mov(edx, Operand(esp, 4));
124 __ mov(eax, 1);
125 __ jmp(&C);
126
127 __ bind(&L);
128 __ imul(eax, edx);
129 __ sub(edx, Immediate(1));
130
131 __ bind(&C);
132 __ test(edx, edx);
133 __ j(not_zero, &L);
134 __ ret(0);
135
136 // some relocated stuff here, not executed
137 __ mov(eax, isolate->factory()->true_value());
138 __ jmp(NULL, RelocInfo::RUNTIME_ENTRY);
139
140 CodeDesc desc;
141 assm.GetCode(&desc);
142 Handle<Code> code = isolate->factory()->NewCode(
143 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
144#ifdef OBJECT_PRINT
145 OFStream os(stdout);
146 code->Print(os);
147#endif
148 F1 f = FUNCTION_CAST<F1>(code->entry());
149 int res = f(10);
150 ::printf("f() = %d\n", res);
151 CHECK_EQ(3628800, res);
152}
153
154
155typedef int (*F3)(float x);
156
157typedef int (*F4)(double x);
158
159static int baz = 42;
160TEST(AssemblerIa325) {
161 CcTest::InitializeVM();
162 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
163 HandleScope scope(isolate);
164
165 v8::internal::byte buffer[256];
166 Assembler assm(isolate, buffer, sizeof buffer);
167
168 __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE32));
169 __ ret(0);
170
171 CodeDesc desc;
172 assm.GetCode(&desc);
173 Handle<Code> code = isolate->factory()->NewCode(
174 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
175 F0 f = FUNCTION_CAST<F0>(code->entry());
176 int res = f();
177 CHECK_EQ(42, res);
178}
179
180
181typedef int (*F7)(double x, double y);
182
183TEST(AssemblerIa329) {
184 CcTest::InitializeVM();
185 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
186 HandleScope scope(isolate);
187 v8::internal::byte buffer[256];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000188 MacroAssembler assm(isolate, buffer, sizeof(buffer),
189 v8::internal::CodeObjectRequired::kYes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000190 enum { kEqual = 0, kGreater = 1, kLess = 2, kNaN = 3, kUndefined = 4 };
191 Label equal_l, less_l, greater_l, nan_l;
192 __ fld_d(Operand(esp, 3 * kPointerSize));
193 __ fld_d(Operand(esp, 1 * kPointerSize));
194 __ FCmp();
195 __ j(parity_even, &nan_l);
196 __ j(equal, &equal_l);
197 __ j(below, &less_l);
198 __ j(above, &greater_l);
199
200 __ mov(eax, kUndefined);
201 __ ret(0);
202
203 __ bind(&equal_l);
204 __ mov(eax, kEqual);
205 __ ret(0);
206
207 __ bind(&greater_l);
208 __ mov(eax, kGreater);
209 __ ret(0);
210
211 __ bind(&less_l);
212 __ mov(eax, kLess);
213 __ ret(0);
214
215 __ bind(&nan_l);
216 __ mov(eax, kNaN);
217 __ ret(0);
218
219
220 CodeDesc desc;
221 assm.GetCode(&desc);
222 Handle<Code> code = isolate->factory()->NewCode(
223 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
224#ifdef OBJECT_PRINT
225 OFStream os(stdout);
226 code->Print(os);
227#endif
228
229 F7 f = FUNCTION_CAST<F7>(code->entry());
230 CHECK_EQ(kLess, f(1.1, 2.2));
231 CHECK_EQ(kEqual, f(2.2, 2.2));
232 CHECK_EQ(kGreater, f(3.3, 2.2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000233 CHECK_EQ(kNaN, f(std::numeric_limits<double>::quiet_NaN(), 1.1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000234}
235
236
237TEST(AssemblerIa3210) {
238 // Test chaining of label usages within instructions (issue 1644).
239 CcTest::InitializeVM();
240 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
241 HandleScope scope(isolate);
242 Assembler assm(isolate, NULL, 0);
243
244 Label target;
245 __ j(equal, &target);
246 __ j(not_equal, &target);
247 __ bind(&target);
248 __ nop();
249}
250
251
252TEST(AssemblerMultiByteNop) {
253 CcTest::InitializeVM();
254 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
255 HandleScope scope(isolate);
256 v8::internal::byte buffer[1024];
257 Assembler assm(isolate, buffer, sizeof(buffer));
258 __ push(ebx);
259 __ push(ecx);
260 __ push(edx);
261 __ push(edi);
262 __ push(esi);
263 __ mov(eax, 1);
264 __ mov(ebx, 2);
265 __ mov(ecx, 3);
266 __ mov(edx, 4);
267 __ mov(edi, 5);
268 __ mov(esi, 6);
269 for (int i = 0; i < 16; i++) {
270 int before = assm.pc_offset();
271 __ Nop(i);
272 CHECK_EQ(assm.pc_offset() - before, i);
273 }
274
275 Label fail;
276 __ cmp(eax, 1);
277 __ j(not_equal, &fail);
278 __ cmp(ebx, 2);
279 __ j(not_equal, &fail);
280 __ cmp(ecx, 3);
281 __ j(not_equal, &fail);
282 __ cmp(edx, 4);
283 __ j(not_equal, &fail);
284 __ cmp(edi, 5);
285 __ j(not_equal, &fail);
286 __ cmp(esi, 6);
287 __ j(not_equal, &fail);
288 __ mov(eax, 42);
289 __ pop(esi);
290 __ pop(edi);
291 __ pop(edx);
292 __ pop(ecx);
293 __ pop(ebx);
294 __ ret(0);
295 __ bind(&fail);
296 __ mov(eax, 13);
297 __ pop(esi);
298 __ pop(edi);
299 __ pop(edx);
300 __ pop(ecx);
301 __ pop(ebx);
302 __ ret(0);
303
304 CodeDesc desc;
305 assm.GetCode(&desc);
306 Handle<Code> code = isolate->factory()->NewCode(
307 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
308 CHECK(code->IsCode());
309
310 F0 f = FUNCTION_CAST<F0>(code->entry());
311 int res = f();
312 CHECK_EQ(42, res);
313}
314
315
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000316TEST(AssemblerIa32JumpTables1) {
317 // Test jump tables with forward jumps.
318 CcTest::InitializeVM();
319 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
320 HandleScope scope(isolate);
321 Assembler assm(isolate, nullptr, 0);
322
323 const int kNumCases = 512;
324 int values[kNumCases];
325 isolate->random_number_generator()->NextBytes(values, sizeof(values));
326 Label labels[kNumCases];
327
328 Label done, table;
329 __ mov(eax, Operand(esp, 4));
330 __ jmp(Operand::JumpTable(eax, times_4, &table));
331 __ ud2();
332 __ bind(&table);
333 for (int i = 0; i < kNumCases; ++i) {
334 __ dd(&labels[i]);
335 }
336
337 for (int i = 0; i < kNumCases; ++i) {
338 __ bind(&labels[i]);
339 __ mov(eax, Immediate(values[i]));
340 __ jmp(&done);
341 }
342
343 __ bind(&done);
344 __ ret(0);
345
346 CodeDesc desc;
347 assm.GetCode(&desc);
348 Handle<Code> code = isolate->factory()->NewCode(
349 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
350#ifdef OBJECT_PRINT
351 OFStream os(stdout);
352 code->Print(os);
353#endif
354 F1 f = FUNCTION_CAST<F1>(code->entry());
355 for (int i = 0; i < kNumCases; ++i) {
356 int res = f(i);
357 ::printf("f(%d) = %d\n", i, res);
358 CHECK_EQ(values[i], res);
359 }
360}
361
362
363TEST(AssemblerIa32JumpTables2) {
364 // Test jump tables with backward jumps.
365 CcTest::InitializeVM();
366 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
367 HandleScope scope(isolate);
368 Assembler assm(isolate, nullptr, 0);
369
370 const int kNumCases = 512;
371 int values[kNumCases];
372 isolate->random_number_generator()->NextBytes(values, sizeof(values));
373 Label labels[kNumCases];
374
375 Label done, table;
376 __ mov(eax, Operand(esp, 4));
377 __ jmp(Operand::JumpTable(eax, times_4, &table));
378 __ ud2();
379
380 for (int i = 0; i < kNumCases; ++i) {
381 __ bind(&labels[i]);
382 __ mov(eax, Immediate(values[i]));
383 __ jmp(&done);
384 }
385
386 __ bind(&table);
387 for (int i = 0; i < kNumCases; ++i) {
388 __ dd(&labels[i]);
389 }
390
391 __ bind(&done);
392 __ ret(0);
393
394 CodeDesc desc;
395 assm.GetCode(&desc);
396 Handle<Code> code = isolate->factory()->NewCode(
397 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
398#ifdef OBJECT_PRINT
399 OFStream os(stdout);
400 code->Print(os);
401#endif
402 F1 f = FUNCTION_CAST<F1>(code->entry());
403 for (int i = 0; i < kNumCases; ++i) {
404 int res = f(i);
405 ::printf("f(%d) = %d\n", i, res);
406 CHECK_EQ(values[i], res);
407 }
408}
409
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000410#undef __