46592a05d18fe7aa5adb686a0b5a84391db46736
[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 "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(std::numeric_limits<double>::quiet_NaN(), 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 4u
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 (unsigned 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 (unsigned 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(static_cast<int>(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 typedef int (*F9)(double x, double y, double z);
593 TEST(AssemblerX64FMA_sd) {
594   CcTest::InitializeVM();
595   if (!CpuFeatures::IsSupported(FMA3)) return;
596
597   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
598   HandleScope scope(isolate);
599   v8::internal::byte buffer[1024];
600   MacroAssembler assm(isolate, buffer, sizeof buffer);
601   {
602     CpuFeatureScope fscope(&assm, FMA3);
603     Label exit;
604     __ movsd(xmm0, Operand(esp, 1 * kPointerSize));
605     __ movsd(xmm1, Operand(esp, 3 * kPointerSize));
606     __ movsd(xmm2, Operand(esp, 5 * kPointerSize));
607     // argument in xmm0, xmm1 and xmm2
608     // xmm0 * xmm1 + xmm2
609     __ movaps(xmm3, xmm0);
610     __ mulsd(xmm3, xmm1);
611     __ addsd(xmm3, xmm2);  // Expected result in xmm3
612
613     __ sub(esp, Immediate(kDoubleSize));  // For memory operand
614     // vfmadd132sd
615     __ mov(eax, Immediate(1));  // Test number
616     __ movaps(xmm4, xmm0);
617     __ vfmadd132sd(xmm4, xmm2, xmm1);
618     __ ucomisd(xmm4, xmm3);
619     __ j(not_equal, &exit);
620     // vfmadd213sd
621     __ inc(eax);
622     __ movaps(xmm4, xmm1);
623     __ vfmadd213sd(xmm4, xmm0, xmm2);
624     __ ucomisd(xmm4, xmm3);
625     __ j(not_equal, &exit);
626     // vfmadd231sd
627     __ inc(eax);
628     __ movaps(xmm4, xmm2);
629     __ vfmadd231sd(xmm4, xmm0, xmm1);
630     __ ucomisd(xmm4, xmm3);
631     __ j(not_equal, &exit);
632
633     // vfmadd132sd
634     __ inc(eax);
635     __ movaps(xmm4, xmm0);
636     __ movsd(Operand(esp, 0), xmm1);
637     __ vfmadd132sd(xmm4, xmm2, Operand(esp, 0));
638     __ ucomisd(xmm4, xmm3);
639     __ j(not_equal, &exit);
640     // vfmadd213sd
641     __ inc(eax);
642     __ movaps(xmm4, xmm1);
643     __ movsd(Operand(esp, 0), xmm2);
644     __ vfmadd213sd(xmm4, xmm0, Operand(esp, 0));
645     __ ucomisd(xmm4, xmm3);
646     __ j(not_equal, &exit);
647     // vfmadd231sd
648     __ inc(eax);
649     __ movaps(xmm4, xmm2);
650     __ movsd(Operand(esp, 0), xmm1);
651     __ vfmadd231sd(xmm4, xmm0, Operand(esp, 0));
652     __ ucomisd(xmm4, xmm3);
653     __ j(not_equal, &exit);
654
655     // xmm0 * xmm1 - xmm2
656     __ movaps(xmm3, xmm0);
657     __ mulsd(xmm3, xmm1);
658     __ subsd(xmm3, xmm2);  // Expected result in xmm3
659
660     // vfmsub132sd
661     __ inc(eax);
662     __ movaps(xmm4, xmm0);
663     __ vfmsub132sd(xmm4, xmm2, xmm1);
664     __ ucomisd(xmm4, xmm3);
665     __ j(not_equal, &exit);
666     // vfmadd213sd
667     __ inc(eax);
668     __ movaps(xmm4, xmm1);
669     __ vfmsub213sd(xmm4, xmm0, xmm2);
670     __ ucomisd(xmm4, xmm3);
671     __ j(not_equal, &exit);
672     // vfmsub231sd
673     __ inc(eax);
674     __ movaps(xmm4, xmm2);
675     __ vfmsub231sd(xmm4, xmm0, xmm1);
676     __ ucomisd(xmm4, xmm3);
677     __ j(not_equal, &exit);
678
679     // vfmsub132sd
680     __ inc(eax);
681     __ movaps(xmm4, xmm0);
682     __ movsd(Operand(esp, 0), xmm1);
683     __ vfmsub132sd(xmm4, xmm2, Operand(esp, 0));
684     __ ucomisd(xmm4, xmm3);
685     __ j(not_equal, &exit);
686     // vfmsub213sd
687     __ inc(eax);
688     __ movaps(xmm4, xmm1);
689     __ movsd(Operand(esp, 0), xmm2);
690     __ vfmsub213sd(xmm4, xmm0, Operand(esp, 0));
691     __ ucomisd(xmm4, xmm3);
692     __ j(not_equal, &exit);
693     // vfmsub231sd
694     __ inc(eax);
695     __ movaps(xmm4, xmm2);
696     __ movsd(Operand(esp, 0), xmm1);
697     __ vfmsub231sd(xmm4, xmm0, Operand(esp, 0));
698     __ ucomisd(xmm4, xmm3);
699     __ j(not_equal, &exit);
700
701
702     // - xmm0 * xmm1 + xmm2
703     __ movaps(xmm3, xmm0);
704     __ mulsd(xmm3, xmm1);
705     __ Move(xmm4, (uint64_t)1 << 63);
706     __ xorpd(xmm3, xmm4);
707     __ addsd(xmm3, xmm2);  // Expected result in xmm3
708
709     // vfnmadd132sd
710     __ inc(eax);
711     __ movaps(xmm4, xmm0);
712     __ vfnmadd132sd(xmm4, xmm2, xmm1);
713     __ ucomisd(xmm4, xmm3);
714     __ j(not_equal, &exit);
715     // vfmadd213sd
716     __ inc(eax);
717     __ movaps(xmm4, xmm1);
718     __ vfnmadd213sd(xmm4, xmm0, xmm2);
719     __ ucomisd(xmm4, xmm3);
720     __ j(not_equal, &exit);
721     // vfnmadd231sd
722     __ inc(eax);
723     __ movaps(xmm4, xmm2);
724     __ vfnmadd231sd(xmm4, xmm0, xmm1);
725     __ ucomisd(xmm4, xmm3);
726     __ j(not_equal, &exit);
727
728     // vfnmadd132sd
729     __ inc(eax);
730     __ movaps(xmm4, xmm0);
731     __ movsd(Operand(esp, 0), xmm1);
732     __ vfnmadd132sd(xmm4, xmm2, Operand(esp, 0));
733     __ ucomisd(xmm4, xmm3);
734     __ j(not_equal, &exit);
735     // vfnmadd213sd
736     __ inc(eax);
737     __ movaps(xmm4, xmm1);
738     __ movsd(Operand(esp, 0), xmm2);
739     __ vfnmadd213sd(xmm4, xmm0, Operand(esp, 0));
740     __ ucomisd(xmm4, xmm3);
741     __ j(not_equal, &exit);
742     // vfnmadd231sd
743     __ inc(eax);
744     __ movaps(xmm4, xmm2);
745     __ movsd(Operand(esp, 0), xmm1);
746     __ vfnmadd231sd(xmm4, xmm0, Operand(esp, 0));
747     __ ucomisd(xmm4, xmm3);
748     __ j(not_equal, &exit);
749
750
751     // - xmm0 * xmm1 - xmm2
752     __ movaps(xmm3, xmm0);
753     __ mulsd(xmm3, xmm1);
754     __ Move(xmm4, (uint64_t)1 << 63);
755     __ xorpd(xmm3, xmm4);
756     __ subsd(xmm3, xmm2);  // Expected result in xmm3
757
758     // vfnmsub132sd
759     __ inc(eax);
760     __ movaps(xmm4, xmm0);
761     __ vfnmsub132sd(xmm4, xmm2, xmm1);
762     __ ucomisd(xmm4, xmm3);
763     __ j(not_equal, &exit);
764     // vfmsub213sd
765     __ inc(eax);
766     __ movaps(xmm4, xmm1);
767     __ vfnmsub213sd(xmm4, xmm0, xmm2);
768     __ ucomisd(xmm4, xmm3);
769     __ j(not_equal, &exit);
770     // vfnmsub231sd
771     __ inc(eax);
772     __ movaps(xmm4, xmm2);
773     __ vfnmsub231sd(xmm4, xmm0, xmm1);
774     __ ucomisd(xmm4, xmm3);
775     __ j(not_equal, &exit);
776
777     // vfnmsub132sd
778     __ inc(eax);
779     __ movaps(xmm4, xmm0);
780     __ movsd(Operand(esp, 0), xmm1);
781     __ vfnmsub132sd(xmm4, xmm2, Operand(esp, 0));
782     __ ucomisd(xmm4, xmm3);
783     __ j(not_equal, &exit);
784     // vfnmsub213sd
785     __ inc(eax);
786     __ movaps(xmm4, xmm1);
787     __ movsd(Operand(esp, 0), xmm2);
788     __ vfnmsub213sd(xmm4, xmm0, Operand(esp, 0));
789     __ ucomisd(xmm4, xmm3);
790     __ j(not_equal, &exit);
791     // vfnmsub231sd
792     __ inc(eax);
793     __ movaps(xmm4, xmm2);
794     __ movsd(Operand(esp, 0), xmm1);
795     __ vfnmsub231sd(xmm4, xmm0, Operand(esp, 0));
796     __ ucomisd(xmm4, xmm3);
797     __ j(not_equal, &exit);
798
799
800     __ xor_(eax, eax);
801     __ bind(&exit);
802     __ add(esp, Immediate(kDoubleSize));
803     __ ret(0);
804   }
805
806   CodeDesc desc;
807   assm.GetCode(&desc);
808   Handle<Code> code = isolate->factory()->NewCode(
809       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
810 #ifdef OBJECT_PRINT
811   OFStream os(stdout);
812   code->Print(os);
813 #endif
814
815   F9 f = FUNCTION_CAST<F9>(code->entry());
816   CHECK_EQ(0, f(0.000092662107262076, -2.460774966188315, -1.0958787393627414));
817 }
818
819
820 typedef int (*F10)(float x, float y, float z);
821 TEST(AssemblerX64FMA_ss) {
822   CcTest::InitializeVM();
823   if (!CpuFeatures::IsSupported(FMA3)) return;
824
825   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
826   HandleScope scope(isolate);
827   v8::internal::byte buffer[1024];
828   MacroAssembler assm(isolate, buffer, sizeof buffer);
829   {
830     CpuFeatureScope fscope(&assm, FMA3);
831     Label exit;
832     __ movss(xmm0, Operand(esp, 1 * kPointerSize));
833     __ movss(xmm1, Operand(esp, 2 * kPointerSize));
834     __ movss(xmm2, Operand(esp, 3 * kPointerSize));
835     // arguments in xmm0, xmm1 and xmm2
836     // xmm0 * xmm1 + xmm2
837     __ movaps(xmm3, xmm0);
838     __ mulss(xmm3, xmm1);
839     __ addss(xmm3, xmm2);  // Expected result in xmm3
840
841     __ sub(esp, Immediate(kDoubleSize));  // For memory operand
842     // vfmadd132ss
843     __ mov(eax, Immediate(1));  // Test number
844     __ movaps(xmm4, xmm0);
845     __ vfmadd132ss(xmm4, xmm2, xmm1);
846     __ ucomiss(xmm4, xmm3);
847     __ j(not_equal, &exit);
848     // vfmadd213ss
849     __ inc(eax);
850     __ movaps(xmm4, xmm1);
851     __ vfmadd213ss(xmm4, xmm0, xmm2);
852     __ ucomiss(xmm4, xmm3);
853     __ j(not_equal, &exit);
854     // vfmadd231ss
855     __ inc(eax);
856     __ movaps(xmm4, xmm2);
857     __ vfmadd231ss(xmm4, xmm0, xmm1);
858     __ ucomiss(xmm4, xmm3);
859     __ j(not_equal, &exit);
860
861     // vfmadd132ss
862     __ inc(eax);
863     __ movaps(xmm4, xmm0);
864     __ movss(Operand(esp, 0), xmm1);
865     __ vfmadd132ss(xmm4, xmm2, Operand(esp, 0));
866     __ ucomiss(xmm4, xmm3);
867     __ j(not_equal, &exit);
868     // vfmadd213ss
869     __ inc(eax);
870     __ movaps(xmm4, xmm1);
871     __ movss(Operand(esp, 0), xmm2);
872     __ vfmadd213ss(xmm4, xmm0, Operand(esp, 0));
873     __ ucomiss(xmm4, xmm3);
874     __ j(not_equal, &exit);
875     // vfmadd231ss
876     __ inc(eax);
877     __ movaps(xmm4, xmm2);
878     __ movss(Operand(esp, 0), xmm1);
879     __ vfmadd231ss(xmm4, xmm0, Operand(esp, 0));
880     __ ucomiss(xmm4, xmm3);
881     __ j(not_equal, &exit);
882
883     // xmm0 * xmm1 - xmm2
884     __ movaps(xmm3, xmm0);
885     __ mulss(xmm3, xmm1);
886     __ subss(xmm3, xmm2);  // Expected result in xmm3
887
888     // vfmsub132ss
889     __ inc(eax);
890     __ movaps(xmm4, xmm0);
891     __ vfmsub132ss(xmm4, xmm2, xmm1);
892     __ ucomiss(xmm4, xmm3);
893     __ j(not_equal, &exit);
894     // vfmadd213ss
895     __ inc(eax);
896     __ movaps(xmm4, xmm1);
897     __ vfmsub213ss(xmm4, xmm0, xmm2);
898     __ ucomiss(xmm4, xmm3);
899     __ j(not_equal, &exit);
900     // vfmsub231ss
901     __ inc(eax);
902     __ movaps(xmm4, xmm2);
903     __ vfmsub231ss(xmm4, xmm0, xmm1);
904     __ ucomiss(xmm4, xmm3);
905     __ j(not_equal, &exit);
906
907     // vfmsub132ss
908     __ inc(eax);
909     __ movaps(xmm4, xmm0);
910     __ movss(Operand(esp, 0), xmm1);
911     __ vfmsub132ss(xmm4, xmm2, Operand(esp, 0));
912     __ ucomiss(xmm4, xmm3);
913     __ j(not_equal, &exit);
914     // vfmsub213ss
915     __ inc(eax);
916     __ movaps(xmm4, xmm1);
917     __ movss(Operand(esp, 0), xmm2);
918     __ vfmsub213ss(xmm4, xmm0, Operand(esp, 0));
919     __ ucomiss(xmm4, xmm3);
920     __ j(not_equal, &exit);
921     // vfmsub231ss
922     __ inc(eax);
923     __ movaps(xmm4, xmm2);
924     __ movss(Operand(esp, 0), xmm1);
925     __ vfmsub231ss(xmm4, xmm0, Operand(esp, 0));
926     __ ucomiss(xmm4, xmm3);
927     __ j(not_equal, &exit);
928
929
930     // - xmm0 * xmm1 + xmm2
931     __ movaps(xmm3, xmm0);
932     __ mulss(xmm3, xmm1);
933     __ Move(xmm4, (uint32_t)1 << 31);
934     __ xorps(xmm3, xmm4);
935     __ addss(xmm3, xmm2);  // Expected result in xmm3
936
937     // vfnmadd132ss
938     __ inc(eax);
939     __ movaps(xmm4, xmm0);
940     __ vfnmadd132ss(xmm4, xmm2, xmm1);
941     __ ucomiss(xmm4, xmm3);
942     __ j(not_equal, &exit);
943     // vfmadd213ss
944     __ inc(eax);
945     __ movaps(xmm4, xmm1);
946     __ vfnmadd213ss(xmm4, xmm0, xmm2);
947     __ ucomiss(xmm4, xmm3);
948     __ j(not_equal, &exit);
949     // vfnmadd231ss
950     __ inc(eax);
951     __ movaps(xmm4, xmm2);
952     __ vfnmadd231ss(xmm4, xmm0, xmm1);
953     __ ucomiss(xmm4, xmm3);
954     __ j(not_equal, &exit);
955
956     // vfnmadd132ss
957     __ inc(eax);
958     __ movaps(xmm4, xmm0);
959     __ movss(Operand(esp, 0), xmm1);
960     __ vfnmadd132ss(xmm4, xmm2, Operand(esp, 0));
961     __ ucomiss(xmm4, xmm3);
962     __ j(not_equal, &exit);
963     // vfnmadd213ss
964     __ inc(eax);
965     __ movaps(xmm4, xmm1);
966     __ movss(Operand(esp, 0), xmm2);
967     __ vfnmadd213ss(xmm4, xmm0, Operand(esp, 0));
968     __ ucomiss(xmm4, xmm3);
969     __ j(not_equal, &exit);
970     // vfnmadd231ss
971     __ inc(eax);
972     __ movaps(xmm4, xmm2);
973     __ movss(Operand(esp, 0), xmm1);
974     __ vfnmadd231ss(xmm4, xmm0, Operand(esp, 0));
975     __ ucomiss(xmm4, xmm3);
976     __ j(not_equal, &exit);
977
978
979     // - xmm0 * xmm1 - xmm2
980     __ movaps(xmm3, xmm0);
981     __ mulss(xmm3, xmm1);
982     __ Move(xmm4, (uint32_t)1 << 31);
983     __ xorps(xmm3, xmm4);
984     __ subss(xmm3, xmm2);  // Expected result in xmm3
985
986     // vfnmsub132ss
987     __ inc(eax);
988     __ movaps(xmm4, xmm0);
989     __ vfnmsub132ss(xmm4, xmm2, xmm1);
990     __ ucomiss(xmm4, xmm3);
991     __ j(not_equal, &exit);
992     // vfmsub213ss
993     __ inc(eax);
994     __ movaps(xmm4, xmm1);
995     __ vfnmsub213ss(xmm4, xmm0, xmm2);
996     __ ucomiss(xmm4, xmm3);
997     __ j(not_equal, &exit);
998     // vfnmsub231ss
999     __ inc(eax);
1000     __ movaps(xmm4, xmm2);
1001     __ vfnmsub231ss(xmm4, xmm0, xmm1);
1002     __ ucomiss(xmm4, xmm3);
1003     __ j(not_equal, &exit);
1004
1005     // vfnmsub132ss
1006     __ inc(eax);
1007     __ movaps(xmm4, xmm0);
1008     __ movss(Operand(esp, 0), xmm1);
1009     __ vfnmsub132ss(xmm4, xmm2, Operand(esp, 0));
1010     __ ucomiss(xmm4, xmm3);
1011     __ j(not_equal, &exit);
1012     // vfnmsub213ss
1013     __ inc(eax);
1014     __ movaps(xmm4, xmm1);
1015     __ movss(Operand(esp, 0), xmm2);
1016     __ vfnmsub213ss(xmm4, xmm0, Operand(esp, 0));
1017     __ ucomiss(xmm4, xmm3);
1018     __ j(not_equal, &exit);
1019     // vfnmsub231ss
1020     __ inc(eax);
1021     __ movaps(xmm4, xmm2);
1022     __ movss(Operand(esp, 0), xmm1);
1023     __ vfnmsub231ss(xmm4, xmm0, Operand(esp, 0));
1024     __ ucomiss(xmm4, xmm3);
1025     __ j(not_equal, &exit);
1026
1027
1028     __ xor_(eax, eax);
1029     __ bind(&exit);
1030     __ add(esp, Immediate(kDoubleSize));
1031     __ ret(0);
1032   }
1033
1034   CodeDesc desc;
1035   assm.GetCode(&desc);
1036   Handle<Code> code = isolate->factory()->NewCode(
1037       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1038 #ifdef OBJECT_PRINT
1039   OFStream os(stdout);
1040   code->Print(os);
1041 #endif
1042
1043   F10 f = FUNCTION_CAST<F10>(code->entry());
1044   CHECK_EQ(0, f(9.26621069e-05f, -2.4607749f, -1.09587872f));
1045 }
1046
1047
1048 TEST(AssemblerIa32JumpTables1) {
1049   // Test jump tables with forward jumps.
1050   CcTest::InitializeVM();
1051   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1052   HandleScope scope(isolate);
1053   Assembler assm(isolate, nullptr, 0);
1054
1055   const int kNumCases = 512;
1056   int values[kNumCases];
1057   isolate->random_number_generator()->NextBytes(values, sizeof(values));
1058   Label labels[kNumCases];
1059
1060   Label done, table;
1061   __ mov(eax, Operand(esp, 4));
1062   __ jmp(Operand::JumpTable(eax, times_4, &table));
1063   __ ud2();
1064   __ bind(&table);
1065   for (int i = 0; i < kNumCases; ++i) {
1066     __ dd(&labels[i]);
1067   }
1068
1069   for (int i = 0; i < kNumCases; ++i) {
1070     __ bind(&labels[i]);
1071     __ mov(eax, Immediate(values[i]));
1072     __ jmp(&done);
1073   }
1074
1075   __ bind(&done);
1076   __ ret(0);
1077
1078   CodeDesc desc;
1079   assm.GetCode(&desc);
1080   Handle<Code> code = isolate->factory()->NewCode(
1081       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1082 #ifdef OBJECT_PRINT
1083   OFStream os(stdout);
1084   code->Print(os);
1085 #endif
1086   F1 f = FUNCTION_CAST<F1>(code->entry());
1087   for (int i = 0; i < kNumCases; ++i) {
1088     int res = f(i);
1089     ::printf("f(%d) = %d\n", i, res);
1090     CHECK_EQ(values[i], res);
1091   }
1092 }
1093
1094
1095 TEST(AssemblerIa32JumpTables2) {
1096   // Test jump tables with backward jumps.
1097   CcTest::InitializeVM();
1098   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1099   HandleScope scope(isolate);
1100   Assembler assm(isolate, nullptr, 0);
1101
1102   const int kNumCases = 512;
1103   int values[kNumCases];
1104   isolate->random_number_generator()->NextBytes(values, sizeof(values));
1105   Label labels[kNumCases];
1106
1107   Label done, table;
1108   __ mov(eax, Operand(esp, 4));
1109   __ jmp(Operand::JumpTable(eax, times_4, &table));
1110   __ ud2();
1111
1112   for (int i = 0; i < kNumCases; ++i) {
1113     __ bind(&labels[i]);
1114     __ mov(eax, Immediate(values[i]));
1115     __ jmp(&done);
1116   }
1117
1118   __ bind(&table);
1119   for (int i = 0; i < kNumCases; ++i) {
1120     __ dd(&labels[i]);
1121   }
1122
1123   __ bind(&done);
1124   __ ret(0);
1125
1126   CodeDesc desc;
1127   assm.GetCode(&desc);
1128   Handle<Code> code = isolate->factory()->NewCode(
1129       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1130 #ifdef OBJECT_PRINT
1131   OFStream os(stdout);
1132   code->Print(os);
1133 #endif
1134   F1 f = FUNCTION_CAST<F1>(code->entry());
1135   for (int i = 0; i < kNumCases; ++i) {
1136     int res = f(i);
1137     ::printf("f(%d) = %d\n", i, res);
1138     CHECK_EQ(values[i], res);
1139   }
1140 }
1141
1142 #undef __