deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / 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 "test/cctest/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 #define __ assm.
48
49 TEST(AssemblerIa320) {
50   CcTest::InitializeVM();
51   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
52   HandleScope scope(isolate);
53
54   v8::internal::byte buffer[256];
55   Assembler assm(isolate, buffer, sizeof buffer);
56
57   __ mov(eax, Operand(esp, 4));
58   __ add(eax, Operand(esp, 8));
59   __ ret(0);
60
61   CodeDesc desc;
62   assm.GetCode(&desc);
63   Handle<Code> code = isolate->factory()->NewCode(
64       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
65 #ifdef OBJECT_PRINT
66   OFStream os(stdout);
67   code->Print(os);
68 #endif
69   F2 f = FUNCTION_CAST<F2>(code->entry());
70   int res = f(3, 4);
71   ::printf("f() = %d\n", res);
72   CHECK_EQ(7, res);
73 }
74
75
76 TEST(AssemblerIa321) {
77   CcTest::InitializeVM();
78   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
79   HandleScope scope(isolate);
80
81   v8::internal::byte buffer[256];
82   Assembler assm(isolate, buffer, sizeof buffer);
83   Label L, C;
84
85   __ mov(edx, Operand(esp, 4));
86   __ xor_(eax, eax);  // clear eax
87   __ jmp(&C);
88
89   __ bind(&L);
90   __ add(eax, edx);
91   __ sub(edx, Immediate(1));
92
93   __ bind(&C);
94   __ test(edx, edx);
95   __ j(not_zero, &L);
96   __ ret(0);
97
98   CodeDesc desc;
99   assm.GetCode(&desc);
100   Handle<Code> code = isolate->factory()->NewCode(
101       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
102 #ifdef OBJECT_PRINT
103   OFStream os(stdout);
104   code->Print(os);
105 #endif
106   F1 f = FUNCTION_CAST<F1>(code->entry());
107   int res = f(100);
108   ::printf("f() = %d\n", res);
109   CHECK_EQ(5050, res);
110 }
111
112
113 TEST(AssemblerIa322) {
114   CcTest::InitializeVM();
115   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
116   HandleScope scope(isolate);
117
118   v8::internal::byte buffer[256];
119   Assembler assm(isolate, buffer, sizeof buffer);
120   Label L, C;
121
122   __ mov(edx, Operand(esp, 4));
123   __ mov(eax, 1);
124   __ jmp(&C);
125
126   __ bind(&L);
127   __ imul(eax, edx);
128   __ sub(edx, Immediate(1));
129
130   __ bind(&C);
131   __ test(edx, edx);
132   __ j(not_zero, &L);
133   __ ret(0);
134
135   // some relocated stuff here, not executed
136   __ mov(eax, isolate->factory()->true_value());
137   __ jmp(NULL, RelocInfo::RUNTIME_ENTRY);
138
139   CodeDesc desc;
140   assm.GetCode(&desc);
141   Handle<Code> code = isolate->factory()->NewCode(
142       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
143 #ifdef OBJECT_PRINT
144   OFStream os(stdout);
145   code->Print(os);
146 #endif
147   F1 f = FUNCTION_CAST<F1>(code->entry());
148   int res = f(10);
149   ::printf("f() = %d\n", res);
150   CHECK_EQ(3628800, res);
151 }
152
153
154 typedef int (*F3)(float x);
155
156 TEST(AssemblerIa323) {
157   CcTest::InitializeVM();
158
159   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
160   HandleScope scope(isolate);
161
162   v8::internal::byte buffer[256];
163   Assembler assm(isolate, buffer, sizeof buffer);
164
165   __ cvttss2si(eax, Operand(esp, 4));
166   __ ret(0);
167
168   CodeDesc desc;
169   assm.GetCode(&desc);
170   Handle<Code> code = isolate->factory()->NewCode(
171       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
172 #ifdef OBJECT_PRINT
173   OFStream os(stdout);
174   code->Print(os);
175 #endif
176   F3 f = FUNCTION_CAST<F3>(code->entry());
177   int res = f(static_cast<float>(-3.1415));
178   ::printf("f() = %d\n", res);
179   CHECK_EQ(-3, res);
180 }
181
182
183 typedef int (*F4)(double x);
184
185 TEST(AssemblerIa324) {
186   CcTest::InitializeVM();
187
188   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
189   HandleScope scope(isolate);
190
191   v8::internal::byte buffer[256];
192   Assembler assm(isolate, buffer, sizeof buffer);
193
194   __ cvttsd2si(eax, Operand(esp, 4));
195   __ ret(0);
196
197   CodeDesc desc;
198   assm.GetCode(&desc);
199   Handle<Code> code = isolate->factory()->NewCode(
200       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
201 #ifdef OBJECT_PRINT
202   OFStream os(stdout);
203   code->Print(os);
204 #endif
205   F4 f = FUNCTION_CAST<F4>(code->entry());
206   int res = f(2.718281828);
207   ::printf("f() = %d\n", res);
208   CHECK_EQ(2, res);
209 }
210
211
212 static int baz = 42;
213 TEST(AssemblerIa325) {
214   CcTest::InitializeVM();
215   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
216   HandleScope scope(isolate);
217
218   v8::internal::byte buffer[256];
219   Assembler assm(isolate, buffer, sizeof buffer);
220
221   __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE32));
222   __ ret(0);
223
224   CodeDesc desc;
225   assm.GetCode(&desc);
226   Handle<Code> code = isolate->factory()->NewCode(
227       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
228   F0 f = FUNCTION_CAST<F0>(code->entry());
229   int res = f();
230   CHECK_EQ(42, res);
231 }
232
233
234 typedef double (*F5)(double x, double y);
235
236 TEST(AssemblerIa326) {
237   CcTest::InitializeVM();
238
239   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
240   HandleScope scope(isolate);
241   v8::internal::byte buffer[256];
242   Assembler assm(isolate, buffer, sizeof buffer);
243
244   __ movsd(xmm0, Operand(esp, 1 * kPointerSize));
245   __ movsd(xmm1, Operand(esp, 3 * kPointerSize));
246   __ addsd(xmm0, xmm1);
247   __ mulsd(xmm0, xmm1);
248   __ subsd(xmm0, xmm1);
249   __ divsd(xmm0, xmm1);
250   // Copy xmm0 to st(0) using eight bytes of stack.
251   __ sub(esp, Immediate(8));
252   __ movsd(Operand(esp, 0), xmm0);
253   __ fld_d(Operand(esp, 0));
254   __ add(esp, Immediate(8));
255   __ ret(0);
256
257   CodeDesc desc;
258   assm.GetCode(&desc);
259   Handle<Code> code = isolate->factory()->NewCode(
260       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
261 #ifdef OBJECT_PRINT
262   OFStream os(stdout);
263   code->Print(os);
264 #endif
265   F5 f = FUNCTION_CAST<F5>(code->entry());
266   double res = f(2.2, 1.1);
267   ::printf("f() = %f\n", res);
268   CHECK(2.29 < res && res < 2.31);
269 }
270
271
272 typedef double (*F6)(int x);
273
274 TEST(AssemblerIa328) {
275   CcTest::InitializeVM();
276
277   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
278   HandleScope scope(isolate);
279   v8::internal::byte buffer[256];
280   Assembler assm(isolate, buffer, sizeof buffer);
281   __ mov(eax, Operand(esp, 4));
282   __ cvtsi2sd(xmm0, eax);
283   // Copy xmm0 to st(0) using eight bytes of stack.
284   __ sub(esp, Immediate(8));
285   __ movsd(Operand(esp, 0), xmm0);
286   __ fld_d(Operand(esp, 0));
287   __ add(esp, Immediate(8));
288   __ ret(0);
289   CodeDesc desc;
290   assm.GetCode(&desc);
291   Handle<Code> code = isolate->factory()->NewCode(
292       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
293 #ifdef OBJECT_PRINT
294   OFStream os(stdout);
295   code->Print(os);
296 #endif
297   F6 f = FUNCTION_CAST<F6>(code->entry());
298   double res = f(12);
299
300   ::printf("f() = %f\n", res);
301   CHECK(11.99 < res && res < 12.001);
302 }
303
304
305 typedef int (*F7)(double x, double y);
306
307 TEST(AssemblerIa329) {
308   CcTest::InitializeVM();
309   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
310   HandleScope scope(isolate);
311   v8::internal::byte buffer[256];
312   MacroAssembler assm(isolate, buffer, sizeof buffer);
313   enum { kEqual = 0, kGreater = 1, kLess = 2, kNaN = 3, kUndefined = 4 };
314   Label equal_l, less_l, greater_l, nan_l;
315   __ fld_d(Operand(esp, 3 * kPointerSize));
316   __ fld_d(Operand(esp, 1 * kPointerSize));
317   __ FCmp();
318   __ j(parity_even, &nan_l);
319   __ j(equal, &equal_l);
320   __ j(below, &less_l);
321   __ j(above, &greater_l);
322
323   __ mov(eax, kUndefined);
324   __ ret(0);
325
326   __ bind(&equal_l);
327   __ mov(eax, kEqual);
328   __ ret(0);
329
330   __ bind(&greater_l);
331   __ mov(eax, kGreater);
332   __ ret(0);
333
334   __ bind(&less_l);
335   __ mov(eax, kLess);
336   __ ret(0);
337
338   __ bind(&nan_l);
339   __ mov(eax, kNaN);
340   __ ret(0);
341
342
343   CodeDesc desc;
344   assm.GetCode(&desc);
345   Handle<Code> code = isolate->factory()->NewCode(
346       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
347 #ifdef OBJECT_PRINT
348   OFStream os(stdout);
349   code->Print(os);
350 #endif
351
352   F7 f = FUNCTION_CAST<F7>(code->entry());
353   CHECK_EQ(kLess, f(1.1, 2.2));
354   CHECK_EQ(kEqual, f(2.2, 2.2));
355   CHECK_EQ(kGreater, f(3.3, 2.2));
356   CHECK_EQ(kNaN, f(std::numeric_limits<double>::quiet_NaN(), 1.1));
357 }
358
359
360 TEST(AssemblerIa3210) {
361   // Test chaining of label usages within instructions (issue 1644).
362   CcTest::InitializeVM();
363   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
364   HandleScope scope(isolate);
365   Assembler assm(isolate, NULL, 0);
366
367   Label target;
368   __ j(equal, &target);
369   __ j(not_equal, &target);
370   __ bind(&target);
371   __ nop();
372 }
373
374
375 TEST(AssemblerMultiByteNop) {
376   CcTest::InitializeVM();
377   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
378   HandleScope scope(isolate);
379   v8::internal::byte buffer[1024];
380   Assembler assm(isolate, buffer, sizeof(buffer));
381   __ push(ebx);
382   __ push(ecx);
383   __ push(edx);
384   __ push(edi);
385   __ push(esi);
386   __ mov(eax, 1);
387   __ mov(ebx, 2);
388   __ mov(ecx, 3);
389   __ mov(edx, 4);
390   __ mov(edi, 5);
391   __ mov(esi, 6);
392   for (int i = 0; i < 16; i++) {
393     int before = assm.pc_offset();
394     __ Nop(i);
395     CHECK_EQ(assm.pc_offset() - before, i);
396   }
397
398   Label fail;
399   __ cmp(eax, 1);
400   __ j(not_equal, &fail);
401   __ cmp(ebx, 2);
402   __ j(not_equal, &fail);
403   __ cmp(ecx, 3);
404   __ j(not_equal, &fail);
405   __ cmp(edx, 4);
406   __ j(not_equal, &fail);
407   __ cmp(edi, 5);
408   __ j(not_equal, &fail);
409   __ cmp(esi, 6);
410   __ j(not_equal, &fail);
411   __ mov(eax, 42);
412   __ pop(esi);
413   __ pop(edi);
414   __ pop(edx);
415   __ pop(ecx);
416   __ pop(ebx);
417   __ ret(0);
418   __ bind(&fail);
419   __ mov(eax, 13);
420   __ pop(esi);
421   __ pop(edi);
422   __ pop(edx);
423   __ pop(ecx);
424   __ pop(ebx);
425   __ ret(0);
426
427   CodeDesc desc;
428   assm.GetCode(&desc);
429   Handle<Code> code = isolate->factory()->NewCode(
430       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
431   CHECK(code->IsCode());
432
433   F0 f = FUNCTION_CAST<F0>(code->entry());
434   int res = f();
435   CHECK_EQ(42, res);
436 }
437
438
439 #ifdef __GNUC__
440 #define ELEMENT_COUNT 4u
441
442 void DoSSE2(const v8::FunctionCallbackInfo<v8::Value>& args) {
443   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
444   HandleScope scope(isolate);
445
446   CHECK(args[0]->IsArray());
447   v8::Local<v8::Array> vec = v8::Local<v8::Array>::Cast(args[0]);
448   CHECK_EQ(ELEMENT_COUNT, vec->Length());
449
450   v8::internal::byte buffer[256];
451   Assembler assm(isolate, buffer, sizeof buffer);
452
453   // Remove return address from the stack for fix stack frame alignment.
454   __ pop(ecx);
455
456   // Store input vector on the stack.
457   for (unsigned i = 0; i < ELEMENT_COUNT; ++i) {
458     __ push(Immediate(vec->Get(i)->Int32Value()));
459   }
460
461   // Read vector into a xmm register.
462   __ pxor(xmm0, xmm0);
463   __ movdqa(xmm0, Operand(esp, 0));
464   // Create mask and store it in the return register.
465   __ movmskps(eax, xmm0);
466
467   // Remove unused data from the stack.
468   __ add(esp, Immediate(ELEMENT_COUNT * sizeof(int32_t)));
469   // Restore return address.
470   __ push(ecx);
471
472   __ ret(0);
473
474   CodeDesc desc;
475   assm.GetCode(&desc);
476
477   Handle<Code> code = isolate->factory()->NewCode(
478       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
479
480   F0 f = FUNCTION_CAST<F0>(code->entry());
481   int res = f();
482   args.GetReturnValue().Set(v8::Integer::New(CcTest::isolate(), res));
483 }
484
485
486 TEST(StackAlignmentForSSE2) {
487   CcTest::InitializeVM();
488   CHECK_EQ(0, v8::base::OS::ActivationFrameAlignment() % 16);
489
490   v8::Isolate* isolate = CcTest::isolate();
491   v8::HandleScope handle_scope(isolate);
492   v8::Handle<v8::ObjectTemplate> global_template =
493       v8::ObjectTemplate::New(isolate);
494   global_template->Set(v8_str("do_sse2"),
495                        v8::FunctionTemplate::New(isolate, DoSSE2));
496
497   LocalContext env(NULL, global_template);
498   CompileRun(
499       "function foo(vec) {"
500       "  return do_sse2(vec);"
501       "}");
502
503   v8::Local<v8::Object> global_object = env->Global();
504   v8::Local<v8::Function> foo =
505       v8::Local<v8::Function>::Cast(global_object->Get(v8_str("foo")));
506
507   int32_t vec[ELEMENT_COUNT] = { -1, 1, 1, 1 };
508   v8::Local<v8::Array> v8_vec = v8::Array::New(isolate, ELEMENT_COUNT);
509   for (unsigned i = 0; i < ELEMENT_COUNT; i++) {
510       v8_vec->Set(i, v8_num(vec[i]));
511   }
512
513   v8::Local<v8::Value> args[] = { v8_vec };
514   v8::Local<v8::Value> result = foo->Call(global_object, 1, args);
515
516   // The mask should be 0b1000.
517   CHECK_EQ(8, result->Int32Value());
518 }
519
520 #undef ELEMENT_COUNT
521 #endif  // __GNUC__
522
523
524 TEST(AssemblerIa32Extractps) {
525   CcTest::InitializeVM();
526   if (!CpuFeatures::IsSupported(SSE4_1)) return;
527
528   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
529   HandleScope scope(isolate);
530   v8::internal::byte buffer[256];
531   MacroAssembler assm(isolate, buffer, sizeof buffer);
532   { CpuFeatureScope fscope41(&assm, SSE4_1);
533     __ movsd(xmm1, Operand(esp, 4));
534     __ extractps(eax, xmm1, 0x1);
535     __ ret(0);
536   }
537
538   CodeDesc desc;
539   assm.GetCode(&desc);
540   Handle<Code> code = isolate->factory()->NewCode(
541       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
542 #ifdef OBJECT_PRINT
543   OFStream os(stdout);
544   code->Print(os);
545 #endif
546
547   F4 f = FUNCTION_CAST<F4>(code->entry());
548   uint64_t value1 = V8_2PART_UINT64_C(0x12345678, 87654321);
549   CHECK_EQ(0x12345678, f(uint64_to_double(value1)));
550   uint64_t value2 = V8_2PART_UINT64_C(0x87654321, 12345678);
551   CHECK_EQ(static_cast<int>(0x87654321), f(uint64_to_double(value2)));
552 }
553
554
555 typedef int (*F8)(float x, float y);
556 TEST(AssemblerIa32SSE) {
557   CcTest::InitializeVM();
558
559   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
560   HandleScope scope(isolate);
561   v8::internal::byte buffer[256];
562   MacroAssembler assm(isolate, buffer, sizeof buffer);
563   {
564     __ movss(xmm0, Operand(esp, kPointerSize));
565     __ movss(xmm1, Operand(esp, 2 * kPointerSize));
566     __ shufps(xmm0, xmm0, 0x0);
567     __ shufps(xmm1, xmm1, 0x0);
568     __ movaps(xmm2, xmm1);
569     __ addps(xmm2, xmm0);
570     __ mulps(xmm2, xmm1);
571     __ subps(xmm2, xmm0);
572     __ divps(xmm2, xmm1);
573     __ cvttss2si(eax, xmm2);
574     __ ret(0);
575   }
576
577   CodeDesc desc;
578   assm.GetCode(&desc);
579   Handle<Code> code = isolate->factory()->NewCode(
580       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
581 #ifdef OBJECT_PRINT
582   OFStream os(stdout);
583   code->Print(os);
584 #endif
585
586   F8 f = FUNCTION_CAST<F8>(code->entry());
587   CHECK_EQ(2, f(1.0, 2.0));
588 }
589
590
591 typedef int (*F9)(double x, double y, double z);
592 TEST(AssemblerX64FMA_sd) {
593   CcTest::InitializeVM();
594   if (!CpuFeatures::IsSupported(FMA3)) return;
595
596   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
597   HandleScope scope(isolate);
598   v8::internal::byte buffer[1024];
599   MacroAssembler assm(isolate, buffer, sizeof buffer);
600   {
601     CpuFeatureScope fscope(&assm, FMA3);
602     Label exit;
603     __ movsd(xmm0, Operand(esp, 1 * kPointerSize));
604     __ movsd(xmm1, Operand(esp, 3 * kPointerSize));
605     __ movsd(xmm2, Operand(esp, 5 * kPointerSize));
606     // argument in xmm0, xmm1 and xmm2
607     // xmm0 * xmm1 + xmm2
608     __ movaps(xmm3, xmm0);
609     __ mulsd(xmm3, xmm1);
610     __ addsd(xmm3, xmm2);  // Expected result in xmm3
611
612     __ sub(esp, Immediate(kDoubleSize));  // For memory operand
613     // vfmadd132sd
614     __ mov(eax, Immediate(1));  // Test number
615     __ movaps(xmm4, xmm0);
616     __ vfmadd132sd(xmm4, xmm2, xmm1);
617     __ ucomisd(xmm4, xmm3);
618     __ j(not_equal, &exit);
619     // vfmadd213sd
620     __ inc(eax);
621     __ movaps(xmm4, xmm1);
622     __ vfmadd213sd(xmm4, xmm0, xmm2);
623     __ ucomisd(xmm4, xmm3);
624     __ j(not_equal, &exit);
625     // vfmadd231sd
626     __ inc(eax);
627     __ movaps(xmm4, xmm2);
628     __ vfmadd231sd(xmm4, xmm0, xmm1);
629     __ ucomisd(xmm4, xmm3);
630     __ j(not_equal, &exit);
631
632     // vfmadd132sd
633     __ inc(eax);
634     __ movaps(xmm4, xmm0);
635     __ movsd(Operand(esp, 0), xmm1);
636     __ vfmadd132sd(xmm4, xmm2, Operand(esp, 0));
637     __ ucomisd(xmm4, xmm3);
638     __ j(not_equal, &exit);
639     // vfmadd213sd
640     __ inc(eax);
641     __ movaps(xmm4, xmm1);
642     __ movsd(Operand(esp, 0), xmm2);
643     __ vfmadd213sd(xmm4, xmm0, Operand(esp, 0));
644     __ ucomisd(xmm4, xmm3);
645     __ j(not_equal, &exit);
646     // vfmadd231sd
647     __ inc(eax);
648     __ movaps(xmm4, xmm2);
649     __ movsd(Operand(esp, 0), xmm1);
650     __ vfmadd231sd(xmm4, xmm0, Operand(esp, 0));
651     __ ucomisd(xmm4, xmm3);
652     __ j(not_equal, &exit);
653
654     // xmm0 * xmm1 - xmm2
655     __ movaps(xmm3, xmm0);
656     __ mulsd(xmm3, xmm1);
657     __ subsd(xmm3, xmm2);  // Expected result in xmm3
658
659     // vfmsub132sd
660     __ inc(eax);
661     __ movaps(xmm4, xmm0);
662     __ vfmsub132sd(xmm4, xmm2, xmm1);
663     __ ucomisd(xmm4, xmm3);
664     __ j(not_equal, &exit);
665     // vfmadd213sd
666     __ inc(eax);
667     __ movaps(xmm4, xmm1);
668     __ vfmsub213sd(xmm4, xmm0, xmm2);
669     __ ucomisd(xmm4, xmm3);
670     __ j(not_equal, &exit);
671     // vfmsub231sd
672     __ inc(eax);
673     __ movaps(xmm4, xmm2);
674     __ vfmsub231sd(xmm4, xmm0, xmm1);
675     __ ucomisd(xmm4, xmm3);
676     __ j(not_equal, &exit);
677
678     // vfmsub132sd
679     __ inc(eax);
680     __ movaps(xmm4, xmm0);
681     __ movsd(Operand(esp, 0), xmm1);
682     __ vfmsub132sd(xmm4, xmm2, Operand(esp, 0));
683     __ ucomisd(xmm4, xmm3);
684     __ j(not_equal, &exit);
685     // vfmsub213sd
686     __ inc(eax);
687     __ movaps(xmm4, xmm1);
688     __ movsd(Operand(esp, 0), xmm2);
689     __ vfmsub213sd(xmm4, xmm0, Operand(esp, 0));
690     __ ucomisd(xmm4, xmm3);
691     __ j(not_equal, &exit);
692     // vfmsub231sd
693     __ inc(eax);
694     __ movaps(xmm4, xmm2);
695     __ movsd(Operand(esp, 0), xmm1);
696     __ vfmsub231sd(xmm4, xmm0, Operand(esp, 0));
697     __ ucomisd(xmm4, xmm3);
698     __ j(not_equal, &exit);
699
700
701     // - xmm0 * xmm1 + xmm2
702     __ movaps(xmm3, xmm0);
703     __ mulsd(xmm3, xmm1);
704     __ Move(xmm4, (uint64_t)1 << 63);
705     __ xorpd(xmm3, xmm4);
706     __ addsd(xmm3, xmm2);  // Expected result in xmm3
707
708     // vfnmadd132sd
709     __ inc(eax);
710     __ movaps(xmm4, xmm0);
711     __ vfnmadd132sd(xmm4, xmm2, xmm1);
712     __ ucomisd(xmm4, xmm3);
713     __ j(not_equal, &exit);
714     // vfmadd213sd
715     __ inc(eax);
716     __ movaps(xmm4, xmm1);
717     __ vfnmadd213sd(xmm4, xmm0, xmm2);
718     __ ucomisd(xmm4, xmm3);
719     __ j(not_equal, &exit);
720     // vfnmadd231sd
721     __ inc(eax);
722     __ movaps(xmm4, xmm2);
723     __ vfnmadd231sd(xmm4, xmm0, xmm1);
724     __ ucomisd(xmm4, xmm3);
725     __ j(not_equal, &exit);
726
727     // vfnmadd132sd
728     __ inc(eax);
729     __ movaps(xmm4, xmm0);
730     __ movsd(Operand(esp, 0), xmm1);
731     __ vfnmadd132sd(xmm4, xmm2, Operand(esp, 0));
732     __ ucomisd(xmm4, xmm3);
733     __ j(not_equal, &exit);
734     // vfnmadd213sd
735     __ inc(eax);
736     __ movaps(xmm4, xmm1);
737     __ movsd(Operand(esp, 0), xmm2);
738     __ vfnmadd213sd(xmm4, xmm0, Operand(esp, 0));
739     __ ucomisd(xmm4, xmm3);
740     __ j(not_equal, &exit);
741     // vfnmadd231sd
742     __ inc(eax);
743     __ movaps(xmm4, xmm2);
744     __ movsd(Operand(esp, 0), xmm1);
745     __ vfnmadd231sd(xmm4, xmm0, Operand(esp, 0));
746     __ ucomisd(xmm4, xmm3);
747     __ j(not_equal, &exit);
748
749
750     // - xmm0 * xmm1 - xmm2
751     __ movaps(xmm3, xmm0);
752     __ mulsd(xmm3, xmm1);
753     __ Move(xmm4, (uint64_t)1 << 63);
754     __ xorpd(xmm3, xmm4);
755     __ subsd(xmm3, xmm2);  // Expected result in xmm3
756
757     // vfnmsub132sd
758     __ inc(eax);
759     __ movaps(xmm4, xmm0);
760     __ vfnmsub132sd(xmm4, xmm2, xmm1);
761     __ ucomisd(xmm4, xmm3);
762     __ j(not_equal, &exit);
763     // vfmsub213sd
764     __ inc(eax);
765     __ movaps(xmm4, xmm1);
766     __ vfnmsub213sd(xmm4, xmm0, xmm2);
767     __ ucomisd(xmm4, xmm3);
768     __ j(not_equal, &exit);
769     // vfnmsub231sd
770     __ inc(eax);
771     __ movaps(xmm4, xmm2);
772     __ vfnmsub231sd(xmm4, xmm0, xmm1);
773     __ ucomisd(xmm4, xmm3);
774     __ j(not_equal, &exit);
775
776     // vfnmsub132sd
777     __ inc(eax);
778     __ movaps(xmm4, xmm0);
779     __ movsd(Operand(esp, 0), xmm1);
780     __ vfnmsub132sd(xmm4, xmm2, Operand(esp, 0));
781     __ ucomisd(xmm4, xmm3);
782     __ j(not_equal, &exit);
783     // vfnmsub213sd
784     __ inc(eax);
785     __ movaps(xmm4, xmm1);
786     __ movsd(Operand(esp, 0), xmm2);
787     __ vfnmsub213sd(xmm4, xmm0, Operand(esp, 0));
788     __ ucomisd(xmm4, xmm3);
789     __ j(not_equal, &exit);
790     // vfnmsub231sd
791     __ inc(eax);
792     __ movaps(xmm4, xmm2);
793     __ movsd(Operand(esp, 0), xmm1);
794     __ vfnmsub231sd(xmm4, xmm0, Operand(esp, 0));
795     __ ucomisd(xmm4, xmm3);
796     __ j(not_equal, &exit);
797
798
799     __ xor_(eax, eax);
800     __ bind(&exit);
801     __ add(esp, Immediate(kDoubleSize));
802     __ ret(0);
803   }
804
805   CodeDesc desc;
806   assm.GetCode(&desc);
807   Handle<Code> code = isolate->factory()->NewCode(
808       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
809 #ifdef OBJECT_PRINT
810   OFStream os(stdout);
811   code->Print(os);
812 #endif
813
814   F9 f = FUNCTION_CAST<F9>(code->entry());
815   CHECK_EQ(0, f(0.000092662107262076, -2.460774966188315, -1.0958787393627414));
816 }
817
818
819 typedef int (*F10)(float x, float y, float z);
820 TEST(AssemblerX64FMA_ss) {
821   CcTest::InitializeVM();
822   if (!CpuFeatures::IsSupported(FMA3)) return;
823
824   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
825   HandleScope scope(isolate);
826   v8::internal::byte buffer[1024];
827   MacroAssembler assm(isolate, buffer, sizeof buffer);
828   {
829     CpuFeatureScope fscope(&assm, FMA3);
830     Label exit;
831     __ movss(xmm0, Operand(esp, 1 * kPointerSize));
832     __ movss(xmm1, Operand(esp, 2 * kPointerSize));
833     __ movss(xmm2, Operand(esp, 3 * kPointerSize));
834     // arguments in xmm0, xmm1 and xmm2
835     // xmm0 * xmm1 + xmm2
836     __ movaps(xmm3, xmm0);
837     __ mulss(xmm3, xmm1);
838     __ addss(xmm3, xmm2);  // Expected result in xmm3
839
840     __ sub(esp, Immediate(kDoubleSize));  // For memory operand
841     // vfmadd132ss
842     __ mov(eax, Immediate(1));  // Test number
843     __ movaps(xmm4, xmm0);
844     __ vfmadd132ss(xmm4, xmm2, xmm1);
845     __ ucomiss(xmm4, xmm3);
846     __ j(not_equal, &exit);
847     // vfmadd213ss
848     __ inc(eax);
849     __ movaps(xmm4, xmm1);
850     __ vfmadd213ss(xmm4, xmm0, xmm2);
851     __ ucomiss(xmm4, xmm3);
852     __ j(not_equal, &exit);
853     // vfmadd231ss
854     __ inc(eax);
855     __ movaps(xmm4, xmm2);
856     __ vfmadd231ss(xmm4, xmm0, xmm1);
857     __ ucomiss(xmm4, xmm3);
858     __ j(not_equal, &exit);
859
860     // vfmadd132ss
861     __ inc(eax);
862     __ movaps(xmm4, xmm0);
863     __ movss(Operand(esp, 0), xmm1);
864     __ vfmadd132ss(xmm4, xmm2, Operand(esp, 0));
865     __ ucomiss(xmm4, xmm3);
866     __ j(not_equal, &exit);
867     // vfmadd213ss
868     __ inc(eax);
869     __ movaps(xmm4, xmm1);
870     __ movss(Operand(esp, 0), xmm2);
871     __ vfmadd213ss(xmm4, xmm0, Operand(esp, 0));
872     __ ucomiss(xmm4, xmm3);
873     __ j(not_equal, &exit);
874     // vfmadd231ss
875     __ inc(eax);
876     __ movaps(xmm4, xmm2);
877     __ movss(Operand(esp, 0), xmm1);
878     __ vfmadd231ss(xmm4, xmm0, Operand(esp, 0));
879     __ ucomiss(xmm4, xmm3);
880     __ j(not_equal, &exit);
881
882     // xmm0 * xmm1 - xmm2
883     __ movaps(xmm3, xmm0);
884     __ mulss(xmm3, xmm1);
885     __ subss(xmm3, xmm2);  // Expected result in xmm3
886
887     // vfmsub132ss
888     __ inc(eax);
889     __ movaps(xmm4, xmm0);
890     __ vfmsub132ss(xmm4, xmm2, xmm1);
891     __ ucomiss(xmm4, xmm3);
892     __ j(not_equal, &exit);
893     // vfmadd213ss
894     __ inc(eax);
895     __ movaps(xmm4, xmm1);
896     __ vfmsub213ss(xmm4, xmm0, xmm2);
897     __ ucomiss(xmm4, xmm3);
898     __ j(not_equal, &exit);
899     // vfmsub231ss
900     __ inc(eax);
901     __ movaps(xmm4, xmm2);
902     __ vfmsub231ss(xmm4, xmm0, xmm1);
903     __ ucomiss(xmm4, xmm3);
904     __ j(not_equal, &exit);
905
906     // vfmsub132ss
907     __ inc(eax);
908     __ movaps(xmm4, xmm0);
909     __ movss(Operand(esp, 0), xmm1);
910     __ vfmsub132ss(xmm4, xmm2, Operand(esp, 0));
911     __ ucomiss(xmm4, xmm3);
912     __ j(not_equal, &exit);
913     // vfmsub213ss
914     __ inc(eax);
915     __ movaps(xmm4, xmm1);
916     __ movss(Operand(esp, 0), xmm2);
917     __ vfmsub213ss(xmm4, xmm0, Operand(esp, 0));
918     __ ucomiss(xmm4, xmm3);
919     __ j(not_equal, &exit);
920     // vfmsub231ss
921     __ inc(eax);
922     __ movaps(xmm4, xmm2);
923     __ movss(Operand(esp, 0), xmm1);
924     __ vfmsub231ss(xmm4, xmm0, Operand(esp, 0));
925     __ ucomiss(xmm4, xmm3);
926     __ j(not_equal, &exit);
927
928
929     // - xmm0 * xmm1 + xmm2
930     __ movaps(xmm3, xmm0);
931     __ mulss(xmm3, xmm1);
932     __ Move(xmm4, (uint32_t)1 << 31);
933     __ xorps(xmm3, xmm4);
934     __ addss(xmm3, xmm2);  // Expected result in xmm3
935
936     // vfnmadd132ss
937     __ inc(eax);
938     __ movaps(xmm4, xmm0);
939     __ vfnmadd132ss(xmm4, xmm2, xmm1);
940     __ ucomiss(xmm4, xmm3);
941     __ j(not_equal, &exit);
942     // vfmadd213ss
943     __ inc(eax);
944     __ movaps(xmm4, xmm1);
945     __ vfnmadd213ss(xmm4, xmm0, xmm2);
946     __ ucomiss(xmm4, xmm3);
947     __ j(not_equal, &exit);
948     // vfnmadd231ss
949     __ inc(eax);
950     __ movaps(xmm4, xmm2);
951     __ vfnmadd231ss(xmm4, xmm0, xmm1);
952     __ ucomiss(xmm4, xmm3);
953     __ j(not_equal, &exit);
954
955     // vfnmadd132ss
956     __ inc(eax);
957     __ movaps(xmm4, xmm0);
958     __ movss(Operand(esp, 0), xmm1);
959     __ vfnmadd132ss(xmm4, xmm2, Operand(esp, 0));
960     __ ucomiss(xmm4, xmm3);
961     __ j(not_equal, &exit);
962     // vfnmadd213ss
963     __ inc(eax);
964     __ movaps(xmm4, xmm1);
965     __ movss(Operand(esp, 0), xmm2);
966     __ vfnmadd213ss(xmm4, xmm0, Operand(esp, 0));
967     __ ucomiss(xmm4, xmm3);
968     __ j(not_equal, &exit);
969     // vfnmadd231ss
970     __ inc(eax);
971     __ movaps(xmm4, xmm2);
972     __ movss(Operand(esp, 0), xmm1);
973     __ vfnmadd231ss(xmm4, xmm0, Operand(esp, 0));
974     __ ucomiss(xmm4, xmm3);
975     __ j(not_equal, &exit);
976
977
978     // - xmm0 * xmm1 - xmm2
979     __ movaps(xmm3, xmm0);
980     __ mulss(xmm3, xmm1);
981     __ Move(xmm4, (uint32_t)1 << 31);
982     __ xorps(xmm3, xmm4);
983     __ subss(xmm3, xmm2);  // Expected result in xmm3
984
985     // vfnmsub132ss
986     __ inc(eax);
987     __ movaps(xmm4, xmm0);
988     __ vfnmsub132ss(xmm4, xmm2, xmm1);
989     __ ucomiss(xmm4, xmm3);
990     __ j(not_equal, &exit);
991     // vfmsub213ss
992     __ inc(eax);
993     __ movaps(xmm4, xmm1);
994     __ vfnmsub213ss(xmm4, xmm0, xmm2);
995     __ ucomiss(xmm4, xmm3);
996     __ j(not_equal, &exit);
997     // vfnmsub231ss
998     __ inc(eax);
999     __ movaps(xmm4, xmm2);
1000     __ vfnmsub231ss(xmm4, xmm0, xmm1);
1001     __ ucomiss(xmm4, xmm3);
1002     __ j(not_equal, &exit);
1003
1004     // vfnmsub132ss
1005     __ inc(eax);
1006     __ movaps(xmm4, xmm0);
1007     __ movss(Operand(esp, 0), xmm1);
1008     __ vfnmsub132ss(xmm4, xmm2, Operand(esp, 0));
1009     __ ucomiss(xmm4, xmm3);
1010     __ j(not_equal, &exit);
1011     // vfnmsub213ss
1012     __ inc(eax);
1013     __ movaps(xmm4, xmm1);
1014     __ movss(Operand(esp, 0), xmm2);
1015     __ vfnmsub213ss(xmm4, xmm0, Operand(esp, 0));
1016     __ ucomiss(xmm4, xmm3);
1017     __ j(not_equal, &exit);
1018     // vfnmsub231ss
1019     __ inc(eax);
1020     __ movaps(xmm4, xmm2);
1021     __ movss(Operand(esp, 0), xmm1);
1022     __ vfnmsub231ss(xmm4, xmm0, Operand(esp, 0));
1023     __ ucomiss(xmm4, xmm3);
1024     __ j(not_equal, &exit);
1025
1026
1027     __ xor_(eax, eax);
1028     __ bind(&exit);
1029     __ add(esp, Immediate(kDoubleSize));
1030     __ ret(0);
1031   }
1032
1033   CodeDesc desc;
1034   assm.GetCode(&desc);
1035   Handle<Code> code = isolate->factory()->NewCode(
1036       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1037 #ifdef OBJECT_PRINT
1038   OFStream os(stdout);
1039   code->Print(os);
1040 #endif
1041
1042   F10 f = FUNCTION_CAST<F10>(code->entry());
1043   CHECK_EQ(0, f(9.26621069e-05f, -2.4607749f, -1.09587872f));
1044 }
1045
1046
1047 TEST(AssemblerIa32JumpTables1) {
1048   // Test jump tables with forward jumps.
1049   CcTest::InitializeVM();
1050   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1051   HandleScope scope(isolate);
1052   Assembler assm(isolate, nullptr, 0);
1053
1054   const int kNumCases = 512;
1055   int values[kNumCases];
1056   isolate->random_number_generator()->NextBytes(values, sizeof(values));
1057   Label labels[kNumCases];
1058
1059   Label done, table;
1060   __ mov(eax, Operand(esp, 4));
1061   __ jmp(Operand::JumpTable(eax, times_4, &table));
1062   __ ud2();
1063   __ bind(&table);
1064   for (int i = 0; i < kNumCases; ++i) {
1065     __ dd(&labels[i]);
1066   }
1067
1068   for (int i = 0; i < kNumCases; ++i) {
1069     __ bind(&labels[i]);
1070     __ mov(eax, Immediate(values[i]));
1071     __ jmp(&done);
1072   }
1073
1074   __ bind(&done);
1075   __ ret(0);
1076
1077   CodeDesc desc;
1078   assm.GetCode(&desc);
1079   Handle<Code> code = isolate->factory()->NewCode(
1080       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1081 #ifdef OBJECT_PRINT
1082   OFStream os(stdout);
1083   code->Print(os);
1084 #endif
1085   F1 f = FUNCTION_CAST<F1>(code->entry());
1086   for (int i = 0; i < kNumCases; ++i) {
1087     int res = f(i);
1088     ::printf("f(%d) = %d\n", i, res);
1089     CHECK_EQ(values[i], res);
1090   }
1091 }
1092
1093
1094 TEST(AssemblerIa32JumpTables2) {
1095   // Test jump tables with backward jumps.
1096   CcTest::InitializeVM();
1097   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1098   HandleScope scope(isolate);
1099   Assembler assm(isolate, nullptr, 0);
1100
1101   const int kNumCases = 512;
1102   int values[kNumCases];
1103   isolate->random_number_generator()->NextBytes(values, sizeof(values));
1104   Label labels[kNumCases];
1105
1106   Label done, table;
1107   __ mov(eax, Operand(esp, 4));
1108   __ jmp(Operand::JumpTable(eax, times_4, &table));
1109   __ ud2();
1110
1111   for (int i = 0; i < kNumCases; ++i) {
1112     __ bind(&labels[i]);
1113     __ mov(eax, Immediate(values[i]));
1114     __ jmp(&done);
1115   }
1116
1117   __ bind(&table);
1118   for (int i = 0; i < kNumCases; ++i) {
1119     __ dd(&labels[i]);
1120   }
1121
1122   __ bind(&done);
1123   __ ret(0);
1124
1125   CodeDesc desc;
1126   assm.GetCode(&desc);
1127   Handle<Code> code = isolate->factory()->NewCode(
1128       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1129 #ifdef OBJECT_PRINT
1130   OFStream os(stdout);
1131   code->Print(os);
1132 #endif
1133   F1 f = FUNCTION_CAST<F1>(code->entry());
1134   for (int i = 0; i < kNumCases; ++i) {
1135     int res = f(i);
1136     ::printf("f(%d) = %d\n", i, res);
1137     CHECK_EQ(values[i], res);
1138   }
1139 }
1140
1141 #undef __