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