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 "test/cctest/cctest.h"
39 using namespace v8::internal;
43 typedef int (*F1)(int x);
44 typedef int (*F2)(int x, int y);
49 TEST(AssemblerIa320) {
50 CcTest::InitializeVM();
51 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
52 HandleScope scope(isolate);
54 v8::internal::byte buffer[256];
55 Assembler assm(isolate, buffer, sizeof buffer);
57 __ mov(eax, Operand(esp, 4));
58 __ add(eax, Operand(esp, 8));
63 Handle<Code> code = isolate->factory()->NewCode(
64 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
69 F2 f = FUNCTION_CAST<F2>(code->entry());
71 ::printf("f() = %d\n", res);
76 TEST(AssemblerIa321) {
77 CcTest::InitializeVM();
78 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
79 HandleScope scope(isolate);
81 v8::internal::byte buffer[256];
82 Assembler assm(isolate, buffer, sizeof buffer);
85 __ mov(edx, Operand(esp, 4));
86 __ xor_(eax, eax); // clear eax
91 __ sub(edx, Immediate(1));
100 Handle<Code> code = isolate->factory()->NewCode(
101 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
106 F1 f = FUNCTION_CAST<F1>(code->entry());
108 ::printf("f() = %d\n", res);
113 TEST(AssemblerIa322) {
114 CcTest::InitializeVM();
115 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
116 HandleScope scope(isolate);
118 v8::internal::byte buffer[256];
119 Assembler assm(isolate, buffer, sizeof buffer);
122 __ mov(edx, Operand(esp, 4));
128 __ sub(edx, Immediate(1));
135 // some relocated stuff here, not executed
136 __ mov(eax, isolate->factory()->true_value());
137 __ jmp(NULL, RelocInfo::RUNTIME_ENTRY);
141 Handle<Code> code = isolate->factory()->NewCode(
142 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
147 F1 f = FUNCTION_CAST<F1>(code->entry());
149 ::printf("f() = %d\n", res);
150 CHECK_EQ(3628800, res);
154 typedef int (*F3)(float x);
156 typedef int (*F4)(double x);
159 TEST(AssemblerIa325) {
160 CcTest::InitializeVM();
161 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
162 HandleScope scope(isolate);
164 v8::internal::byte buffer[256];
165 Assembler assm(isolate, buffer, sizeof buffer);
167 __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE32));
172 Handle<Code> code = isolate->factory()->NewCode(
173 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
174 F0 f = FUNCTION_CAST<F0>(code->entry());
180 typedef int (*F7)(double x, double y);
182 TEST(AssemblerIa329) {
183 CcTest::InitializeVM();
184 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
185 HandleScope scope(isolate);
186 v8::internal::byte buffer[256];
187 MacroAssembler assm(isolate, buffer, sizeof buffer);
188 enum { kEqual = 0, kGreater = 1, kLess = 2, kNaN = 3, kUndefined = 4 };
189 Label equal_l, less_l, greater_l, nan_l;
190 __ fld_d(Operand(esp, 3 * kPointerSize));
191 __ fld_d(Operand(esp, 1 * kPointerSize));
193 __ j(parity_even, &nan_l);
194 __ j(equal, &equal_l);
195 __ j(below, &less_l);
196 __ j(above, &greater_l);
198 __ mov(eax, kUndefined);
206 __ mov(eax, kGreater);
220 Handle<Code> code = isolate->factory()->NewCode(
221 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
227 F7 f = FUNCTION_CAST<F7>(code->entry());
228 CHECK_EQ(kLess, f(1.1, 2.2));
229 CHECK_EQ(kEqual, f(2.2, 2.2));
230 CHECK_EQ(kGreater, f(3.3, 2.2));
231 CHECK_EQ(kNaN, f(std::numeric_limits<double>::quiet_NaN(), 1.1));
235 TEST(AssemblerIa3210) {
236 // Test chaining of label usages within instructions (issue 1644).
237 CcTest::InitializeVM();
238 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
239 HandleScope scope(isolate);
240 Assembler assm(isolate, NULL, 0);
243 __ j(equal, &target);
244 __ j(not_equal, &target);
250 TEST(AssemblerMultiByteNop) {
251 CcTest::InitializeVM();
252 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
253 HandleScope scope(isolate);
254 v8::internal::byte buffer[1024];
255 Assembler assm(isolate, buffer, sizeof(buffer));
267 for (int i = 0; i < 16; i++) {
268 int before = assm.pc_offset();
270 CHECK_EQ(assm.pc_offset() - before, i);
275 __ j(not_equal, &fail);
277 __ j(not_equal, &fail);
279 __ j(not_equal, &fail);
281 __ j(not_equal, &fail);
283 __ j(not_equal, &fail);
285 __ j(not_equal, &fail);
304 Handle<Code> code = isolate->factory()->NewCode(
305 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
306 CHECK(code->IsCode());
308 F0 f = FUNCTION_CAST<F0>(code->entry());
314 TEST(AssemblerIa32JumpTables1) {
315 // Test jump tables with forward jumps.
316 CcTest::InitializeVM();
317 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
318 HandleScope scope(isolate);
319 Assembler assm(isolate, nullptr, 0);
321 const int kNumCases = 512;
322 int values[kNumCases];
323 isolate->random_number_generator()->NextBytes(values, sizeof(values));
324 Label labels[kNumCases];
327 __ mov(eax, Operand(esp, 4));
328 __ jmp(Operand::JumpTable(eax, times_4, &table));
331 for (int i = 0; i < kNumCases; ++i) {
335 for (int i = 0; i < kNumCases; ++i) {
337 __ mov(eax, Immediate(values[i]));
346 Handle<Code> code = isolate->factory()->NewCode(
347 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
352 F1 f = FUNCTION_CAST<F1>(code->entry());
353 for (int i = 0; i < kNumCases; ++i) {
355 ::printf("f(%d) = %d\n", i, res);
356 CHECK_EQ(values[i], res);
361 TEST(AssemblerIa32JumpTables2) {
362 // Test jump tables with backward jumps.
363 CcTest::InitializeVM();
364 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
365 HandleScope scope(isolate);
366 Assembler assm(isolate, nullptr, 0);
368 const int kNumCases = 512;
369 int values[kNumCases];
370 isolate->random_number_generator()->NextBytes(values, sizeof(values));
371 Label labels[kNumCases];
374 __ mov(eax, Operand(esp, 4));
375 __ jmp(Operand::JumpTable(eax, times_4, &table));
378 for (int i = 0; i < kNumCases; ++i) {
380 __ mov(eax, Immediate(values[i]));
385 for (int i = 0; i < kNumCases; ++i) {
394 Handle<Code> code = isolate->factory()->NewCode(
395 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
400 F1 f = FUNCTION_CAST<F1>(code->entry());
401 for (int i = 0; i < kNumCases; ++i) {
403 ::printf("f(%d) = %d\n", i, res);
404 CHECK_EQ(values[i], res);