f5d59ded9b8dd01fc872f0adf7f284cbaef6738e
[platform/upstream/nodejs.git] / deps / v8 / test / cctest / test-assembler-x64.cc
1 // Copyright 2009 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 <cstdlib>
29 #include <iostream>
30
31 #include "src/v8.h"
32
33 #include "src/base/platform/platform.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 // Test the x64 assembler by compiling some simple functions into
43 // a buffer and executing them.  These tests do not initialize the
44 // V8 library, create a context, or use any V8 objects.
45 // The AMD64 calling convention is used, with the first six arguments
46 // in RDI, RSI, RDX, RCX, R8, and R9, and floating point arguments in
47 // the XMM registers.  The return value is in RAX.
48 // This calling convention is used on Linux, with GCC, and on Mac OS,
49 // with GCC.  A different convention is used on 64-bit windows,
50 // where the first four integer arguments are passed in RCX, RDX, R8 and R9.
51
52 typedef int (*F0)();
53 typedef int (*F1)(int64_t x);
54 typedef int (*F2)(int64_t x, int64_t y);
55 typedef unsigned (*F3)(double x);
56 typedef uint64_t (*F4)(uint64_t* x, uint64_t* y);
57 typedef uint64_t (*F5)(uint64_t x);
58
59 #ifdef _WIN64
60 static const Register arg1 = rcx;
61 static const Register arg2 = rdx;
62 #else
63 static const Register arg1 = rdi;
64 static const Register arg2 = rsi;
65 #endif
66
67 #define __ assm.
68
69
70 TEST(AssemblerX64ReturnOperation) {
71   CcTest::InitializeVM();
72   // Allocate an executable page of memory.
73   size_t actual_size;
74   byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
75       Assembler::kMinimalBufferSize, &actual_size, true));
76   CHECK(buffer);
77   Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
78
79   // Assemble a simple function that copies argument 2 and returns it.
80   __ movq(rax, arg2);
81   __ nop();
82   __ ret(0);
83
84   CodeDesc desc;
85   assm.GetCode(&desc);
86   // Call the function from C++.
87   int result =  FUNCTION_CAST<F2>(buffer)(3, 2);
88   CHECK_EQ(2, result);
89 }
90
91
92 TEST(AssemblerX64StackOperations) {
93   CcTest::InitializeVM();
94   // Allocate an executable page of memory.
95   size_t actual_size;
96   byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
97       Assembler::kMinimalBufferSize, &actual_size, true));
98   CHECK(buffer);
99   Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
100
101   // Assemble a simple function that copies argument 2 and returns it.
102   // We compile without stack frame pointers, so the gdb debugger shows
103   // incorrect stack frames when debugging this function (which has them).
104   __ pushq(rbp);
105   __ movq(rbp, rsp);
106   __ pushq(arg2);  // Value at (rbp - 8)
107   __ pushq(arg2);  // Value at (rbp - 16)
108   __ pushq(arg1);  // Value at (rbp - 24)
109   __ popq(rax);
110   __ popq(rax);
111   __ popq(rax);
112   __ popq(rbp);
113   __ nop();
114   __ ret(0);
115
116   CodeDesc desc;
117   assm.GetCode(&desc);
118   // Call the function from C++.
119   int result =  FUNCTION_CAST<F2>(buffer)(3, 2);
120   CHECK_EQ(2, result);
121 }
122
123
124 TEST(AssemblerX64ArithmeticOperations) {
125   CcTest::InitializeVM();
126   // Allocate an executable page of memory.
127   size_t actual_size;
128   byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
129       Assembler::kMinimalBufferSize, &actual_size, true));
130   CHECK(buffer);
131   Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
132
133   // Assemble a simple function that adds arguments returning the sum.
134   __ movq(rax, arg2);
135   __ addq(rax, arg1);
136   __ ret(0);
137
138   CodeDesc desc;
139   assm.GetCode(&desc);
140   // Call the function from C++.
141   int result =  FUNCTION_CAST<F2>(buffer)(3, 2);
142   CHECK_EQ(5, result);
143 }
144
145
146 TEST(AssemblerX64CmpbOperation) {
147   CcTest::InitializeVM();
148   // Allocate an executable page of memory.
149   size_t actual_size;
150   byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
151       Assembler::kMinimalBufferSize, &actual_size, true));
152   CHECK(buffer);
153   Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
154
155   // Assemble a function that compare argument byte returing 1 if equal else 0.
156   // On Windows, it compares rcx with rdx which does not require REX prefix;
157   // on Linux, it compares rdi with rsi which requires REX prefix.
158
159   Label done;
160   __ movq(rax, Immediate(1));
161   __ cmpb(arg1, arg2);
162   __ j(equal, &done);
163   __ movq(rax, Immediate(0));
164   __ bind(&done);
165   __ ret(0);
166
167   CodeDesc desc;
168   assm.GetCode(&desc);
169   // Call the function from C++.
170   int result =  FUNCTION_CAST<F2>(buffer)(0x1002, 0x2002);
171   CHECK_EQ(1, result);
172   result =  FUNCTION_CAST<F2>(buffer)(0x1002, 0x2003);
173   CHECK_EQ(0, result);
174 }
175
176
177 TEST(AssemblerX64ImulOperation) {
178   CcTest::InitializeVM();
179   // Allocate an executable page of memory.
180   size_t actual_size;
181   byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
182       Assembler::kMinimalBufferSize, &actual_size, true));
183   CHECK(buffer);
184   Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
185
186   // Assemble a simple function that multiplies arguments returning the high
187   // word.
188   __ movq(rax, arg2);
189   __ imulq(arg1);
190   __ movq(rax, rdx);
191   __ ret(0);
192
193   CodeDesc desc;
194   assm.GetCode(&desc);
195   // Call the function from C++.
196   int result =  FUNCTION_CAST<F2>(buffer)(3, 2);
197   CHECK_EQ(0, result);
198   result =  FUNCTION_CAST<F2>(buffer)(0x100000000l, 0x100000000l);
199   CHECK_EQ(1, result);
200   result =  FUNCTION_CAST<F2>(buffer)(-0x100000000l, 0x100000000l);
201   CHECK_EQ(-1, result);
202 }
203
204
205 TEST(AssemblerX64XchglOperations) {
206   CcTest::InitializeVM();
207   // Allocate an executable page of memory.
208   size_t actual_size;
209   byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
210       Assembler::kMinimalBufferSize, &actual_size, true));
211   CHECK(buffer);
212   Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
213
214   __ movq(rax, Operand(arg1, 0));
215   __ movq(r11, Operand(arg2, 0));
216   __ xchgl(rax, r11);
217   __ movq(Operand(arg1, 0), rax);
218   __ movq(Operand(arg2, 0), r11);
219   __ ret(0);
220
221   CodeDesc desc;
222   assm.GetCode(&desc);
223   // Call the function from C++.
224   uint64_t left = V8_2PART_UINT64_C(0x10000000, 20000000);
225   uint64_t right = V8_2PART_UINT64_C(0x30000000, 40000000);
226   uint64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right);
227   CHECK_EQ(V8_2PART_UINT64_C(0x00000000, 40000000), left);
228   CHECK_EQ(V8_2PART_UINT64_C(0x00000000, 20000000), right);
229   USE(result);
230 }
231
232
233 TEST(AssemblerX64OrlOperations) {
234   CcTest::InitializeVM();
235   // Allocate an executable page of memory.
236   size_t actual_size;
237   byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
238       Assembler::kMinimalBufferSize, &actual_size, true));
239   CHECK(buffer);
240   Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
241
242   __ movq(rax, Operand(arg2, 0));
243   __ orl(Operand(arg1, 0), rax);
244   __ ret(0);
245
246   CodeDesc desc;
247   assm.GetCode(&desc);
248   // Call the function from C++.
249   uint64_t left = V8_2PART_UINT64_C(0x10000000, 20000000);
250   uint64_t right = V8_2PART_UINT64_C(0x30000000, 40000000);
251   uint64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right);
252   CHECK_EQ(V8_2PART_UINT64_C(0x10000000, 60000000), left);
253   USE(result);
254 }
255
256
257 TEST(AssemblerX64RollOperations) {
258   CcTest::InitializeVM();
259   // Allocate an executable page of memory.
260   size_t actual_size;
261   byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
262       Assembler::kMinimalBufferSize, &actual_size, true));
263   CHECK(buffer);
264   Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
265
266   __ movq(rax, arg1);
267   __ roll(rax, Immediate(1));
268   __ ret(0);
269
270   CodeDesc desc;
271   assm.GetCode(&desc);
272   // Call the function from C++.
273   uint64_t src = V8_2PART_UINT64_C(0x10000000, C0000000);
274   uint64_t result = FUNCTION_CAST<F5>(buffer)(src);
275   CHECK_EQ(V8_2PART_UINT64_C(0x00000000, 80000001), result);
276 }
277
278
279 TEST(AssemblerX64SublOperations) {
280   CcTest::InitializeVM();
281   // Allocate an executable page of memory.
282   size_t actual_size;
283   byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
284       Assembler::kMinimalBufferSize, &actual_size, true));
285   CHECK(buffer);
286   Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
287
288   __ movq(rax, Operand(arg2, 0));
289   __ subl(Operand(arg1, 0), rax);
290   __ ret(0);
291
292   CodeDesc desc;
293   assm.GetCode(&desc);
294   // Call the function from C++.
295   uint64_t left = V8_2PART_UINT64_C(0x10000000, 20000000);
296   uint64_t right = V8_2PART_UINT64_C(0x30000000, 40000000);
297   uint64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right);
298   CHECK_EQ(V8_2PART_UINT64_C(0x10000000, e0000000), left);
299   USE(result);
300 }
301
302
303 TEST(AssemblerX64TestlOperations) {
304   CcTest::InitializeVM();
305   // Allocate an executable page of memory.
306   size_t actual_size;
307   byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
308       Assembler::kMinimalBufferSize, &actual_size, true));
309   CHECK(buffer);
310   Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
311
312   // Set rax with the ZF flag of the testl instruction.
313   Label done;
314   __ movq(rax, Immediate(1));
315   __ movq(r11, Operand(arg2, 0));
316   __ testl(Operand(arg1, 0), r11);
317   __ j(zero, &done, Label::kNear);
318   __ movq(rax, Immediate(0));
319   __ bind(&done);
320   __ ret(0);
321
322   CodeDesc desc;
323   assm.GetCode(&desc);
324   // Call the function from C++.
325   uint64_t left = V8_2PART_UINT64_C(0x10000000, 20000000);
326   uint64_t right = V8_2PART_UINT64_C(0x30000000, 00000000);
327   uint64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right);
328   CHECK_EQ(1u, result);
329 }
330
331
332 TEST(AssemblerX64XorlOperations) {
333   CcTest::InitializeVM();
334   // Allocate an executable page of memory.
335   size_t actual_size;
336   byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
337       Assembler::kMinimalBufferSize, &actual_size, true));
338   CHECK(buffer);
339   Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
340
341   __ movq(rax, Operand(arg2, 0));
342   __ xorl(Operand(arg1, 0), rax);
343   __ ret(0);
344
345   CodeDesc desc;
346   assm.GetCode(&desc);
347   // Call the function from C++.
348   uint64_t left = V8_2PART_UINT64_C(0x10000000, 20000000);
349   uint64_t right = V8_2PART_UINT64_C(0x30000000, 60000000);
350   uint64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right);
351   CHECK_EQ(V8_2PART_UINT64_C(0x10000000, 40000000), left);
352   USE(result);
353 }
354
355
356 TEST(AssemblerX64MemoryOperands) {
357   CcTest::InitializeVM();
358   // Allocate an executable page of memory.
359   size_t actual_size;
360   byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
361       Assembler::kMinimalBufferSize, &actual_size, true));
362   CHECK(buffer);
363   Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
364
365   // Assemble a simple function that copies argument 2 and returns it.
366   __ pushq(rbp);
367   __ movq(rbp, rsp);
368
369   __ pushq(arg2);  // Value at (rbp - 8)
370   __ pushq(arg2);  // Value at (rbp - 16)
371   __ pushq(arg1);  // Value at (rbp - 24)
372
373   const int kStackElementSize = 8;
374   __ movq(rax, Operand(rbp, -3 * kStackElementSize));
375   __ popq(arg2);
376   __ popq(arg2);
377   __ popq(arg2);
378   __ popq(rbp);
379   __ nop();
380   __ ret(0);
381
382   CodeDesc desc;
383   assm.GetCode(&desc);
384   // Call the function from C++.
385   int result =  FUNCTION_CAST<F2>(buffer)(3, 2);
386   CHECK_EQ(3, result);
387 }
388
389
390 TEST(AssemblerX64ControlFlow) {
391   CcTest::InitializeVM();
392   // Allocate an executable page of memory.
393   size_t actual_size;
394   byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
395       Assembler::kMinimalBufferSize, &actual_size, true));
396   CHECK(buffer);
397   Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
398
399   // Assemble a simple function that copies argument 1 and returns it.
400   __ pushq(rbp);
401
402   __ movq(rbp, rsp);
403   __ movq(rax, arg1);
404   Label target;
405   __ jmp(&target);
406   __ movq(rax, arg2);
407   __ bind(&target);
408   __ popq(rbp);
409   __ ret(0);
410
411   CodeDesc desc;
412   assm.GetCode(&desc);
413   // Call the function from C++.
414   int result =  FUNCTION_CAST<F2>(buffer)(3, 2);
415   CHECK_EQ(3, result);
416 }
417
418
419 TEST(AssemblerX64LoopImmediates) {
420   CcTest::InitializeVM();
421   // Allocate an executable page of memory.
422   size_t actual_size;
423   byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
424       Assembler::kMinimalBufferSize, &actual_size, true));
425   CHECK(buffer);
426   Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
427   // Assemble two loops using rax as counter, and verify the ending counts.
428   Label Fail;
429   __ movq(rax, Immediate(-3));
430   Label Loop1_test;
431   Label Loop1_body;
432   __ jmp(&Loop1_test);
433   __ bind(&Loop1_body);
434   __ addq(rax, Immediate(7));
435   __ bind(&Loop1_test);
436   __ cmpq(rax, Immediate(20));
437   __ j(less_equal, &Loop1_body);
438   // Did the loop terminate with the expected value?
439   __ cmpq(rax, Immediate(25));
440   __ j(not_equal, &Fail);
441
442   Label Loop2_test;
443   Label Loop2_body;
444   __ movq(rax, Immediate(0x11FEED00));
445   __ jmp(&Loop2_test);
446   __ bind(&Loop2_body);
447   __ addq(rax, Immediate(-0x1100));
448   __ bind(&Loop2_test);
449   __ cmpq(rax, Immediate(0x11FE8000));
450   __ j(greater, &Loop2_body);
451   // Did the loop terminate with the expected value?
452   __ cmpq(rax, Immediate(0x11FE7600));
453   __ j(not_equal, &Fail);
454
455   __ movq(rax, Immediate(1));
456   __ ret(0);
457   __ bind(&Fail);
458   __ movq(rax, Immediate(0));
459   __ ret(0);
460
461   CodeDesc desc;
462   assm.GetCode(&desc);
463   // Call the function from C++.
464   int result =  FUNCTION_CAST<F0>(buffer)();
465   CHECK_EQ(1, result);
466 }
467
468
469 TEST(OperandRegisterDependency) {
470   int offsets[4] = {0, 1, 0xfed, 0xbeefcad};
471   for (int i = 0; i < 4; i++) {
472     int offset = offsets[i];
473     CHECK(Operand(rax, offset).AddressUsesRegister(rax));
474     CHECK(!Operand(rax, offset).AddressUsesRegister(r8));
475     CHECK(!Operand(rax, offset).AddressUsesRegister(rcx));
476
477     CHECK(Operand(rax, rax, times_1, offset).AddressUsesRegister(rax));
478     CHECK(!Operand(rax, rax, times_1, offset).AddressUsesRegister(r8));
479     CHECK(!Operand(rax, rax, times_1, offset).AddressUsesRegister(rcx));
480
481     CHECK(Operand(rax, rcx, times_1, offset).AddressUsesRegister(rax));
482     CHECK(Operand(rax, rcx, times_1, offset).AddressUsesRegister(rcx));
483     CHECK(!Operand(rax, rcx, times_1, offset).AddressUsesRegister(r8));
484     CHECK(!Operand(rax, rcx, times_1, offset).AddressUsesRegister(r9));
485     CHECK(!Operand(rax, rcx, times_1, offset).AddressUsesRegister(rdx));
486     CHECK(!Operand(rax, rcx, times_1, offset).AddressUsesRegister(rsp));
487
488     CHECK(Operand(rsp, offset).AddressUsesRegister(rsp));
489     CHECK(!Operand(rsp, offset).AddressUsesRegister(rax));
490     CHECK(!Operand(rsp, offset).AddressUsesRegister(r15));
491
492     CHECK(Operand(rbp, offset).AddressUsesRegister(rbp));
493     CHECK(!Operand(rbp, offset).AddressUsesRegister(rax));
494     CHECK(!Operand(rbp, offset).AddressUsesRegister(r13));
495
496     CHECK(Operand(rbp, rax, times_1, offset).AddressUsesRegister(rbp));
497     CHECK(Operand(rbp, rax, times_1, offset).AddressUsesRegister(rax));
498     CHECK(!Operand(rbp, rax, times_1, offset).AddressUsesRegister(rcx));
499     CHECK(!Operand(rbp, rax, times_1, offset).AddressUsesRegister(r13));
500     CHECK(!Operand(rbp, rax, times_1, offset).AddressUsesRegister(r8));
501     CHECK(!Operand(rbp, rax, times_1, offset).AddressUsesRegister(rsp));
502
503     CHECK(Operand(rsp, rbp, times_1, offset).AddressUsesRegister(rsp));
504     CHECK(Operand(rsp, rbp, times_1, offset).AddressUsesRegister(rbp));
505     CHECK(!Operand(rsp, rbp, times_1, offset).AddressUsesRegister(rax));
506     CHECK(!Operand(rsp, rbp, times_1, offset).AddressUsesRegister(r15));
507     CHECK(!Operand(rsp, rbp, times_1, offset).AddressUsesRegister(r13));
508   }
509 }
510
511
512 TEST(AssemblerX64LabelChaining) {
513   // Test chaining of label usages within instructions (issue 1644).
514   CcTest::InitializeVM();
515   v8::HandleScope scope(CcTest::isolate());
516   Assembler assm(CcTest::i_isolate(), NULL, 0);
517
518   Label target;
519   __ j(equal, &target);
520   __ j(not_equal, &target);
521   __ bind(&target);
522   __ nop();
523 }
524
525
526 TEST(AssemblerMultiByteNop) {
527   CcTest::InitializeVM();
528   v8::HandleScope scope(CcTest::isolate());
529   byte buffer[1024];
530   Isolate* isolate = CcTest::i_isolate();
531   Assembler assm(isolate, buffer, sizeof(buffer));
532   __ pushq(rbx);
533   __ pushq(rcx);
534   __ pushq(rdx);
535   __ pushq(rdi);
536   __ pushq(rsi);
537   __ movq(rax, Immediate(1));
538   __ movq(rbx, Immediate(2));
539   __ movq(rcx, Immediate(3));
540   __ movq(rdx, Immediate(4));
541   __ movq(rdi, Immediate(5));
542   __ movq(rsi, Immediate(6));
543   for (int i = 0; i < 16; i++) {
544     int before = assm.pc_offset();
545     __ Nop(i);
546     CHECK_EQ(assm.pc_offset() - before, i);
547   }
548
549   Label fail;
550   __ cmpq(rax, Immediate(1));
551   __ j(not_equal, &fail);
552   __ cmpq(rbx, Immediate(2));
553   __ j(not_equal, &fail);
554   __ cmpq(rcx, Immediate(3));
555   __ j(not_equal, &fail);
556   __ cmpq(rdx, Immediate(4));
557   __ j(not_equal, &fail);
558   __ cmpq(rdi, Immediate(5));
559   __ j(not_equal, &fail);
560   __ cmpq(rsi, Immediate(6));
561   __ j(not_equal, &fail);
562   __ movq(rax, Immediate(42));
563   __ popq(rsi);
564   __ popq(rdi);
565   __ popq(rdx);
566   __ popq(rcx);
567   __ popq(rbx);
568   __ ret(0);
569   __ bind(&fail);
570   __ movq(rax, Immediate(13));
571   __ popq(rsi);
572   __ popq(rdi);
573   __ popq(rdx);
574   __ popq(rcx);
575   __ popq(rbx);
576   __ ret(0);
577
578   CodeDesc desc;
579   assm.GetCode(&desc);
580   Handle<Code> code = isolate->factory()->NewCode(
581       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
582
583   F0 f = FUNCTION_CAST<F0>(code->entry());
584   int res = f();
585   CHECK_EQ(42, res);
586 }
587
588
589 #ifdef __GNUC__
590 #define ELEMENT_COUNT 4u
591
592 void DoSSE2(const v8::FunctionCallbackInfo<v8::Value>& args) {
593   v8::HandleScope scope(CcTest::isolate());
594   byte buffer[1024];
595
596   CHECK(args[0]->IsArray());
597   v8::Local<v8::Array> vec = v8::Local<v8::Array>::Cast(args[0]);
598   CHECK_EQ(ELEMENT_COUNT, vec->Length());
599
600   Isolate* isolate = CcTest::i_isolate();
601   Assembler assm(isolate, buffer, sizeof(buffer));
602
603   // Remove return address from the stack for fix stack frame alignment.
604   __ popq(rcx);
605
606   // Store input vector on the stack.
607   for (unsigned i = 0; i < ELEMENT_COUNT; i++) {
608     __ movl(rax, Immediate(vec->Get(i)->Int32Value()));
609     __ shlq(rax, Immediate(0x20));
610     __ orq(rax, Immediate(vec->Get(++i)->Int32Value()));
611     __ pushq(rax);
612   }
613
614   // Read vector into a xmm register.
615   __ xorps(xmm0, xmm0);
616   __ movdqa(xmm0, Operand(rsp, 0));
617   // Create mask and store it in the return register.
618   __ movmskps(rax, xmm0);
619
620   // Remove unused data from the stack.
621   __ addq(rsp, Immediate(ELEMENT_COUNT * sizeof(int32_t)));
622   // Restore return address.
623   __ pushq(rcx);
624
625   __ ret(0);
626
627   CodeDesc desc;
628   assm.GetCode(&desc);
629   Handle<Code> code = isolate->factory()->NewCode(
630       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
631
632   F0 f = FUNCTION_CAST<F0>(code->entry());
633   int res = f();
634   args.GetReturnValue().Set(v8::Integer::New(CcTest::isolate(), res));
635 }
636
637
638 TEST(StackAlignmentForSSE2) {
639   CcTest::InitializeVM();
640   CHECK_EQ(0, v8::base::OS::ActivationFrameAlignment() % 16);
641
642   v8::Isolate* isolate = CcTest::isolate();
643   v8::HandleScope handle_scope(isolate);
644   v8::Handle<v8::ObjectTemplate> global_template =
645       v8::ObjectTemplate::New(isolate);
646   global_template->Set(v8_str("do_sse2"),
647                        v8::FunctionTemplate::New(isolate, DoSSE2));
648
649   LocalContext env(NULL, global_template);
650   CompileRun(
651       "function foo(vec) {"
652       "  return do_sse2(vec);"
653       "}");
654
655   v8::Local<v8::Object> global_object = env->Global();
656   v8::Local<v8::Function> foo =
657       v8::Local<v8::Function>::Cast(global_object->Get(v8_str("foo")));
658
659   int32_t vec[ELEMENT_COUNT] = { -1, 1, 1, 1 };
660   v8::Local<v8::Array> v8_vec = v8::Array::New(isolate, ELEMENT_COUNT);
661   for (unsigned i = 0; i < ELEMENT_COUNT; i++) {
662     v8_vec->Set(i, v8_num(vec[i]));
663   }
664
665   v8::Local<v8::Value> args[] = { v8_vec };
666   v8::Local<v8::Value> result = foo->Call(global_object, 1, args);
667
668   // The mask should be 0b1000.
669   CHECK_EQ(8, result->Int32Value());
670 }
671
672 #undef ELEMENT_COUNT
673 #endif  // __GNUC__
674
675
676 TEST(AssemblerX64Extractps) {
677   CcTest::InitializeVM();
678   if (!CpuFeatures::IsSupported(SSE4_1)) return;
679
680   v8::HandleScope scope(CcTest::isolate());
681   byte buffer[256];
682   Isolate* isolate = CcTest::i_isolate();
683   Assembler assm(isolate, buffer, sizeof(buffer));
684   { CpuFeatureScope fscope2(&assm, SSE4_1);
685     __ extractps(rax, xmm0, 0x1);
686     __ ret(0);
687   }
688
689   CodeDesc desc;
690   assm.GetCode(&desc);
691   Handle<Code> code = isolate->factory()->NewCode(
692       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
693 #ifdef OBJECT_PRINT
694   OFStream os(stdout);
695   code->Print(os);
696 #endif
697
698   F3 f = FUNCTION_CAST<F3>(code->entry());
699   uint64_t value1 = V8_2PART_UINT64_C(0x12345678, 87654321);
700   CHECK_EQ(0x12345678u, f(uint64_to_double(value1)));
701   uint64_t value2 = V8_2PART_UINT64_C(0x87654321, 12345678);
702   CHECK_EQ(0x87654321u, f(uint64_to_double(value2)));
703 }
704
705
706 typedef int (*F6)(float x, float y);
707 TEST(AssemblerX64SSE) {
708   CcTest::InitializeVM();
709
710   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
711   HandleScope scope(isolate);
712   v8::internal::byte buffer[256];
713   MacroAssembler assm(isolate, buffer, sizeof buffer);
714   {
715     __ shufps(xmm0, xmm0, 0x0);  // brocast first argument
716     __ shufps(xmm1, xmm1, 0x0);  // brocast second argument
717     __ movaps(xmm2, xmm1);
718     __ addps(xmm2, xmm0);
719     __ mulps(xmm2, xmm1);
720     __ subps(xmm2, xmm0);
721     __ divps(xmm2, xmm1);
722     __ cvttss2si(rax, xmm2);
723     __ ret(0);
724   }
725
726   CodeDesc desc;
727   assm.GetCode(&desc);
728   Handle<Code> code = isolate->factory()->NewCode(
729       desc,
730       Code::ComputeFlags(Code::STUB),
731       Handle<Code>());
732 #ifdef OBJECT_PRINT
733   OFStream os(stdout);
734   code->Print(os);
735 #endif
736
737   F6 f = FUNCTION_CAST<F6>(code->entry());
738   CHECK_EQ(2, f(1.0, 2.0));
739 }
740
741
742 typedef int (*F7)(double x, double y, double z);
743 TEST(AssemblerX64FMA_sd) {
744   CcTest::InitializeVM();
745   if (!CpuFeatures::IsSupported(FMA3)) return;
746
747   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
748   HandleScope scope(isolate);
749   v8::internal::byte buffer[1024];
750   MacroAssembler assm(isolate, buffer, sizeof buffer);
751   {
752     CpuFeatureScope fscope(&assm, FMA3);
753     Label exit;
754     // argument in xmm0, xmm1 and xmm2
755     // xmm0 * xmm1 + xmm2
756     __ movaps(xmm3, xmm0);
757     __ mulsd(xmm3, xmm1);
758     __ addsd(xmm3, xmm2);  // Expected result in xmm3
759
760     __ subq(rsp, Immediate(kDoubleSize));  // For memory operand
761     // vfmadd132sd
762     __ movl(rax, Immediate(1));  // Test number
763     __ movaps(xmm8, xmm0);
764     __ vfmadd132sd(xmm8, xmm2, xmm1);
765     __ ucomisd(xmm8, xmm3);
766     __ j(not_equal, &exit);
767     // vfmadd213sd
768     __ incq(rax);
769     __ movaps(xmm8, xmm1);
770     __ vfmadd213sd(xmm8, xmm0, xmm2);
771     __ ucomisd(xmm8, xmm3);
772     __ j(not_equal, &exit);
773     // vfmadd231sd
774     __ incq(rax);
775     __ movaps(xmm8, xmm2);
776     __ vfmadd231sd(xmm8, xmm0, xmm1);
777     __ ucomisd(xmm8, xmm3);
778     __ j(not_equal, &exit);
779
780     // vfmadd132sd
781     __ incq(rax);
782     __ movaps(xmm8, xmm0);
783     __ movsd(Operand(rsp, 0), xmm1);
784     __ vfmadd132sd(xmm8, xmm2, Operand(rsp, 0));
785     __ ucomisd(xmm8, xmm3);
786     __ j(not_equal, &exit);
787     // vfmadd213sd
788     __ incq(rax);
789     __ movaps(xmm8, xmm1);
790     __ movsd(Operand(rsp, 0), xmm2);
791     __ vfmadd213sd(xmm8, xmm0, Operand(rsp, 0));
792     __ ucomisd(xmm8, xmm3);
793     __ j(not_equal, &exit);
794     // vfmadd231sd
795     __ incq(rax);
796     __ movaps(xmm8, xmm2);
797     __ movsd(Operand(rsp, 0), xmm1);
798     __ vfmadd231sd(xmm8, xmm0, Operand(rsp, 0));
799     __ ucomisd(xmm8, xmm3);
800     __ j(not_equal, &exit);
801
802     // xmm0 * xmm1 - xmm2
803     __ movaps(xmm3, xmm0);
804     __ mulsd(xmm3, xmm1);
805     __ subsd(xmm3, xmm2);  // Expected result in xmm3
806
807     // vfmsub132sd
808     __ incq(rax);
809     __ movaps(xmm8, xmm0);
810     __ vfmsub132sd(xmm8, xmm2, xmm1);
811     __ ucomisd(xmm8, xmm3);
812     __ j(not_equal, &exit);
813     // vfmadd213sd
814     __ incq(rax);
815     __ movaps(xmm8, xmm1);
816     __ vfmsub213sd(xmm8, xmm0, xmm2);
817     __ ucomisd(xmm8, xmm3);
818     __ j(not_equal, &exit);
819     // vfmsub231sd
820     __ incq(rax);
821     __ movaps(xmm8, xmm2);
822     __ vfmsub231sd(xmm8, xmm0, xmm1);
823     __ ucomisd(xmm8, xmm3);
824     __ j(not_equal, &exit);
825
826     // vfmsub132sd
827     __ incq(rax);
828     __ movaps(xmm8, xmm0);
829     __ movsd(Operand(rsp, 0), xmm1);
830     __ vfmsub132sd(xmm8, xmm2, Operand(rsp, 0));
831     __ ucomisd(xmm8, xmm3);
832     __ j(not_equal, &exit);
833     // vfmsub213sd
834     __ incq(rax);
835     __ movaps(xmm8, xmm1);
836     __ movsd(Operand(rsp, 0), xmm2);
837     __ vfmsub213sd(xmm8, xmm0, Operand(rsp, 0));
838     __ ucomisd(xmm8, xmm3);
839     __ j(not_equal, &exit);
840     // vfmsub231sd
841     __ incq(rax);
842     __ movaps(xmm8, xmm2);
843     __ movsd(Operand(rsp, 0), xmm1);
844     __ vfmsub231sd(xmm8, xmm0, Operand(rsp, 0));
845     __ ucomisd(xmm8, xmm3);
846     __ j(not_equal, &exit);
847
848
849     // - xmm0 * xmm1 + xmm2
850     __ movaps(xmm3, xmm0);
851     __ mulsd(xmm3, xmm1);
852     __ Move(xmm4, (uint64_t)1 << 63);
853     __ xorpd(xmm3, xmm4);
854     __ addsd(xmm3, xmm2);  // Expected result in xmm3
855
856     // vfnmadd132sd
857     __ incq(rax);
858     __ movaps(xmm8, xmm0);
859     __ vfnmadd132sd(xmm8, xmm2, xmm1);
860     __ ucomisd(xmm8, xmm3);
861     __ j(not_equal, &exit);
862     // vfmadd213sd
863     __ incq(rax);
864     __ movaps(xmm8, xmm1);
865     __ vfnmadd213sd(xmm8, xmm0, xmm2);
866     __ ucomisd(xmm8, xmm3);
867     __ j(not_equal, &exit);
868     // vfnmadd231sd
869     __ incq(rax);
870     __ movaps(xmm8, xmm2);
871     __ vfnmadd231sd(xmm8, xmm0, xmm1);
872     __ ucomisd(xmm8, xmm3);
873     __ j(not_equal, &exit);
874
875     // vfnmadd132sd
876     __ incq(rax);
877     __ movaps(xmm8, xmm0);
878     __ movsd(Operand(rsp, 0), xmm1);
879     __ vfnmadd132sd(xmm8, xmm2, Operand(rsp, 0));
880     __ ucomisd(xmm8, xmm3);
881     __ j(not_equal, &exit);
882     // vfnmadd213sd
883     __ incq(rax);
884     __ movaps(xmm8, xmm1);
885     __ movsd(Operand(rsp, 0), xmm2);
886     __ vfnmadd213sd(xmm8, xmm0, Operand(rsp, 0));
887     __ ucomisd(xmm8, xmm3);
888     __ j(not_equal, &exit);
889     // vfnmadd231sd
890     __ incq(rax);
891     __ movaps(xmm8, xmm2);
892     __ movsd(Operand(rsp, 0), xmm1);
893     __ vfnmadd231sd(xmm8, xmm0, Operand(rsp, 0));
894     __ ucomisd(xmm8, xmm3);
895     __ j(not_equal, &exit);
896
897
898     // - xmm0 * xmm1 - xmm2
899     __ movaps(xmm3, xmm0);
900     __ mulsd(xmm3, xmm1);
901     __ Move(xmm4, (uint64_t)1 << 63);
902     __ xorpd(xmm3, xmm4);
903     __ subsd(xmm3, xmm2);  // Expected result in xmm3
904
905     // vfnmsub132sd
906     __ incq(rax);
907     __ movaps(xmm8, xmm0);
908     __ vfnmsub132sd(xmm8, xmm2, xmm1);
909     __ ucomisd(xmm8, xmm3);
910     __ j(not_equal, &exit);
911     // vfmsub213sd
912     __ incq(rax);
913     __ movaps(xmm8, xmm1);
914     __ vfnmsub213sd(xmm8, xmm0, xmm2);
915     __ ucomisd(xmm8, xmm3);
916     __ j(not_equal, &exit);
917     // vfnmsub231sd
918     __ incq(rax);
919     __ movaps(xmm8, xmm2);
920     __ vfnmsub231sd(xmm8, xmm0, xmm1);
921     __ ucomisd(xmm8, xmm3);
922     __ j(not_equal, &exit);
923
924     // vfnmsub132sd
925     __ incq(rax);
926     __ movaps(xmm8, xmm0);
927     __ movsd(Operand(rsp, 0), xmm1);
928     __ vfnmsub132sd(xmm8, xmm2, Operand(rsp, 0));
929     __ ucomisd(xmm8, xmm3);
930     __ j(not_equal, &exit);
931     // vfnmsub213sd
932     __ incq(rax);
933     __ movaps(xmm8, xmm1);
934     __ movsd(Operand(rsp, 0), xmm2);
935     __ vfnmsub213sd(xmm8, xmm0, Operand(rsp, 0));
936     __ ucomisd(xmm8, xmm3);
937     __ j(not_equal, &exit);
938     // vfnmsub231sd
939     __ incq(rax);
940     __ movaps(xmm8, xmm2);
941     __ movsd(Operand(rsp, 0), xmm1);
942     __ vfnmsub231sd(xmm8, xmm0, Operand(rsp, 0));
943     __ ucomisd(xmm8, xmm3);
944     __ j(not_equal, &exit);
945
946
947     __ xorl(rax, rax);
948     __ bind(&exit);
949     __ addq(rsp, Immediate(kDoubleSize));
950     __ ret(0);
951   }
952
953   CodeDesc desc;
954   assm.GetCode(&desc);
955   Handle<Code> code = isolate->factory()->NewCode(
956       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
957 #ifdef OBJECT_PRINT
958   OFStream os(stdout);
959   code->Print(os);
960 #endif
961
962   F7 f = FUNCTION_CAST<F7>(code->entry());
963   CHECK_EQ(0, f(0.000092662107262076, -2.460774966188315, -1.0958787393627414));
964 }
965
966
967 typedef int (*F8)(float x, float y, float z);
968 TEST(AssemblerX64FMA_ss) {
969   CcTest::InitializeVM();
970   if (!CpuFeatures::IsSupported(FMA3)) return;
971
972   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
973   HandleScope scope(isolate);
974   v8::internal::byte buffer[1024];
975   MacroAssembler assm(isolate, buffer, sizeof buffer);
976   {
977     CpuFeatureScope fscope(&assm, FMA3);
978     Label exit;
979     // arguments in xmm0, xmm1 and xmm2
980     // xmm0 * xmm1 + xmm2
981     __ movaps(xmm3, xmm0);
982     __ mulss(xmm3, xmm1);
983     __ addss(xmm3, xmm2);  // Expected result in xmm3
984
985     __ subq(rsp, Immediate(kDoubleSize));  // For memory operand
986     // vfmadd132ss
987     __ movl(rax, Immediate(1));  // Test number
988     __ movaps(xmm8, xmm0);
989     __ vfmadd132ss(xmm8, xmm2, xmm1);
990     __ ucomiss(xmm8, xmm3);
991     __ j(not_equal, &exit);
992     // vfmadd213ss
993     __ incq(rax);
994     __ movaps(xmm8, xmm1);
995     __ vfmadd213ss(xmm8, xmm0, xmm2);
996     __ ucomiss(xmm8, xmm3);
997     __ j(not_equal, &exit);
998     // vfmadd231ss
999     __ incq(rax);
1000     __ movaps(xmm8, xmm2);
1001     __ vfmadd231ss(xmm8, xmm0, xmm1);
1002     __ ucomiss(xmm8, xmm3);
1003     __ j(not_equal, &exit);
1004
1005     // vfmadd132ss
1006     __ incq(rax);
1007     __ movaps(xmm8, xmm0);
1008     __ movss(Operand(rsp, 0), xmm1);
1009     __ vfmadd132ss(xmm8, xmm2, Operand(rsp, 0));
1010     __ ucomiss(xmm8, xmm3);
1011     __ j(not_equal, &exit);
1012     // vfmadd213ss
1013     __ incq(rax);
1014     __ movaps(xmm8, xmm1);
1015     __ movss(Operand(rsp, 0), xmm2);
1016     __ vfmadd213ss(xmm8, xmm0, Operand(rsp, 0));
1017     __ ucomiss(xmm8, xmm3);
1018     __ j(not_equal, &exit);
1019     // vfmadd231ss
1020     __ incq(rax);
1021     __ movaps(xmm8, xmm2);
1022     __ movss(Operand(rsp, 0), xmm1);
1023     __ vfmadd231ss(xmm8, xmm0, Operand(rsp, 0));
1024     __ ucomiss(xmm8, xmm3);
1025     __ j(not_equal, &exit);
1026
1027     // xmm0 * xmm1 - xmm2
1028     __ movaps(xmm3, xmm0);
1029     __ mulss(xmm3, xmm1);
1030     __ subss(xmm3, xmm2);  // Expected result in xmm3
1031
1032     // vfmsub132ss
1033     __ incq(rax);
1034     __ movaps(xmm8, xmm0);
1035     __ vfmsub132ss(xmm8, xmm2, xmm1);
1036     __ ucomiss(xmm8, xmm3);
1037     __ j(not_equal, &exit);
1038     // vfmadd213ss
1039     __ incq(rax);
1040     __ movaps(xmm8, xmm1);
1041     __ vfmsub213ss(xmm8, xmm0, xmm2);
1042     __ ucomiss(xmm8, xmm3);
1043     __ j(not_equal, &exit);
1044     // vfmsub231ss
1045     __ incq(rax);
1046     __ movaps(xmm8, xmm2);
1047     __ vfmsub231ss(xmm8, xmm0, xmm1);
1048     __ ucomiss(xmm8, xmm3);
1049     __ j(not_equal, &exit);
1050
1051     // vfmsub132ss
1052     __ incq(rax);
1053     __ movaps(xmm8, xmm0);
1054     __ movss(Operand(rsp, 0), xmm1);
1055     __ vfmsub132ss(xmm8, xmm2, Operand(rsp, 0));
1056     __ ucomiss(xmm8, xmm3);
1057     __ j(not_equal, &exit);
1058     // vfmsub213ss
1059     __ incq(rax);
1060     __ movaps(xmm8, xmm1);
1061     __ movss(Operand(rsp, 0), xmm2);
1062     __ vfmsub213ss(xmm8, xmm0, Operand(rsp, 0));
1063     __ ucomiss(xmm8, xmm3);
1064     __ j(not_equal, &exit);
1065     // vfmsub231ss
1066     __ incq(rax);
1067     __ movaps(xmm8, xmm2);
1068     __ movss(Operand(rsp, 0), xmm1);
1069     __ vfmsub231ss(xmm8, xmm0, Operand(rsp, 0));
1070     __ ucomiss(xmm8, xmm3);
1071     __ j(not_equal, &exit);
1072
1073
1074     // - xmm0 * xmm1 + xmm2
1075     __ movaps(xmm3, xmm0);
1076     __ mulss(xmm3, xmm1);
1077     __ Move(xmm4, (uint32_t)1 << 31);
1078     __ xorps(xmm3, xmm4);
1079     __ addss(xmm3, xmm2);  // Expected result in xmm3
1080
1081     // vfnmadd132ss
1082     __ incq(rax);
1083     __ movaps(xmm8, xmm0);
1084     __ vfnmadd132ss(xmm8, xmm2, xmm1);
1085     __ ucomiss(xmm8, xmm3);
1086     __ j(not_equal, &exit);
1087     // vfmadd213ss
1088     __ incq(rax);
1089     __ movaps(xmm8, xmm1);
1090     __ vfnmadd213ss(xmm8, xmm0, xmm2);
1091     __ ucomiss(xmm8, xmm3);
1092     __ j(not_equal, &exit);
1093     // vfnmadd231ss
1094     __ incq(rax);
1095     __ movaps(xmm8, xmm2);
1096     __ vfnmadd231ss(xmm8, xmm0, xmm1);
1097     __ ucomiss(xmm8, xmm3);
1098     __ j(not_equal, &exit);
1099
1100     // vfnmadd132ss
1101     __ incq(rax);
1102     __ movaps(xmm8, xmm0);
1103     __ movss(Operand(rsp, 0), xmm1);
1104     __ vfnmadd132ss(xmm8, xmm2, Operand(rsp, 0));
1105     __ ucomiss(xmm8, xmm3);
1106     __ j(not_equal, &exit);
1107     // vfnmadd213ss
1108     __ incq(rax);
1109     __ movaps(xmm8, xmm1);
1110     __ movss(Operand(rsp, 0), xmm2);
1111     __ vfnmadd213ss(xmm8, xmm0, Operand(rsp, 0));
1112     __ ucomiss(xmm8, xmm3);
1113     __ j(not_equal, &exit);
1114     // vfnmadd231ss
1115     __ incq(rax);
1116     __ movaps(xmm8, xmm2);
1117     __ movss(Operand(rsp, 0), xmm1);
1118     __ vfnmadd231ss(xmm8, xmm0, Operand(rsp, 0));
1119     __ ucomiss(xmm8, xmm3);
1120     __ j(not_equal, &exit);
1121
1122
1123     // - xmm0 * xmm1 - xmm2
1124     __ movaps(xmm3, xmm0);
1125     __ mulss(xmm3, xmm1);
1126     __ Move(xmm4, (uint32_t)1 << 31);
1127     __ xorps(xmm3, xmm4);
1128     __ subss(xmm3, xmm2);  // Expected result in xmm3
1129
1130     // vfnmsub132ss
1131     __ incq(rax);
1132     __ movaps(xmm8, xmm0);
1133     __ vfnmsub132ss(xmm8, xmm2, xmm1);
1134     __ ucomiss(xmm8, xmm3);
1135     __ j(not_equal, &exit);
1136     // vfmsub213ss
1137     __ incq(rax);
1138     __ movaps(xmm8, xmm1);
1139     __ vfnmsub213ss(xmm8, xmm0, xmm2);
1140     __ ucomiss(xmm8, xmm3);
1141     __ j(not_equal, &exit);
1142     // vfnmsub231ss
1143     __ incq(rax);
1144     __ movaps(xmm8, xmm2);
1145     __ vfnmsub231ss(xmm8, xmm0, xmm1);
1146     __ ucomiss(xmm8, xmm3);
1147     __ j(not_equal, &exit);
1148
1149     // vfnmsub132ss
1150     __ incq(rax);
1151     __ movaps(xmm8, xmm0);
1152     __ movss(Operand(rsp, 0), xmm1);
1153     __ vfnmsub132ss(xmm8, xmm2, Operand(rsp, 0));
1154     __ ucomiss(xmm8, xmm3);
1155     __ j(not_equal, &exit);
1156     // vfnmsub213ss
1157     __ incq(rax);
1158     __ movaps(xmm8, xmm1);
1159     __ movss(Operand(rsp, 0), xmm2);
1160     __ vfnmsub213ss(xmm8, xmm0, Operand(rsp, 0));
1161     __ ucomiss(xmm8, xmm3);
1162     __ j(not_equal, &exit);
1163     // vfnmsub231ss
1164     __ incq(rax);
1165     __ movaps(xmm8, xmm2);
1166     __ movss(Operand(rsp, 0), xmm1);
1167     __ vfnmsub231ss(xmm8, xmm0, Operand(rsp, 0));
1168     __ ucomiss(xmm8, xmm3);
1169     __ j(not_equal, &exit);
1170
1171
1172     __ xorl(rax, rax);
1173     __ bind(&exit);
1174     __ addq(rsp, Immediate(kDoubleSize));
1175     __ ret(0);
1176   }
1177
1178   CodeDesc desc;
1179   assm.GetCode(&desc);
1180   Handle<Code> code = isolate->factory()->NewCode(
1181       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1182 #ifdef OBJECT_PRINT
1183   OFStream os(stdout);
1184   code->Print(os);
1185 #endif
1186
1187   F8 f = FUNCTION_CAST<F8>(code->entry());
1188   CHECK_EQ(0, f(9.26621069e-05f, -2.4607749f, -1.09587872f));
1189 }
1190
1191
1192 TEST(AssemblerX64JumpTables1) {
1193   // Test jump tables with forward jumps.
1194   CcTest::InitializeVM();
1195   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1196   HandleScope scope(isolate);
1197   MacroAssembler assm(isolate, nullptr, 0);
1198
1199   const int kNumCases = 512;
1200   int values[kNumCases];
1201   isolate->random_number_generator()->NextBytes(values, sizeof(values));
1202   Label labels[kNumCases];
1203
1204   Label done, table;
1205   __ leaq(arg2, Operand(&table));
1206   __ jmp(Operand(arg2, arg1, times_8, 0));
1207   __ ud2();
1208   __ bind(&table);
1209   for (int i = 0; i < kNumCases; ++i) {
1210     __ dq(&labels[i]);
1211   }
1212
1213   for (int i = 0; i < kNumCases; ++i) {
1214     __ bind(&labels[i]);
1215     __ movq(rax, Immediate(values[i]));
1216     __ jmp(&done);
1217   }
1218
1219   __ bind(&done);
1220   __ ret(0);
1221
1222   CodeDesc desc;
1223   assm.GetCode(&desc);
1224   Handle<Code> code = isolate->factory()->NewCode(
1225       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1226 #ifdef OBJECT_PRINT
1227   code->Print(std::cout);
1228 #endif
1229
1230   F1 f = FUNCTION_CAST<F1>(code->entry());
1231   for (int i = 0; i < kNumCases; ++i) {
1232     int res = f(i);
1233     PrintF("f(%d) = %d\n", i, res);
1234     CHECK_EQ(values[i], res);
1235   }
1236 }
1237
1238
1239 TEST(AssemblerX64JumpTables2) {
1240   // Test jump tables with backwards jumps.
1241   CcTest::InitializeVM();
1242   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1243   HandleScope scope(isolate);
1244   MacroAssembler assm(isolate, nullptr, 0);
1245
1246   const int kNumCases = 512;
1247   int values[kNumCases];
1248   isolate->random_number_generator()->NextBytes(values, sizeof(values));
1249   Label labels[kNumCases];
1250
1251   Label done, table;
1252   __ leaq(arg2, Operand(&table));
1253   __ jmp(Operand(arg2, arg1, times_8, 0));
1254   __ ud2();
1255
1256   for (int i = 0; i < kNumCases; ++i) {
1257     __ bind(&labels[i]);
1258     __ movq(rax, Immediate(values[i]));
1259     __ jmp(&done);
1260   }
1261
1262   __ bind(&done);
1263   __ ret(0);
1264
1265   __ bind(&table);
1266   for (int i = 0; i < kNumCases; ++i) {
1267     __ dq(&labels[i]);
1268   }
1269
1270   CodeDesc desc;
1271   assm.GetCode(&desc);
1272   Handle<Code> code = isolate->factory()->NewCode(
1273       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1274 #ifdef OBJECT_PRINT
1275   code->Print(std::cout);
1276 #endif
1277
1278   F1 f = FUNCTION_CAST<F1>(code->entry());
1279   for (int i = 0; i < kNumCases; ++i) {
1280     int res = f(i);
1281     PrintF("f(%d) = %d\n", i, res);
1282     CHECK_EQ(values[i], res);
1283   }
1284 }
1285
1286 #undef __