1755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org// Copyright 2009 the V8 project authors. All rights reserved.
2755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org// Redistribution and use in source and binary forms, with or without
3755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org// modification, are permitted provided that the following conditions are
4755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org// met:
5755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org//
6755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org//     * Redistributions of source code must retain the above copyright
7755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org//       notice, this list of conditions and the following disclaimer.
8755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org//     * Redistributions in binary form must reproduce the above
9755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org//       copyright notice, this list of conditions and the following
10755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org//       disclaimer in the documentation and/or other materials provided
11755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org//       with the distribution.
12755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org//     * Neither the name of Google Inc. nor the names of its
13755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org//       contributors may be used to endorse or promote products derived
14755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org//       from this software without specific prior written permission.
15755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org//
16755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
28755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org#include <stdlib.h>
29755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
30196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
31755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
325de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/platform/platform.h"
33196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/factory.h"
344b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "src/macro-assembler.h"
357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/ostreams.h"
36196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/serialize.h"
37196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "test/cctest/cctest.h"
38755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
39b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.orgusing namespace v8::internal;
400ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
41755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org// Test the x64 assembler by compiling some simple functions into
42755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org// a buffer and executing them.  These tests do not initialize the
43755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org// V8 library, create a context, or use any V8 objects.
449d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com// The AMD64 calling convention is used, with the first six arguments
459d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com// in RDI, RSI, RDX, RCX, R8, and R9, and floating point arguments in
46755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org// the XMM registers.  The return value is in RAX.
47755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org// This calling convention is used on Linux, with GCC, and on Mac OS,
489d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com// with GCC.  A different convention is used on 64-bit windows,
499d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com// where the first four integer arguments are passed in RCX, RDX, R8 and R9.
50755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
51755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.orgtypedef int (*F0)();
522abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.orgtypedef int (*F1)(int64_t x);
532abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.orgtypedef int (*F2)(int64_t x, int64_t y);
54b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.orgtypedef int (*F3)(double x);
55c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.orgtypedef int64_t (*F4)(int64_t* x, int64_t* y);
56c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.orgtypedef int64_t (*F5)(int64_t x);
57755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
589d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com#ifdef _WIN64
59b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.orgstatic const Register arg1 = rcx;
60b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.orgstatic const Register arg2 = rdx;
619d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com#else
62b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.orgstatic const Register arg1 = rdi;
63b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.orgstatic const Register arg2 = rsi;
649d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com#endif
659d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
66755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org#define __ assm.
67755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
68755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
69755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.orgTEST(AssemblerX64ReturnOperation) {
70874aad37f2a832804012c6f56739f4fc6c9283cdmachenbach@chromium.org  CcTest::InitializeVM();
71755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Allocate an executable page of memory.
72755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  size_t actual_size;
735de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
745de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      Assembler::kMinimalBufferSize, &actual_size, true));
75755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  CHECK(buffer);
76528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
77755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
78755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Assemble a simple function that copies argument 2 and returns it.
799d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  __ movq(rax, arg2);
80755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ nop();
81755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ ret(0);
82755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
83755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  CodeDesc desc;
84755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  assm.GetCode(&desc);
85755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Call the function from C++.
86755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  int result =  FUNCTION_CAST<F2>(buffer)(3, 2);
87755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  CHECK_EQ(2, result);
88755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org}
89755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
90e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
91755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.orgTEST(AssemblerX64StackOperations) {
92874aad37f2a832804012c6f56739f4fc6c9283cdmachenbach@chromium.org  CcTest::InitializeVM();
93755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Allocate an executable page of memory.
94755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  size_t actual_size;
955de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
965de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      Assembler::kMinimalBufferSize, &actual_size, true));
97755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  CHECK(buffer);
98528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
99755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
100755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Assemble a simple function that copies argument 2 and returns it.
101755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // We compile without stack frame pointers, so the gdb debugger shows
102755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // incorrect stack frames when debugging this function (which has them).
103763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(rbp);
104755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ movq(rbp, rsp);
105763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(arg2);  // Value at (rbp - 8)
106763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(arg2);  // Value at (rbp - 16)
107763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(arg1);  // Value at (rbp - 24)
108763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rax);
109763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rax);
110763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rax);
111763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rbp);
112755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ nop();
113755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ ret(0);
114755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
115755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  CodeDesc desc;
116755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  assm.GetCode(&desc);
117755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Call the function from C++.
118755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  int result =  FUNCTION_CAST<F2>(buffer)(3, 2);
119755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  CHECK_EQ(2, result);
120755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org}
121755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
122e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
123755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.orgTEST(AssemblerX64ArithmeticOperations) {
124874aad37f2a832804012c6f56739f4fc6c9283cdmachenbach@chromium.org  CcTest::InitializeVM();
125755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Allocate an executable page of memory.
126755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  size_t actual_size;
1275de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1285de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      Assembler::kMinimalBufferSize, &actual_size, true));
129755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  CHECK(buffer);
130528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
131755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1322abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  // Assemble a simple function that adds arguments returning the sum.
1339d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  __ movq(rax, arg2);
1349d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  __ addq(rax, arg1);
135755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ ret(0);
136755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
137755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  CodeDesc desc;
138755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  assm.GetCode(&desc);
139755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Call the function from C++.
140755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  int result =  FUNCTION_CAST<F2>(buffer)(3, 2);
141755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  CHECK_EQ(5, result);
142755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org}
143755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
144e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
1452f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.orgTEST(AssemblerX64CmpbOperation) {
146874aad37f2a832804012c6f56739f4fc6c9283cdmachenbach@chromium.org  CcTest::InitializeVM();
1472f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  // Allocate an executable page of memory.
1482f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  size_t actual_size;
1495de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1505de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      Assembler::kMinimalBufferSize, &actual_size, true));
1512f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  CHECK(buffer);
1522f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
1532f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org
1542f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  // Assemble a function that compare argument byte returing 1 if equal else 0.
1552f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  // On Windows, it compares rcx with rdx which does not require REX prefix;
1562f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  // on Linux, it compares rdi with rsi which requires REX prefix.
1572f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org
1582f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  Label done;
1592f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  __ movq(rax, Immediate(1));
1602f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  __ cmpb(arg1, arg2);
1612f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  __ j(equal, &done);
1622f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  __ movq(rax, Immediate(0));
1632f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  __ bind(&done);
1642f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  __ ret(0);
1652f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org
1662f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  CodeDesc desc;
1672f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  assm.GetCode(&desc);
1682f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  // Call the function from C++.
1692f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  int result =  FUNCTION_CAST<F2>(buffer)(0x1002, 0x2002);
1702f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  CHECK_EQ(1, result);
1712f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  result =  FUNCTION_CAST<F2>(buffer)(0x1002, 0x2003);
1722f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  CHECK_EQ(0, result);
1732f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org}
1742f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org
1752f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org
1762abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.orgTEST(AssemblerX64ImulOperation) {
177874aad37f2a832804012c6f56739f4fc6c9283cdmachenbach@chromium.org  CcTest::InitializeVM();
1782abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  // Allocate an executable page of memory.
1792abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  size_t actual_size;
1805de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1815de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      Assembler::kMinimalBufferSize, &actual_size, true));
1822abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  CHECK(buffer);
183528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
1842abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org
1852abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  // Assemble a simple function that multiplies arguments returning the high
1862abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  // word.
1879d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  __ movq(rax, arg2);
188fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  __ imulq(arg1);
1892abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  __ movq(rax, rdx);
1902abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  __ ret(0);
1912abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org
1922abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  CodeDesc desc;
1932abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  assm.GetCode(&desc);
1942abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  // Call the function from C++.
1952abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  int result =  FUNCTION_CAST<F2>(buffer)(3, 2);
1962abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  CHECK_EQ(0, result);
1972abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  result =  FUNCTION_CAST<F2>(buffer)(0x100000000l, 0x100000000l);
1982abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  CHECK_EQ(1, result);
1992abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  result =  FUNCTION_CAST<F2>(buffer)(-0x100000000l, 0x100000000l);
2002abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  CHECK_EQ(-1, result);
2012abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org}
2022abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org
203e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
204c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.orgTEST(AssemblerX64XchglOperations) {
205874aad37f2a832804012c6f56739f4fc6c9283cdmachenbach@chromium.org  CcTest::InitializeVM();
206c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // Allocate an executable page of memory.
207c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  size_t actual_size;
2085de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
2095de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      Assembler::kMinimalBufferSize, &actual_size, true));
210c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  CHECK(buffer);
211c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
212c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
213c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ movq(rax, Operand(arg1, 0));
21425530ce9cb50f9e8386663ca40fd3f6e023ec9f6bmeurer@chromium.org  __ movq(r11, Operand(arg2, 0));
21525530ce9cb50f9e8386663ca40fd3f6e023ec9f6bmeurer@chromium.org  __ xchgl(rax, r11);
216c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ movq(Operand(arg1, 0), rax);
21725530ce9cb50f9e8386663ca40fd3f6e023ec9f6bmeurer@chromium.org  __ movq(Operand(arg2, 0), r11);
218c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ ret(0);
219c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
220c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  CodeDesc desc;
221c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  assm.GetCode(&desc);
222c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // Call the function from C++.
223c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  int64_t left   = V8_2PART_UINT64_C(0x10000000, 20000000);
224c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  int64_t right  = V8_2PART_UINT64_C(0x30000000, 40000000);
225c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  int64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right);
226c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  CHECK_EQ(V8_2PART_UINT64_C(0x00000000, 40000000), left);
227c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  CHECK_EQ(V8_2PART_UINT64_C(0x00000000, 20000000), right);
228c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  USE(result);
229c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org}
230c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
231c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
232c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.orgTEST(AssemblerX64OrlOperations) {
233874aad37f2a832804012c6f56739f4fc6c9283cdmachenbach@chromium.org  CcTest::InitializeVM();
234c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // Allocate an executable page of memory.
235c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  size_t actual_size;
2365de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
2375de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      Assembler::kMinimalBufferSize, &actual_size, true));
238c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  CHECK(buffer);
239c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
240c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
241c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ movq(rax, Operand(arg2, 0));
242c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ orl(Operand(arg1, 0), rax);
243c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ ret(0);
244c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
245c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  CodeDesc desc;
246c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  assm.GetCode(&desc);
247c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // Call the function from C++.
248c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  int64_t left   = V8_2PART_UINT64_C(0x10000000, 20000000);
249c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  int64_t right  = V8_2PART_UINT64_C(0x30000000, 40000000);
250c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  int64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right);
251c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  CHECK_EQ(V8_2PART_UINT64_C(0x10000000, 60000000), left);
252c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  USE(result);
253c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org}
254c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
255c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
256c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.orgTEST(AssemblerX64RollOperations) {
257874aad37f2a832804012c6f56739f4fc6c9283cdmachenbach@chromium.org  CcTest::InitializeVM();
258c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // Allocate an executable page of memory.
259c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  size_t actual_size;
2605de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
2615de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      Assembler::kMinimalBufferSize, &actual_size, true));
262c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  CHECK(buffer);
263c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
264c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
265c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ movq(rax, arg1);
266c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ roll(rax, Immediate(1));
267c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ ret(0);
268c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
269c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  CodeDesc desc;
270c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  assm.GetCode(&desc);
271c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // Call the function from C++.
272c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  int64_t src    = V8_2PART_UINT64_C(0x10000000, C0000000);
273c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  int64_t result = FUNCTION_CAST<F5>(buffer)(src);
274c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  CHECK_EQ(V8_2PART_UINT64_C(0x00000000, 80000001), result);
275c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org}
276c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
277c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
278c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.orgTEST(AssemblerX64SublOperations) {
279874aad37f2a832804012c6f56739f4fc6c9283cdmachenbach@chromium.org  CcTest::InitializeVM();
280c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // Allocate an executable page of memory.
281c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  size_t actual_size;
2825de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
2835de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      Assembler::kMinimalBufferSize, &actual_size, true));
284c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  CHECK(buffer);
285c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
286c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
287c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ movq(rax, Operand(arg2, 0));
288c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ subl(Operand(arg1, 0), rax);
289c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ ret(0);
290c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
291c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  CodeDesc desc;
292c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  assm.GetCode(&desc);
293c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // Call the function from C++.
294c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  int64_t left   = V8_2PART_UINT64_C(0x10000000, 20000000);
295c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  int64_t right  = V8_2PART_UINT64_C(0x30000000, 40000000);
296c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  int64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right);
297c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  CHECK_EQ(V8_2PART_UINT64_C(0x10000000, e0000000), left);
298c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  USE(result);
299c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org}
300c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
301c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
302c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.orgTEST(AssemblerX64TestlOperations) {
303874aad37f2a832804012c6f56739f4fc6c9283cdmachenbach@chromium.org  CcTest::InitializeVM();
304c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // Allocate an executable page of memory.
305c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  size_t actual_size;
3065de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
3075de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      Assembler::kMinimalBufferSize, &actual_size, true));
308c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  CHECK(buffer);
309c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
310c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
311c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // Set rax with the ZF flag of the testl instruction.
312c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  Label done;
313c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ movq(rax, Immediate(1));
31425530ce9cb50f9e8386663ca40fd3f6e023ec9f6bmeurer@chromium.org  __ movq(r11, Operand(arg2, 0));
31525530ce9cb50f9e8386663ca40fd3f6e023ec9f6bmeurer@chromium.org  __ testl(Operand(arg1, 0), r11);
316c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ j(zero, &done, Label::kNear);
317c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ movq(rax, Immediate(0));
318c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ bind(&done);
319c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ ret(0);
320c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
321c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  CodeDesc desc;
322c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  assm.GetCode(&desc);
323c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // Call the function from C++.
324c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  int64_t left   = V8_2PART_UINT64_C(0x10000000, 20000000);
325c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  int64_t right  = V8_2PART_UINT64_C(0x30000000, 00000000);
326c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  int64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right);
327c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  CHECK_EQ(static_cast<int64_t>(1), result);
328c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org}
329c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
330c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
331c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.orgTEST(AssemblerX64XorlOperations) {
332874aad37f2a832804012c6f56739f4fc6c9283cdmachenbach@chromium.org  CcTest::InitializeVM();
333c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // Allocate an executable page of memory.
334c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  size_t actual_size;
3355de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
3365de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      Assembler::kMinimalBufferSize, &actual_size, true));
337c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  CHECK(buffer);
338c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
339c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
340c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ movq(rax, Operand(arg2, 0));
341c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ xorl(Operand(arg1, 0), rax);
342c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ ret(0);
343c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
344c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  CodeDesc desc;
345c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  assm.GetCode(&desc);
346c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // Call the function from C++.
347c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  int64_t left   = V8_2PART_UINT64_C(0x10000000, 20000000);
348c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  int64_t right  = V8_2PART_UINT64_C(0x30000000, 60000000);
349c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  int64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right);
350c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  CHECK_EQ(V8_2PART_UINT64_C(0x10000000, 40000000), left);
351c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  USE(result);
352c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org}
353c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
354c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
355755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.orgTEST(AssemblerX64MemoryOperands) {
356874aad37f2a832804012c6f56739f4fc6c9283cdmachenbach@chromium.org  CcTest::InitializeVM();
357755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Allocate an executable page of memory.
358755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  size_t actual_size;
3595de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
3605de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      Assembler::kMinimalBufferSize, &actual_size, true));
361755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  CHECK(buffer);
362528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
363755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
364755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Assemble a simple function that copies argument 2 and returns it.
365763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(rbp);
366755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ movq(rbp, rsp);
3679d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
368763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(arg2);  // Value at (rbp - 8)
369763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(arg2);  // Value at (rbp - 16)
370763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(arg1);  // Value at (rbp - 24)
3719d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
372755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  const int kStackElementSize = 8;
373755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ movq(rax, Operand(rbp, -3 * kStackElementSize));
374763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(arg2);
375763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(arg2);
376763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(arg2);
377763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rbp);
378755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ nop();
379755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ ret(0);
380755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
381755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  CodeDesc desc;
382755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  assm.GetCode(&desc);
383755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Call the function from C++.
384755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  int result =  FUNCTION_CAST<F2>(buffer)(3, 2);
385755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  CHECK_EQ(3, result);
386755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org}
387755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
388e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
389755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.orgTEST(AssemblerX64ControlFlow) {
390874aad37f2a832804012c6f56739f4fc6c9283cdmachenbach@chromium.org  CcTest::InitializeVM();
391755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Allocate an executable page of memory.
392755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  size_t actual_size;
3935de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
3945de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      Assembler::kMinimalBufferSize, &actual_size, true));
395755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  CHECK(buffer);
396528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
397755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
3989d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // Assemble a simple function that copies argument 1 and returns it.
399763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(rbp);
4009d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
401755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ movq(rbp, rsp);
4029d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  __ movq(rax, arg1);
403755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  Label target;
404755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ jmp(&target);
4059d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  __ movq(rax, arg2);
406755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ bind(&target);
407763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rbp);
408755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ ret(0);
409755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
410755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  CodeDesc desc;
411755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  assm.GetCode(&desc);
412755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Call the function from C++.
413755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  int result =  FUNCTION_CAST<F2>(buffer)(3, 2);
414755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  CHECK_EQ(3, result);
415755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org}
416755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
417e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
418755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.orgTEST(AssemblerX64LoopImmediates) {
419874aad37f2a832804012c6f56739f4fc6c9283cdmachenbach@chromium.org  CcTest::InitializeVM();
420755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Allocate an executable page of memory.
421755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  size_t actual_size;
4225de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
4235de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      Assembler::kMinimalBufferSize, &actual_size, true));
424755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  CHECK(buffer);
425528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
426755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Assemble two loops using rax as counter, and verify the ending counts.
427755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  Label Fail;
428755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ movq(rax, Immediate(-3));
429755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  Label Loop1_test;
430755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  Label Loop1_body;
431755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ jmp(&Loop1_test);
432755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ bind(&Loop1_body);
433eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  __ addq(rax, Immediate(7));
434755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ bind(&Loop1_test);
435eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  __ cmpq(rax, Immediate(20));
436755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ j(less_equal, &Loop1_body);
437755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Did the loop terminate with the expected value?
438eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  __ cmpq(rax, Immediate(25));
439755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ j(not_equal, &Fail);
440755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
441755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  Label Loop2_test;
442755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  Label Loop2_body;
443755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ movq(rax, Immediate(0x11FEED00));
444755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ jmp(&Loop2_test);
445755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ bind(&Loop2_body);
446eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  __ addq(rax, Immediate(-0x1100));
447755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ bind(&Loop2_test);
448eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  __ cmpq(rax, Immediate(0x11FE8000));
449755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ j(greater, &Loop2_body);
450755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Did the loop terminate with the expected value?
451eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  __ cmpq(rax, Immediate(0x11FE7600));
452755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ j(not_equal, &Fail);
453755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
454755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ movq(rax, Immediate(1));
455755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ ret(0);
456755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ bind(&Fail);
457755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ movq(rax, Immediate(0));
458755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  __ ret(0);
459755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
460755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  CodeDesc desc;
461755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  assm.GetCode(&desc);
462755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Call the function from C++.
463755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  int result =  FUNCTION_CAST<F0>(buffer)();
464755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  CHECK_EQ(1, result);
465755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org}
466eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
4670ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
4680ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.orgTEST(OperandRegisterDependency) {
4690ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  int offsets[4] = {0, 1, 0xfed, 0xbeefcad};
4700ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  for (int i = 0; i < 4; i++) {
4710ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    int offset = offsets[i];
4720ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(Operand(rax, offset).AddressUsesRegister(rax));
4730ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(!Operand(rax, offset).AddressUsesRegister(r8));
4740ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(!Operand(rax, offset).AddressUsesRegister(rcx));
4750ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
4760ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(Operand(rax, rax, times_1, offset).AddressUsesRegister(rax));
4770ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(!Operand(rax, rax, times_1, offset).AddressUsesRegister(r8));
4780ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(!Operand(rax, rax, times_1, offset).AddressUsesRegister(rcx));
4790ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
4800ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(Operand(rax, rcx, times_1, offset).AddressUsesRegister(rax));
4810ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(Operand(rax, rcx, times_1, offset).AddressUsesRegister(rcx));
4820ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(!Operand(rax, rcx, times_1, offset).AddressUsesRegister(r8));
4830ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(!Operand(rax, rcx, times_1, offset).AddressUsesRegister(r9));
4840ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(!Operand(rax, rcx, times_1, offset).AddressUsesRegister(rdx));
4850ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(!Operand(rax, rcx, times_1, offset).AddressUsesRegister(rsp));
4860ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
4870ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(Operand(rsp, offset).AddressUsesRegister(rsp));
4880ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(!Operand(rsp, offset).AddressUsesRegister(rax));
489b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org    CHECK(!Operand(rsp, offset).AddressUsesRegister(r15));
4900ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
4910ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(Operand(rbp, offset).AddressUsesRegister(rbp));
4920ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(!Operand(rbp, offset).AddressUsesRegister(rax));
4930ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(!Operand(rbp, offset).AddressUsesRegister(r13));
4940ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
4950ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(Operand(rbp, rax, times_1, offset).AddressUsesRegister(rbp));
4960ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(Operand(rbp, rax, times_1, offset).AddressUsesRegister(rax));
4970ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(!Operand(rbp, rax, times_1, offset).AddressUsesRegister(rcx));
4980ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(!Operand(rbp, rax, times_1, offset).AddressUsesRegister(r13));
4990ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(!Operand(rbp, rax, times_1, offset).AddressUsesRegister(r8));
5000ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(!Operand(rbp, rax, times_1, offset).AddressUsesRegister(rsp));
5010ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
5020ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(Operand(rsp, rbp, times_1, offset).AddressUsesRegister(rsp));
5030ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(Operand(rsp, rbp, times_1, offset).AddressUsesRegister(rbp));
5040ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(!Operand(rsp, rbp, times_1, offset).AddressUsesRegister(rax));
505b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org    CHECK(!Operand(rsp, rbp, times_1, offset).AddressUsesRegister(r15));
5060ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    CHECK(!Operand(rsp, rbp, times_1, offset).AddressUsesRegister(r13));
5070ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  }
5080ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org}
5090ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
51080c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org
51180c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.orgTEST(AssemblerX64LabelChaining) {
51280c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  // Test chaining of label usages within instructions (issue 1644).
513e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  CcTest::InitializeVM();
514e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  v8::HandleScope scope(CcTest::isolate());
515528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Assembler assm(CcTest::i_isolate(), NULL, 0);
51680c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org
51780c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  Label target;
51880c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  __ j(equal, &target);
51980c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  __ j(not_equal, &target);
52080c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  __ bind(&target);
52180c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  __ nop();
52280c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org}
52380c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org
52464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
52564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.orgTEST(AssemblerMultiByteNop) {
526e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  CcTest::InitializeVM();
527e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  v8::HandleScope scope(CcTest::isolate());
528b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  byte buffer[1024];
529528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Isolate* isolate = CcTest::i_isolate();
53009d7ab5aba54ebac170eac755664c45eefb0be7dulan@chromium.org  Assembler assm(isolate, buffer, sizeof(buffer));
531763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(rbx);
532763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(rcx);
533763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(rdx);
534763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(rdi);
535763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(rsi);
53664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ movq(rax, Immediate(1));
53764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ movq(rbx, Immediate(2));
53864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ movq(rcx, Immediate(3));
53964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ movq(rdx, Immediate(4));
54064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ movq(rdi, Immediate(5));
54164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ movq(rsi, Immediate(6));
54264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  for (int i = 0; i < 16; i++) {
54364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    int before = assm.pc_offset();
54464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ Nop(i);
54564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    CHECK_EQ(assm.pc_offset() - before, i);
54664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  }
54764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
54864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  Label fail;
54964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ cmpq(rax, Immediate(1));
55064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ j(not_equal, &fail);
55164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ cmpq(rbx, Immediate(2));
55264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ j(not_equal, &fail);
55364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ cmpq(rcx, Immediate(3));
55464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ j(not_equal, &fail);
55564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ cmpq(rdx, Immediate(4));
55664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ j(not_equal, &fail);
55764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ cmpq(rdi, Immediate(5));
55864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ j(not_equal, &fail);
55964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ cmpq(rsi, Immediate(6));
56064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ j(not_equal, &fail);
56164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ movq(rax, Immediate(42));
562763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rsi);
563763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rdi);
564763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rdx);
565763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rcx);
566763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rbx);
56764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ ret(0);
56864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ bind(&fail);
56964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ movq(rax, Immediate(13));
570763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rsi);
571763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rdi);
572763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rdx);
573763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rcx);
574763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rbx);
57564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ ret(0);
57664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
57764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  CodeDesc desc;
57864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  assm.GetCode(&desc);
5799fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org  Handle<Code> code = isolate->factory()->NewCode(
5809fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
58164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
58264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  F0 f = FUNCTION_CAST<F0>(code->entry());
58364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  int res = f();
58464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  CHECK_EQ(42, res);
58564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org}
58664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
58764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
588e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org#ifdef __GNUC__
589e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org#define ELEMENT_COUNT 4
590e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
591e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.orgvoid DoSSE2(const v8::FunctionCallbackInfo<v8::Value>& args) {
592e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  v8::HandleScope scope(CcTest::isolate());
593b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  byte buffer[1024];
594e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
595e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  CHECK(args[0]->IsArray());
596e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  v8::Local<v8::Array> vec = v8::Local<v8::Array>::Cast(args[0]);
597e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  CHECK_EQ(ELEMENT_COUNT, vec->Length());
598e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
599528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Isolate* isolate = CcTest::i_isolate();
600e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  Assembler assm(isolate, buffer, sizeof(buffer));
601e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
602e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  // Remove return address from the stack for fix stack frame alignment.
603763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rcx);
604e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
605e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  // Store input vector on the stack.
606e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  for (int i = 0; i < ELEMENT_COUNT; i++) {
607e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org    __ movl(rax, Immediate(vec->Get(i)->Int32Value()));
6082f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    __ shlq(rax, Immediate(0x20));
609895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    __ orq(rax, Immediate(vec->Get(++i)->Int32Value()));
610763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ pushq(rax);
611e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  }
612e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
613e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  // Read vector into a xmm register.
614e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  __ xorps(xmm0, xmm0);
615e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  __ movdqa(xmm0, Operand(rsp, 0));
616e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  // Create mask and store it in the return register.
617e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  __ movmskps(rax, xmm0);
618e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
619e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  // Remove unused data from the stack.
620e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  __ addq(rsp, Immediate(ELEMENT_COUNT * sizeof(int32_t)));
621e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  // Restore return address.
622763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(rcx);
623e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
624e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  __ ret(0);
625e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
626e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  CodeDesc desc;
627e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  assm.GetCode(&desc);
6289fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org  Handle<Code> code = isolate->factory()->NewCode(
6299fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
630e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
631e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  F0 f = FUNCTION_CAST<F0>(code->entry());
632e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  int res = f();
6330f13e74b7310d8b14f19c6b93b36ff95059f97f6ulan@chromium.org  args.GetReturnValue().Set(v8::Integer::New(CcTest::isolate(), res));
634e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org}
635e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
636e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
637e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.orgTEST(StackAlignmentForSSE2) {
638528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  CcTest::InitializeVM();
6395de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  CHECK_EQ(0, v8::base::OS::ActivationFrameAlignment() % 16);
640e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
641528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  v8::Isolate* isolate = CcTest::isolate();
642e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  v8::HandleScope handle_scope(isolate);
6439cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org  v8::Handle<v8::ObjectTemplate> global_template =
6449cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org      v8::ObjectTemplate::New(isolate);
6454f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org  global_template->Set(v8_str("do_sse2"),
6464f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org                       v8::FunctionTemplate::New(isolate, DoSSE2));
647e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
648e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  LocalContext env(NULL, global_template);
649e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  CompileRun(
650e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org      "function foo(vec) {"
651e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org      "  return do_sse2(vec);"
652e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org      "}");
653e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
654e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  v8::Local<v8::Object> global_object = env->Global();
655e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  v8::Local<v8::Function> foo =
656e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org      v8::Local<v8::Function>::Cast(global_object->Get(v8_str("foo")));
657e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
658e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  int32_t vec[ELEMENT_COUNT] = { -1, 1, 1, 1 };
6599f18d9111f676f2899d9aa2444130c985eb75395machenbach@chromium.org  v8::Local<v8::Array> v8_vec = v8::Array::New(isolate, ELEMENT_COUNT);
660e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  for (int i = 0; i < ELEMENT_COUNT; i++) {
661e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org    v8_vec->Set(i, v8_num(vec[i]));
662e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  }
663e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
664e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  v8::Local<v8::Value> args[] = { v8_vec };
665e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  v8::Local<v8::Value> result = foo->Call(global_object, 1, args);
666e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
667e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  // The mask should be 0b1000.
668e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  CHECK_EQ(8, result->Int32Value());
669e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org}
670e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
671e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org#undef ELEMENT_COUNT
672e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org#endif  // __GNUC__
67364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
67464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
675b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.orgTEST(AssemblerX64Extractps) {
676b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  CcTest::InitializeVM();
677b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  if (!CpuFeatures::IsSupported(SSE4_1)) return;
678b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org
679b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  v8::HandleScope scope(CcTest::isolate());
680b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  byte buffer[256];
681b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  Isolate* isolate = CcTest::i_isolate();
682b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  Assembler assm(isolate, buffer, sizeof(buffer));
683b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  { CpuFeatureScope fscope2(&assm, SSE4_1);
684b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org    __ extractps(rax, xmm0, 0x1);
685b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org    __ ret(0);
686b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  }
687b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org
688b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  CodeDesc desc;
689b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  assm.GetCode(&desc);
6909fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org  Handle<Code> code = isolate->factory()->NewCode(
6919fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
692b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org#ifdef OBJECT_PRINT
693f15d0cdbef11a212e108432465f014a7d3c3aa12machenbach@chromium.org  OFStream os(stdout);
694f15d0cdbef11a212e108432465f014a7d3c3aa12machenbach@chromium.org  code->Print(os);
695b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org#endif
696b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org
6979fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org  F3 f = FUNCTION_CAST<F3>(code->entry());
698b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  uint64_t value1 = V8_2PART_UINT64_C(0x12345678, 87654321);
699b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  CHECK_EQ(0x12345678, f(uint64_to_double(value1)));
700b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  uint64_t value2 = V8_2PART_UINT64_C(0x87654321, 12345678);
701b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org  CHECK_EQ(0x87654321, f(uint64_to_double(value2)));
702b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org}
703b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org
704b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org
705af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.orgtypedef int (*F6)(float x, float y);
706af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.orgTEST(AssemblerX64SSE) {
707af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  CcTest::InitializeVM();
708af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org
709af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
710af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  HandleScope scope(isolate);
711af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  v8::internal::byte buffer[256];
712af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  MacroAssembler assm(isolate, buffer, sizeof buffer);
713af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  {
714af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    __ shufps(xmm0, xmm0, 0x0);  // brocast first argument
715af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    __ shufps(xmm1, xmm1, 0x0);  // brocast second argument
716af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    __ movaps(xmm2, xmm1);
717af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    __ addps(xmm2, xmm0);
718af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    __ mulps(xmm2, xmm1);
719af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    __ subps(xmm2, xmm0);
720af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    __ divps(xmm2, xmm1);
721af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    __ cvttss2si(rax, xmm2);
722af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    __ ret(0);
723af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  }
724af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org
725af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  CodeDesc desc;
726af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  assm.GetCode(&desc);
7279fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org  Handle<Code> code = isolate->factory()->NewCode(
728af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org      desc,
729af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org      Code::ComputeFlags(Code::STUB),
7309fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org      Handle<Code>());
731af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org#ifdef OBJECT_PRINT
732f15d0cdbef11a212e108432465f014a7d3c3aa12machenbach@chromium.org  OFStream os(stdout);
733f15d0cdbef11a212e108432465f014a7d3c3aa12machenbach@chromium.org  code->Print(os);
734af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org#endif
735af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org
7369fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org  F6 f = FUNCTION_CAST<F6>(code->entry());
737af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  CHECK_EQ(2, f(1.0, 2.0));
738af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org}
739755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org#undef __
740