Updated V8 from git://github.com/v8/v8.git to 57f8959fb264354ba1a2e5118db512f588917061
[profile/ivi/qtjsbackend.git] / src / 3rdparty / v8 / test / cctest / test-assembler-ia32.cc
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 "v8.h"
31
32 #include "disassembler.h"
33 #include "factory.h"
34 #include "macro-assembler.h"
35 #include "platform.h"
36 #include "serialize.h"
37 #include "cctest.h"
38
39 using namespace v8::internal;
40
41
42 typedef int (*F0)();
43 typedef int (*F1)(int x);
44 typedef int (*F2)(int x, int y);
45
46
47 static v8::Persistent<v8::Context> env;
48
49
50 static void InitializeVM() {
51   if (env.IsEmpty()) {
52     env = v8::Context::New();
53   }
54 }
55
56
57 #define __ assm.
58
59 TEST(AssemblerIa320) {
60   InitializeVM();
61   v8::HandleScope scope;
62
63   v8::internal::byte buffer[256];
64   Assembler assm(Isolate::Current(), buffer, sizeof buffer);
65
66   __ mov(eax, Operand(esp, 4));
67   __ add(eax, Operand(esp, 8));
68   __ ret(0);
69
70   CodeDesc desc;
71   assm.GetCode(&desc);
72   Object* code = HEAP->CreateCode(
73       desc,
74       Code::ComputeFlags(Code::STUB),
75       Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
76   CHECK(code->IsCode());
77 #ifdef OBJECT_PRINT
78   Code::cast(code)->Print();
79 #endif
80   F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
81   int res = f(3, 4);
82   ::printf("f() = %d\n", res);
83   CHECK_EQ(7, res);
84 }
85
86
87 TEST(AssemblerIa321) {
88   InitializeVM();
89   v8::HandleScope scope;
90
91   v8::internal::byte buffer[256];
92   Assembler assm(Isolate::Current(), buffer, sizeof buffer);
93   Label L, C;
94
95   __ mov(edx, Operand(esp, 4));
96   __ xor_(eax, eax);  // clear eax
97   __ jmp(&C);
98
99   __ bind(&L);
100   __ add(eax, edx);
101   __ sub(edx, Immediate(1));
102
103   __ bind(&C);
104   __ test(edx, edx);
105   __ j(not_zero, &L);
106   __ ret(0);
107
108   CodeDesc desc;
109   assm.GetCode(&desc);
110   Object* code = HEAP->CreateCode(
111       desc,
112       Code::ComputeFlags(Code::STUB),
113       Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
114   CHECK(code->IsCode());
115 #ifdef OBJECT_PRINT
116   Code::cast(code)->Print();
117 #endif
118   F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
119   int res = f(100);
120   ::printf("f() = %d\n", res);
121   CHECK_EQ(5050, res);
122 }
123
124
125 TEST(AssemblerIa322) {
126   InitializeVM();
127   v8::HandleScope scope;
128
129   v8::internal::byte buffer[256];
130   Assembler assm(Isolate::Current(), buffer, sizeof buffer);
131   Label L, C;
132
133   __ mov(edx, Operand(esp, 4));
134   __ mov(eax, 1);
135   __ jmp(&C);
136
137   __ bind(&L);
138   __ imul(eax, edx);
139   __ sub(edx, Immediate(1));
140
141   __ bind(&C);
142   __ test(edx, edx);
143   __ j(not_zero, &L);
144   __ ret(0);
145
146   // some relocated stuff here, not executed
147   __ mov(eax, FACTORY->true_value());
148   __ jmp(NULL, RelocInfo::RUNTIME_ENTRY);
149
150   CodeDesc desc;
151   assm.GetCode(&desc);
152   Object* code = HEAP->CreateCode(
153       desc,
154       Code::ComputeFlags(Code::STUB),
155       Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
156   CHECK(code->IsCode());
157 #ifdef OBJECT_PRINT
158   Code::cast(code)->Print();
159 #endif
160   F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
161   int res = f(10);
162   ::printf("f() = %d\n", res);
163   CHECK_EQ(3628800, res);
164 }
165
166
167 typedef int (*F3)(float x);
168
169 TEST(AssemblerIa323) {
170   InitializeVM();
171   if (!CpuFeatures::IsSupported(SSE2)) return;
172
173   v8::HandleScope scope;
174
175   v8::internal::byte buffer[256];
176   Assembler assm(Isolate::Current(), buffer, sizeof buffer);
177
178   CHECK(CpuFeatures::IsSupported(SSE2));
179   { CpuFeatures::Scope fscope(SSE2);
180     __ cvttss2si(eax, Operand(esp, 4));
181     __ ret(0);
182   }
183
184   CodeDesc desc;
185   assm.GetCode(&desc);
186   Code* code = Code::cast(HEAP->CreateCode(
187       desc,
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);
198   CHECK_EQ(-3, res);
199 }
200
201
202 typedef int (*F4)(double x);
203
204 TEST(AssemblerIa324) {
205   InitializeVM();
206   if (!CpuFeatures::IsSupported(SSE2)) return;
207
208   v8::HandleScope scope;
209
210   v8::internal::byte buffer[256];
211   Assembler assm(Isolate::Current(), buffer, sizeof buffer);
212
213   CHECK(CpuFeatures::IsSupported(SSE2));
214   CpuFeatures::Scope fscope(SSE2);
215   __ cvttsd2si(eax, Operand(esp, 4));
216   __ ret(0);
217
218   CodeDesc desc;
219   assm.GetCode(&desc);
220   Code* code = Code::cast(HEAP->CreateCode(
221       desc,
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);
232   CHECK_EQ(2, res);
233 }
234
235
236 static int baz = 42;
237 TEST(AssemblerIa325) {
238   InitializeVM();
239   v8::HandleScope scope;
240
241   v8::internal::byte buffer[256];
242   Assembler assm(Isolate::Current(), buffer, sizeof buffer);
243
244   __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE));
245   __ ret(0);
246
247   CodeDesc desc;
248   assm.GetCode(&desc);
249   Code* code = Code::cast(HEAP->CreateCode(
250       desc,
251       Code::ComputeFlags(Code::STUB),
252       Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
253   F0 f = FUNCTION_CAST<F0>(code->entry());
254   int res = f();
255   CHECK_EQ(42, res);
256 }
257
258
259 typedef double (*F5)(double x, double y);
260
261 TEST(AssemblerIa326) {
262   InitializeVM();
263   if (!CpuFeatures::IsSupported(SSE2)) return;
264
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);
270
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));
282   __ ret(0);
283
284   CodeDesc desc;
285   assm.GetCode(&desc);
286   Code* code = Code::cast(HEAP->CreateCode(
287       desc,
288       Code::ComputeFlags(Code::STUB),
289       Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
290 #ifdef DEBUG
291   ::printf("\n---\n");
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());
297 #endif
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);
302 }
303
304
305 typedef double (*F6)(int x);
306
307 TEST(AssemblerIa328) {
308   InitializeVM();
309   if (!CpuFeatures::IsSupported(SSE2)) return;
310
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));
323   __ ret(0);
324   CodeDesc desc;
325   assm.GetCode(&desc);
326   Code* code = Code::cast(HEAP->CreateCode(
327       desc,
328       Code::ComputeFlags(Code::STUB),
329       Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
330   CHECK(code->IsCode());
331 #ifdef OBJECT_PRINT
332   Code::cast(code)->Print();
333 #endif
334   F6 f = FUNCTION_CAST<F6>(Code::cast(code)->entry());
335   double res = f(12);
336
337   ::printf("f() = %f\n", res);
338   CHECK(11.99 < res && res < 12.001);
339 }
340
341
342 typedef int (*F7)(double x, double y);
343
344 TEST(AssemblerIa329) {
345   InitializeVM();
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));
353   __ FCmp();
354   __ j(parity_even, &nan_l);
355   __ j(equal, &equal_l);
356   __ j(below, &less_l);
357   __ j(above, &greater_l);
358
359   __ mov(eax, kUndefined);
360   __ ret(0);
361
362   __ bind(&equal_l);
363   __ mov(eax, kEqual);
364   __ ret(0);
365
366   __ bind(&greater_l);
367   __ mov(eax, kGreater);
368   __ ret(0);
369
370   __ bind(&less_l);
371   __ mov(eax, kLess);
372   __ ret(0);
373
374   __ bind(&nan_l);
375   __ mov(eax, kNaN);
376   __ ret(0);
377
378
379   CodeDesc desc;
380   assm.GetCode(&desc);
381   Code* code = Code::cast(HEAP->CreateCode(
382       desc,
383       Code::ComputeFlags(Code::STUB),
384       Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
385   CHECK(code->IsCode());
386 #ifdef OBJECT_PRINT
387   Code::cast(code)->Print();
388 #endif
389
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));
395 }
396
397
398 TEST(AssemblerIa3210) {
399   // Test chaining of label usages within instructions (issue 1644).
400   InitializeVM();
401   v8::HandleScope scope;
402   Assembler assm(Isolate::Current(), NULL, 0);
403
404   Label target;
405   __ j(equal, &target);
406   __ j(not_equal, &target);
407   __ bind(&target);
408   __ nop();
409 }
410
411
412 TEST(AssemblerMultiByteNop) {
413   InitializeVM();
414   v8::HandleScope scope;
415   v8::internal::byte buffer[1024];
416   Assembler assm(Isolate::Current(), buffer, sizeof(buffer));
417   __ push(ebx);
418   __ push(ecx);
419   __ push(edx);
420   __ push(edi);
421   __ push(esi);
422   __ mov(eax, 1);
423   __ mov(ebx, 2);
424   __ mov(ecx, 3);
425   __ mov(edx, 4);
426   __ mov(edi, 5);
427   __ mov(esi, 6);
428   for (int i = 0; i < 16; i++) {
429     int before = assm.pc_offset();
430     __ Nop(i);
431     CHECK_EQ(assm.pc_offset() - before, i);
432   }
433
434   Label fail;
435   __ cmp(eax, 1);
436   __ j(not_equal, &fail);
437   __ cmp(ebx, 2);
438   __ j(not_equal, &fail);
439   __ cmp(ecx, 3);
440   __ j(not_equal, &fail);
441   __ cmp(edx, 4);
442   __ j(not_equal, &fail);
443   __ cmp(edi, 5);
444   __ j(not_equal, &fail);
445   __ cmp(esi, 6);
446   __ j(not_equal, &fail);
447   __ mov(eax, 42);
448   __ pop(esi);
449   __ pop(edi);
450   __ pop(edx);
451   __ pop(ecx);
452   __ pop(ebx);
453   __ ret(0);
454   __ bind(&fail);
455   __ mov(eax, 13);
456   __ pop(esi);
457   __ pop(edi);
458   __ pop(edx);
459   __ pop(ecx);
460   __ pop(ebx);
461   __ ret(0);
462
463   CodeDesc desc;
464   assm.GetCode(&desc);
465   Code* code = Code::cast(HEAP->CreateCode(
466       desc,
467       Code::ComputeFlags(Code::STUB),
468       Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
469   CHECK(code->IsCode());
470
471   F0 f = FUNCTION_CAST<F0>(code->entry());
472   int res = f();
473   CHECK_EQ(42, res);
474 }
475
476
477
478
479 #undef __