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
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.
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.
32 #include "src/base/platform/platform.h"
33 #include "src/disassembler.h"
34 #include "src/factory.h"
35 #include "src/macro-assembler.h"
36 #include "src/ostreams.h"
37 #include "src/serialize.h"
38 #include "test/cctest/cctest.h"
40 using namespace v8::internal;
44 typedef int (*F1)(int x);
45 typedef int (*F2)(int x, int y);
50 TEST(AssemblerIa320) {
51 CcTest::InitializeVM();
52 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
53 HandleScope scope(isolate);
55 v8::internal::byte buffer[256];
56 Assembler assm(isolate, buffer, sizeof buffer);
58 __ mov(eax, Operand(esp, 4));
59 __ add(eax, Operand(esp, 8));
64 Handle<Code> code = isolate->factory()->NewCode(
65 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
70 F2 f = FUNCTION_CAST<F2>(code->entry());
72 ::printf("f() = %d\n", res);
77 TEST(AssemblerIa321) {
78 CcTest::InitializeVM();
79 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
80 HandleScope scope(isolate);
82 v8::internal::byte buffer[256];
83 Assembler assm(isolate, buffer, sizeof buffer);
86 __ mov(edx, Operand(esp, 4));
87 __ xor_(eax, eax); // clear eax
92 __ sub(edx, Immediate(1));
101 Handle<Code> code = isolate->factory()->NewCode(
102 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
107 F1 f = FUNCTION_CAST<F1>(code->entry());
109 ::printf("f() = %d\n", res);
114 TEST(AssemblerIa322) {
115 CcTest::InitializeVM();
116 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
117 HandleScope scope(isolate);
119 v8::internal::byte buffer[256];
120 Assembler assm(isolate, buffer, sizeof buffer);
123 __ mov(edx, Operand(esp, 4));
129 __ sub(edx, Immediate(1));
136 // some relocated stuff here, not executed
137 __ mov(eax, isolate->factory()->true_value());
138 __ jmp(NULL, RelocInfo::RUNTIME_ENTRY);
142 Handle<Code> code = isolate->factory()->NewCode(
143 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
148 F1 f = FUNCTION_CAST<F1>(code->entry());
150 ::printf("f() = %d\n", res);
151 CHECK_EQ(3628800, res);
155 typedef int (*F3)(float x);
157 typedef int (*F4)(double x);
160 TEST(AssemblerIa325) {
161 CcTest::InitializeVM();
162 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
163 HandleScope scope(isolate);
165 v8::internal::byte buffer[256];
166 Assembler assm(isolate, buffer, sizeof buffer);
168 __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE32));
173 Handle<Code> code = isolate->factory()->NewCode(
174 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
175 F0 f = FUNCTION_CAST<F0>(code->entry());
181 typedef int (*F7)(double x, double y);
183 TEST(AssemblerIa329) {
184 CcTest::InitializeVM();
185 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
186 HandleScope scope(isolate);
187 v8::internal::byte buffer[256];
188 MacroAssembler assm(isolate, buffer, sizeof buffer);
189 enum { kEqual = 0, kGreater = 1, kLess = 2, kNaN = 3, kUndefined = 4 };
190 Label equal_l, less_l, greater_l, nan_l;
191 __ fld_d(Operand(esp, 3 * kPointerSize));
192 __ fld_d(Operand(esp, 1 * kPointerSize));
194 __ j(parity_even, &nan_l);
195 __ j(equal, &equal_l);
196 __ j(below, &less_l);
197 __ j(above, &greater_l);
199 __ mov(eax, kUndefined);
207 __ mov(eax, kGreater);
221 Handle<Code> code = isolate->factory()->NewCode(
222 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
228 F7 f = FUNCTION_CAST<F7>(code->entry());
229 CHECK_EQ(kLess, f(1.1, 2.2));
230 CHECK_EQ(kEqual, f(2.2, 2.2));
231 CHECK_EQ(kGreater, f(3.3, 2.2));
232 CHECK_EQ(kNaN, f(std::numeric_limits<double>::quiet_NaN(), 1.1));
236 TEST(AssemblerIa3210) {
237 // Test chaining of label usages within instructions (issue 1644).
238 CcTest::InitializeVM();
239 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
240 HandleScope scope(isolate);
241 Assembler assm(isolate, NULL, 0);
244 __ j(equal, &target);
245 __ j(not_equal, &target);
251 TEST(AssemblerMultiByteNop) {
252 CcTest::InitializeVM();
253 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
254 HandleScope scope(isolate);
255 v8::internal::byte buffer[1024];
256 Assembler assm(isolate, buffer, sizeof(buffer));
268 for (int i = 0; i < 16; i++) {
269 int before = assm.pc_offset();
271 CHECK_EQ(assm.pc_offset() - before, i);
276 __ j(not_equal, &fail);
278 __ j(not_equal, &fail);
280 __ j(not_equal, &fail);
282 __ j(not_equal, &fail);
284 __ j(not_equal, &fail);
286 __ j(not_equal, &fail);
305 Handle<Code> code = isolate->factory()->NewCode(
306 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
307 CHECK(code->IsCode());
309 F0 f = FUNCTION_CAST<F0>(code->entry());
315 TEST(AssemblerIa32JumpTables1) {
316 // Test jump tables with forward jumps.
317 CcTest::InitializeVM();
318 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
319 HandleScope scope(isolate);
320 Assembler assm(isolate, nullptr, 0);
322 const int kNumCases = 512;
323 int values[kNumCases];
324 isolate->random_number_generator()->NextBytes(values, sizeof(values));
325 Label labels[kNumCases];
328 __ mov(eax, Operand(esp, 4));
329 __ jmp(Operand::JumpTable(eax, times_4, &table));
332 for (int i = 0; i < kNumCases; ++i) {
336 for (int i = 0; i < kNumCases; ++i) {
338 __ mov(eax, Immediate(values[i]));
347 Handle<Code> code = isolate->factory()->NewCode(
348 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
353 F1 f = FUNCTION_CAST<F1>(code->entry());
354 for (int i = 0; i < kNumCases; ++i) {
356 ::printf("f(%d) = %d\n", i, res);
357 CHECK_EQ(values[i], res);
362 TEST(AssemblerIa32JumpTables2) {
363 // Test jump tables with backward jumps.
364 CcTest::InitializeVM();
365 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
366 HandleScope scope(isolate);
367 Assembler assm(isolate, nullptr, 0);
369 const int kNumCases = 512;
370 int values[kNumCases];
371 isolate->random_number_generator()->NextBytes(values, sizeof(values));
372 Label labels[kNumCases];
375 __ mov(eax, Operand(esp, 4));
376 __ jmp(Operand::JumpTable(eax, times_4, &table));
379 for (int i = 0; i < kNumCases; ++i) {
381 __ mov(eax, Immediate(values[i]));
386 for (int i = 0; i < kNumCases; ++i) {
395 Handle<Code> code = isolate->factory()->NewCode(
396 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
401 F1 f = FUNCTION_CAST<F1>(code->entry());
402 for (int i = 0; i < kNumCases; ++i) {
404 ::printf("f(%d) = %d\n", i, res);
405 CHECK_EQ(values[i], res);