Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / 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 "src/v8.h"
31
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"
39
40 using namespace v8::internal;
41
42
43 typedef int (*F0)();
44 typedef int (*F1)(int x);
45 typedef int (*F2)(int x, int y);
46
47
48 #define __ assm.
49
50 TEST(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
77 TEST(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
114 TEST(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
155 typedef int (*F3)(float x);
156
157 TEST(AssemblerIa323) {
158   CcTest::InitializeVM();
159
160   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
161   HandleScope scope(isolate);
162
163   v8::internal::byte buffer[256];
164   Assembler assm(isolate, buffer, sizeof buffer);
165
166   __ cvttss2si(eax, Operand(esp, 4));
167   __ ret(0);
168
169   CodeDesc desc;
170   assm.GetCode(&desc);
171   Handle<Code> code = isolate->factory()->NewCode(
172       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
173 #ifdef OBJECT_PRINT
174   OFStream os(stdout);
175   code->Print(os);
176 #endif
177   F3 f = FUNCTION_CAST<F3>(code->entry());
178   int res = f(static_cast<float>(-3.1415));
179   ::printf("f() = %d\n", res);
180   CHECK_EQ(-3, res);
181 }
182
183
184 typedef int (*F4)(double x);
185
186 TEST(AssemblerIa324) {
187   CcTest::InitializeVM();
188
189   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
190   HandleScope scope(isolate);
191
192   v8::internal::byte buffer[256];
193   Assembler assm(isolate, buffer, sizeof buffer);
194
195   __ cvttsd2si(eax, Operand(esp, 4));
196   __ ret(0);
197
198   CodeDesc desc;
199   assm.GetCode(&desc);
200   Handle<Code> code = isolate->factory()->NewCode(
201       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
202 #ifdef OBJECT_PRINT
203   OFStream os(stdout);
204   code->Print(os);
205 #endif
206   F4 f = FUNCTION_CAST<F4>(code->entry());
207   int res = f(2.718281828);
208   ::printf("f() = %d\n", res);
209   CHECK_EQ(2, res);
210 }
211
212
213 static int baz = 42;
214 TEST(AssemblerIa325) {
215   CcTest::InitializeVM();
216   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
217   HandleScope scope(isolate);
218
219   v8::internal::byte buffer[256];
220   Assembler assm(isolate, buffer, sizeof buffer);
221
222   __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE32));
223   __ ret(0);
224
225   CodeDesc desc;
226   assm.GetCode(&desc);
227   Handle<Code> code = isolate->factory()->NewCode(
228       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
229   F0 f = FUNCTION_CAST<F0>(code->entry());
230   int res = f();
231   CHECK_EQ(42, res);
232 }
233
234
235 typedef double (*F5)(double x, double y);
236
237 TEST(AssemblerIa326) {
238   CcTest::InitializeVM();
239
240   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
241   HandleScope scope(isolate);
242   v8::internal::byte buffer[256];
243   Assembler assm(isolate, buffer, sizeof buffer);
244
245   __ movsd(xmm0, Operand(esp, 1 * kPointerSize));
246   __ movsd(xmm1, Operand(esp, 3 * kPointerSize));
247   __ addsd(xmm0, xmm1);
248   __ mulsd(xmm0, xmm1);
249   __ subsd(xmm0, xmm1);
250   __ divsd(xmm0, xmm1);
251   // Copy xmm0 to st(0) using eight bytes of stack.
252   __ sub(esp, Immediate(8));
253   __ movsd(Operand(esp, 0), xmm0);
254   __ fld_d(Operand(esp, 0));
255   __ add(esp, Immediate(8));
256   __ ret(0);
257
258   CodeDesc desc;
259   assm.GetCode(&desc);
260   Handle<Code> code = isolate->factory()->NewCode(
261       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
262 #ifdef OBJECT_PRINT
263   OFStream os(stdout);
264   code->Print(os);
265 #endif
266   F5 f = FUNCTION_CAST<F5>(code->entry());
267   double res = f(2.2, 1.1);
268   ::printf("f() = %f\n", res);
269   CHECK(2.29 < res && res < 2.31);
270 }
271
272
273 typedef double (*F6)(int x);
274
275 TEST(AssemblerIa328) {
276   CcTest::InitializeVM();
277
278   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
279   HandleScope scope(isolate);
280   v8::internal::byte buffer[256];
281   Assembler assm(isolate, buffer, sizeof buffer);
282   __ mov(eax, Operand(esp, 4));
283   __ cvtsi2sd(xmm0, eax);
284   // Copy xmm0 to st(0) using eight bytes of stack.
285   __ sub(esp, Immediate(8));
286   __ movsd(Operand(esp, 0), xmm0);
287   __ fld_d(Operand(esp, 0));
288   __ add(esp, Immediate(8));
289   __ ret(0);
290   CodeDesc desc;
291   assm.GetCode(&desc);
292   Handle<Code> code = isolate->factory()->NewCode(
293       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
294 #ifdef OBJECT_PRINT
295   OFStream os(stdout);
296   code->Print(os);
297 #endif
298   F6 f = FUNCTION_CAST<F6>(code->entry());
299   double res = f(12);
300
301   ::printf("f() = %f\n", res);
302   CHECK(11.99 < res && res < 12.001);
303 }
304
305
306 typedef int (*F7)(double x, double y);
307
308 TEST(AssemblerIa329) {
309   CcTest::InitializeVM();
310   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
311   HandleScope scope(isolate);
312   v8::internal::byte buffer[256];
313   MacroAssembler assm(isolate, buffer, sizeof buffer);
314   enum { kEqual = 0, kGreater = 1, kLess = 2, kNaN = 3, kUndefined = 4 };
315   Label equal_l, less_l, greater_l, nan_l;
316   __ fld_d(Operand(esp, 3 * kPointerSize));
317   __ fld_d(Operand(esp, 1 * kPointerSize));
318   __ FCmp();
319   __ j(parity_even, &nan_l);
320   __ j(equal, &equal_l);
321   __ j(below, &less_l);
322   __ j(above, &greater_l);
323
324   __ mov(eax, kUndefined);
325   __ ret(0);
326
327   __ bind(&equal_l);
328   __ mov(eax, kEqual);
329   __ ret(0);
330
331   __ bind(&greater_l);
332   __ mov(eax, kGreater);
333   __ ret(0);
334
335   __ bind(&less_l);
336   __ mov(eax, kLess);
337   __ ret(0);
338
339   __ bind(&nan_l);
340   __ mov(eax, kNaN);
341   __ ret(0);
342
343
344   CodeDesc desc;
345   assm.GetCode(&desc);
346   Handle<Code> code = isolate->factory()->NewCode(
347       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
348 #ifdef OBJECT_PRINT
349   OFStream os(stdout);
350   code->Print(os);
351 #endif
352
353   F7 f = FUNCTION_CAST<F7>(code->entry());
354   CHECK_EQ(kLess, f(1.1, 2.2));
355   CHECK_EQ(kEqual, f(2.2, 2.2));
356   CHECK_EQ(kGreater, f(3.3, 2.2));
357   CHECK_EQ(kNaN, f(v8::base::OS::nan_value(), 1.1));
358 }
359
360
361 TEST(AssemblerIa3210) {
362   // Test chaining of label usages within instructions (issue 1644).
363   CcTest::InitializeVM();
364   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
365   HandleScope scope(isolate);
366   Assembler assm(isolate, NULL, 0);
367
368   Label target;
369   __ j(equal, &target);
370   __ j(not_equal, &target);
371   __ bind(&target);
372   __ nop();
373 }
374
375
376 TEST(AssemblerMultiByteNop) {
377   CcTest::InitializeVM();
378   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
379   HandleScope scope(isolate);
380   v8::internal::byte buffer[1024];
381   Assembler assm(isolate, buffer, sizeof(buffer));
382   __ push(ebx);
383   __ push(ecx);
384   __ push(edx);
385   __ push(edi);
386   __ push(esi);
387   __ mov(eax, 1);
388   __ mov(ebx, 2);
389   __ mov(ecx, 3);
390   __ mov(edx, 4);
391   __ mov(edi, 5);
392   __ mov(esi, 6);
393   for (int i = 0; i < 16; i++) {
394     int before = assm.pc_offset();
395     __ Nop(i);
396     CHECK_EQ(assm.pc_offset() - before, i);
397   }
398
399   Label fail;
400   __ cmp(eax, 1);
401   __ j(not_equal, &fail);
402   __ cmp(ebx, 2);
403   __ j(not_equal, &fail);
404   __ cmp(ecx, 3);
405   __ j(not_equal, &fail);
406   __ cmp(edx, 4);
407   __ j(not_equal, &fail);
408   __ cmp(edi, 5);
409   __ j(not_equal, &fail);
410   __ cmp(esi, 6);
411   __ j(not_equal, &fail);
412   __ mov(eax, 42);
413   __ pop(esi);
414   __ pop(edi);
415   __ pop(edx);
416   __ pop(ecx);
417   __ pop(ebx);
418   __ ret(0);
419   __ bind(&fail);
420   __ mov(eax, 13);
421   __ pop(esi);
422   __ pop(edi);
423   __ pop(edx);
424   __ pop(ecx);
425   __ pop(ebx);
426   __ ret(0);
427
428   CodeDesc desc;
429   assm.GetCode(&desc);
430   Handle<Code> code = isolate->factory()->NewCode(
431       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
432   CHECK(code->IsCode());
433
434   F0 f = FUNCTION_CAST<F0>(code->entry());
435   int res = f();
436   CHECK_EQ(42, res);
437 }
438
439
440 #ifdef __GNUC__
441 #define ELEMENT_COUNT 4
442
443 void DoSSE2(const v8::FunctionCallbackInfo<v8::Value>& args) {
444   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
445   HandleScope scope(isolate);
446
447   CHECK(args[0]->IsArray());
448   v8::Local<v8::Array> vec = v8::Local<v8::Array>::Cast(args[0]);
449   CHECK_EQ(ELEMENT_COUNT, vec->Length());
450
451   v8::internal::byte buffer[256];
452   Assembler assm(isolate, buffer, sizeof buffer);
453
454   // Remove return address from the stack for fix stack frame alignment.
455   __ pop(ecx);
456
457   // Store input vector on the stack.
458   for (int i = 0; i < ELEMENT_COUNT; ++i) {
459     __ push(Immediate(vec->Get(i)->Int32Value()));
460   }
461
462   // Read vector into a xmm register.
463   __ pxor(xmm0, xmm0);
464   __ movdqa(xmm0, Operand(esp, 0));
465   // Create mask and store it in the return register.
466   __ movmskps(eax, xmm0);
467
468   // Remove unused data from the stack.
469   __ add(esp, Immediate(ELEMENT_COUNT * sizeof(int32_t)));
470   // Restore return address.
471   __ push(ecx);
472
473   __ ret(0);
474
475   CodeDesc desc;
476   assm.GetCode(&desc);
477
478   Handle<Code> code = isolate->factory()->NewCode(
479       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
480
481   F0 f = FUNCTION_CAST<F0>(code->entry());
482   int res = f();
483   args.GetReturnValue().Set(v8::Integer::New(CcTest::isolate(), res));
484 }
485
486
487 TEST(StackAlignmentForSSE2) {
488   CcTest::InitializeVM();
489   CHECK_EQ(0, v8::base::OS::ActivationFrameAlignment() % 16);
490
491   v8::Isolate* isolate = CcTest::isolate();
492   v8::HandleScope handle_scope(isolate);
493   v8::Handle<v8::ObjectTemplate> global_template =
494       v8::ObjectTemplate::New(isolate);
495   global_template->Set(v8_str("do_sse2"),
496                        v8::FunctionTemplate::New(isolate, DoSSE2));
497
498   LocalContext env(NULL, global_template);
499   CompileRun(
500       "function foo(vec) {"
501       "  return do_sse2(vec);"
502       "}");
503
504   v8::Local<v8::Object> global_object = env->Global();
505   v8::Local<v8::Function> foo =
506       v8::Local<v8::Function>::Cast(global_object->Get(v8_str("foo")));
507
508   int32_t vec[ELEMENT_COUNT] = { -1, 1, 1, 1 };
509   v8::Local<v8::Array> v8_vec = v8::Array::New(isolate, ELEMENT_COUNT);
510   for (int i = 0; i < ELEMENT_COUNT; i++) {
511       v8_vec->Set(i, v8_num(vec[i]));
512   }
513
514   v8::Local<v8::Value> args[] = { v8_vec };
515   v8::Local<v8::Value> result = foo->Call(global_object, 1, args);
516
517   // The mask should be 0b1000.
518   CHECK_EQ(8, result->Int32Value());
519 }
520
521 #undef ELEMENT_COUNT
522 #endif  // __GNUC__
523
524
525 TEST(AssemblerIa32Extractps) {
526   CcTest::InitializeVM();
527   if (!CpuFeatures::IsSupported(SSE4_1)) return;
528
529   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
530   HandleScope scope(isolate);
531   v8::internal::byte buffer[256];
532   MacroAssembler assm(isolate, buffer, sizeof buffer);
533   { CpuFeatureScope fscope41(&assm, SSE4_1);
534     __ movsd(xmm1, Operand(esp, 4));
535     __ extractps(eax, xmm1, 0x1);
536     __ ret(0);
537   }
538
539   CodeDesc desc;
540   assm.GetCode(&desc);
541   Handle<Code> code = isolate->factory()->NewCode(
542       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
543 #ifdef OBJECT_PRINT
544   OFStream os(stdout);
545   code->Print(os);
546 #endif
547
548   F4 f = FUNCTION_CAST<F4>(code->entry());
549   uint64_t value1 = V8_2PART_UINT64_C(0x12345678, 87654321);
550   CHECK_EQ(0x12345678, f(uint64_to_double(value1)));
551   uint64_t value2 = V8_2PART_UINT64_C(0x87654321, 12345678);
552   CHECK_EQ(0x87654321, f(uint64_to_double(value2)));
553 }
554
555
556 typedef int (*F8)(float x, float y);
557 TEST(AssemblerIa32SSE) {
558   CcTest::InitializeVM();
559
560   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
561   HandleScope scope(isolate);
562   v8::internal::byte buffer[256];
563   MacroAssembler assm(isolate, buffer, sizeof buffer);
564   {
565     __ movss(xmm0, Operand(esp, kPointerSize));
566     __ movss(xmm1, Operand(esp, 2 * kPointerSize));
567     __ shufps(xmm0, xmm0, 0x0);
568     __ shufps(xmm1, xmm1, 0x0);
569     __ movaps(xmm2, xmm1);
570     __ addps(xmm2, xmm0);
571     __ mulps(xmm2, xmm1);
572     __ subps(xmm2, xmm0);
573     __ divps(xmm2, xmm1);
574     __ cvttss2si(eax, xmm2);
575     __ ret(0);
576   }
577
578   CodeDesc desc;
579   assm.GetCode(&desc);
580   Handle<Code> code = isolate->factory()->NewCode(
581       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
582 #ifdef OBJECT_PRINT
583   OFStream os(stdout);
584   code->Print(os);
585 #endif
586
587   F8 f = FUNCTION_CAST<F8>(code->entry());
588   CHECK_EQ(2, f(1.0, 2.0));
589 }
590
591
592 #undef __