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 "disassembler.h"
34 #include "macro-assembler.h"
36 #include "serialize.h"
39 using namespace v8::internal;
43 typedef int (*F1)(int x);
44 typedef int (*F2)(int x, int y);
47 static v8::Persistent<v8::Context> env;
50 static void InitializeVM() {
52 env = v8::Context::New();
59 TEST(AssemblerIa320) {
61 v8::HandleScope scope;
63 v8::internal::byte buffer[256];
64 Assembler assm(Isolate::Current(), buffer, sizeof buffer);
66 __ mov(eax, Operand(esp, 4));
67 __ add(eax, Operand(esp, 8));
72 Object* code = HEAP->CreateCode(
74 Code::ComputeFlags(Code::STUB),
75 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
76 CHECK(code->IsCode());
78 Code::cast(code)->Print();
80 F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
82 ::printf("f() = %d\n", res);
87 TEST(AssemblerIa321) {
89 v8::HandleScope scope;
91 v8::internal::byte buffer[256];
92 Assembler assm(Isolate::Current(), buffer, sizeof buffer);
95 __ mov(edx, Operand(esp, 4));
96 __ xor_(eax, eax); // clear eax
101 __ sub(edx, Immediate(1));
110 Object* code = HEAP->CreateCode(
112 Code::ComputeFlags(Code::STUB),
113 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
114 CHECK(code->IsCode());
116 Code::cast(code)->Print();
118 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
120 ::printf("f() = %d\n", res);
125 TEST(AssemblerIa322) {
127 v8::HandleScope scope;
129 v8::internal::byte buffer[256];
130 Assembler assm(Isolate::Current(), buffer, sizeof buffer);
133 __ mov(edx, Operand(esp, 4));
139 __ sub(edx, Immediate(1));
146 // some relocated stuff here, not executed
147 __ mov(eax, FACTORY->true_value());
148 __ jmp(NULL, RelocInfo::RUNTIME_ENTRY);
152 Object* code = HEAP->CreateCode(
154 Code::ComputeFlags(Code::STUB),
155 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
156 CHECK(code->IsCode());
158 Code::cast(code)->Print();
160 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
162 ::printf("f() = %d\n", res);
163 CHECK_EQ(3628800, res);
167 typedef int (*F3)(float x);
169 TEST(AssemblerIa323) {
171 if (!CpuFeatures::IsSupported(SSE2)) return;
173 v8::HandleScope scope;
175 v8::internal::byte buffer[256];
176 Assembler assm(Isolate::Current(), buffer, sizeof buffer);
178 CHECK(CpuFeatures::IsSupported(SSE2));
179 { CpuFeatures::Scope fscope(SSE2);
180 __ cvttss2si(eax, Operand(esp, 4));
186 Code* code = Code::cast(HEAP->CreateCode(
188 Code::ComputeFlags(Code::STUB),
189 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
190 // 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);
202 typedef int (*F4)(double x);
204 TEST(AssemblerIa324) {
206 if (!CpuFeatures::IsSupported(SSE2)) return;
208 v8::HandleScope scope;
210 v8::internal::byte buffer[256];
211 Assembler assm(Isolate::Current(), buffer, sizeof buffer);
213 CHECK(CpuFeatures::IsSupported(SSE2));
214 CpuFeatures::Scope fscope(SSE2);
215 __ cvttsd2si(eax, Operand(esp, 4));
220 Code* code = Code::cast(HEAP->CreateCode(
222 Code::ComputeFlags(Code::STUB),
223 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
224 // 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);
237 TEST(AssemblerIa325) {
239 v8::HandleScope scope;
241 v8::internal::byte buffer[256];
242 Assembler assm(Isolate::Current(), buffer, sizeof buffer);
244 __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE));
249 Code* code = Code::cast(HEAP->CreateCode(
251 Code::ComputeFlags(Code::STUB),
252 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
253 F0 f = FUNCTION_CAST<F0>(code->entry());
259 typedef double (*F5)(double x, double y);
261 TEST(AssemblerIa326) {
263 if (!CpuFeatures::IsSupported(SSE2)) return;
265 v8::HandleScope scope;
266 CHECK(CpuFeatures::IsSupported(SSE2));
267 CpuFeatures::Scope fscope(SSE2);
268 v8::internal::byte buffer[256];
269 Assembler assm(Isolate::Current(), buffer, sizeof buffer);
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.
278 __ sub(esp, Immediate(8));
279 __ movdbl(Operand(esp, 0), xmm0);
280 __ fld_d(Operand(esp, 0));
281 __ add(esp, Immediate(8));
286 Code* code = Code::cast(HEAP->CreateCode(
288 Code::ComputeFlags(Code::STUB),
289 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
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());
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);
305 typedef double (*F6)(int x);
307 TEST(AssemblerIa328) {
309 if (!CpuFeatures::IsSupported(SSE2)) return;
311 v8::HandleScope scope;
312 CHECK(CpuFeatures::IsSupported(SSE2));
313 CpuFeatures::Scope fscope(SSE2);
314 v8::internal::byte buffer[256];
315 Assembler assm(Isolate::Current(), buffer, sizeof buffer);
316 __ mov(eax, Operand(esp, 4));
317 __ cvtsi2sd(xmm0, eax);
318 // Copy xmm0 to st(0) using eight bytes of stack.
319 __ sub(esp, Immediate(8));
320 __ movdbl(Operand(esp, 0), xmm0);
321 __ fld_d(Operand(esp, 0));
322 __ add(esp, Immediate(8));
326 Code* code = Code::cast(HEAP->CreateCode(
328 Code::ComputeFlags(Code::STUB),
329 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
330 CHECK(code->IsCode());
332 Code::cast(code)->Print();
334 F6 f = FUNCTION_CAST<F6>(Code::cast(code)->entry());
337 ::printf("f() = %f\n", res);
338 CHECK(11.99 < res && res < 12.001);
342 typedef int (*F7)(double x, double y);
344 TEST(AssemblerIa329) {
346 v8::HandleScope scope;
347 v8::internal::byte buffer[256];
348 MacroAssembler assm(Isolate::Current(), buffer, sizeof buffer);
349 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));
354 __ j(parity_even, &nan_l);
355 __ j(equal, &equal_l);
356 __ j(below, &less_l);
357 __ j(above, &greater_l);
359 __ mov(eax, kUndefined);
367 __ mov(eax, kGreater);
381 Code* code = Code::cast(HEAP->CreateCode(
383 Code::ComputeFlags(Code::STUB),
384 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
385 CHECK(code->IsCode());
387 Code::cast(code)->Print();
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));
398 TEST(AssemblerIa3210) {
399 // Test chaining of label usages within instructions (issue 1644).
401 v8::HandleScope scope;
402 Assembler assm(Isolate::Current(), NULL, 0);
405 __ j(equal, &target);
406 __ j(not_equal, &target);
412 TEST(AssemblerMultiByteNop) {
414 v8::HandleScope scope;
415 v8::internal::byte buffer[1024];
416 Assembler assm(Isolate::Current(), buffer, sizeof(buffer));
428 for (int i = 0; i < 16; i++) {
429 int before = assm.pc_offset();
431 CHECK_EQ(assm.pc_offset() - before, i);
436 __ j(not_equal, &fail);
438 __ j(not_equal, &fail);
440 __ j(not_equal, &fail);
442 __ j(not_equal, &fail);
444 __ j(not_equal, &fail);
446 __ j(not_equal, &fail);
465 Code* code = Code::cast(HEAP->CreateCode(
467 Code::ComputeFlags(Code::STUB),
468 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
469 CHECK(code->IsCode());
471 F0 f = FUNCTION_CAST<F0>(code->entry());