assembler-x64.h revision 014dc512cdd3e367bee49a713fdc5ed92584a3e5
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright (c) 1994-2006 Sun Microsystems Inc.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// All Rights Reserved.
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// - Redistributions of source code must retain the above copyright notice,
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// this list of conditions and the following disclaimer.
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// - Redistribution in binary form must reproduce the above copyright
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer in the
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// documentation and/or other materials provided with the distribution.
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// - Neither the name of Sun Microsystems or the names of contributors may
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// be used to endorse or promote products derived from this software without
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// specific prior written permission.
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The original source code covered by the above license above has been
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modified significantly by Google Inc.
333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A lightweight X64 Assembler.
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_X64_ASSEMBLER_X64_H_
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_X64_ASSEMBLER_X64_H_
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include <deque>
41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/assembler.h"
43d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Utility functions
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define GENERAL_REGISTERS(V) \
50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(rax)                     \
51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(rcx)                     \
52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(rdx)                     \
53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(rbx)                     \
54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(rsp)                     \
55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(rbp)                     \
56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(rsi)                     \
57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(rdi)                     \
58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r8)                      \
59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r9)                      \
60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r10)                     \
61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r11)                     \
62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r12)                     \
63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r13)                     \
64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r14)                     \
65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r15)
66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define ALLOCATABLE_GENERAL_REGISTERS(V) \
68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(rax)                                 \
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(rbx)                                 \
70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(rdx)                                 \
71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(rcx)                                 \
72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(rsi)                                 \
73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(rdi)                                 \
74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r8)                                  \
75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r9)                                  \
76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r11)                                 \
77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r12)                                 \
78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r14)                                 \
79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(r15)
80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CPU Registers.
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 1) We would prefer to use an enum, but enum values are assignment-
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// compatible with int, which has caused code-generation bugs.
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 2) We would prefer to use a class instead of a struct but we don't like
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the register initialization to depend on the particular initialization
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// order (which appears to be different on OS X, Linux, and Windows for the
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// installed versions of C++ we tried). Using a struct permits C-style
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "initialization". Also, the Register objects cannot be const as this
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// forces initialization stubs in MSVC, making us dependent on initialization
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// order.
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 3) By not using an enum, we are possibly preventing the compiler from
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// doing certain constant folds, which may significantly reduce the
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// code generated for some assembly instructions (because they boil down
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to a few constants). If this is a problem, we could change the code
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// such that we use an enum in optimized mode, and the struct in debug
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// mode. This way we get the compile-time error checking in debug mode
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and best performance in optimized code.
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct Register {
104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  enum Code {
105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define REGISTER_CODE(R) kCode_##R,
106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GENERAL_REGISTERS(REGISTER_CODE)
107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef REGISTER_CODE
108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        kAfterLast,
109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    kCode_no_reg = -1
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  };
111b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kNumRegisters = Code::kAfterLast;
113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static Register from_code(int code) {
115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(code >= 0);
116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(code < kNumRegisters);
117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register r = {code};
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return r;
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const char* ToString();
121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool IsAllocatable() const;
122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is(Register reg) const { return reg_code == reg.reg_code; }
1240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int code() const {
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(is_valid());
126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return reg_code;
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int bit() const {
129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(is_valid());
130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return 1 << reg_code;
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is_byte_register() const { return reg_code <= 3; }
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the high bit of the register code as a 0 or 1.  Used often
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // when constructing the REX prefix byte.
136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int high_bit() const { return reg_code >> 3; }
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the 3 low bits of the register code.  Used when encoding registers
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in modR/M, SIB, and opcode bytes.
139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int low_bits() const { return reg_code & 0x7; }
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Unfortunately we can't make this private in a struct when initializing
1423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // by assignment.
143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int reg_code;
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochGENERAL_REGISTERS(DECLARE_REGISTER)
149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef DECLARE_REGISTER
150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register no_reg = {Register::kCode_no_reg};
151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef _WIN64
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Windows calling convention
155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register arg_reg_1 = {Register::kCode_rcx};
156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register arg_reg_2 = {Register::kCode_rdx};
157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register arg_reg_3 = {Register::kCode_r8};
158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register arg_reg_4 = {Register::kCode_r9};
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // AMD64 calling convention
161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register arg_reg_1 = {Register::kCode_rdi};
162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register arg_reg_2 = {Register::kCode_rsi};
163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register arg_reg_3 = {Register::kCode_rdx};
164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register arg_reg_4 = {Register::kCode_rcx};
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // _WIN64
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define DOUBLE_REGISTERS(V) \
169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm0)                   \
170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm1)                   \
171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm2)                   \
172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm3)                   \
173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm4)                   \
174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm5)                   \
175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm6)                   \
176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm7)                   \
177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm8)                   \
178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm9)                   \
179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm10)                  \
180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm11)                  \
181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm12)                  \
182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm13)                  \
183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm14)                  \
184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm15)
185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm1)                               \
188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm2)                               \
189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm3)                               \
190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm4)                               \
191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm5)                               \
192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm6)                               \
193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm7)                               \
194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm8)                               \
195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm9)                               \
196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm10)                              \
197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm11)                              \
198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm12)                              \
199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm13)                              \
200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm14)                              \
201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(xmm15)
202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstruct DoubleRegister {
205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  enum Code {
206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define REGISTER_CODE(R) kCode_##R,
207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DOUBLE_REGISTERS(REGISTER_CODE)
208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef REGISTER_CODE
209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        kAfterLast,
210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    kCode_no_reg = -1
211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  };
212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kMaxNumRegisters = Code::kAfterLast;
214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static DoubleRegister from_code(int code) {
216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DoubleRegister result = {code};
217b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return result;
218b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
219b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const char* ToString();
221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool IsAllocatable() const;
222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
2240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int code() const {
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(is_valid());
226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return reg_code;
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the high bit of the register code as a 0 or 1.  Used often
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // when constructing the REX prefix byte.
231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int high_bit() const { return reg_code >> 3; }
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the 3 low bits of the register code.  Used when encoding registers
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in modR/M, SIB, and opcode bytes.
234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int low_bits() const { return reg_code & 0x7; }
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Unfortunately we can't make this private in a struct when initializing
237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // by assignment.
238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int reg_code;
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define DECLARE_REGISTER(R) \
243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const DoubleRegister R = {DoubleRegister::kCode_##R};
244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochDOUBLE_REGISTERS(DECLARE_REGISTER)
245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef DECLARE_REGISTER
246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister no_double_reg = {DoubleRegister::kCode_no_reg};
247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtypedef DoubleRegister XMMRegister;
250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum Condition {
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // any value < 0 is considered no_condition
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  no_condition  = -1,
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  overflow      =  0,
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  no_overflow   =  1,
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  below         =  2,
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  above_equal   =  3,
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  equal         =  4,
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  not_equal     =  5,
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  below_equal   =  6,
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  above         =  7,
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  negative      =  8,
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  positive      =  9,
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  parity_even   = 10,
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  parity_odd    = 11,
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  less          = 12,
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  greater_equal = 13,
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  less_equal    = 14,
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  greater       = 15,
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Fake conditions that are handled by the
2733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // opcodes using them.
2743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  always        = 16,
2753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  never         = 17,
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // aliases
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  carry         = below,
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  not_carry     = above_equal,
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  zero          = equal,
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  not_zero      = not_equal,
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  sign          = negative,
2823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  not_sign      = positive,
2833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  last_condition = greater
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns the equivalent of !cc.
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Negation of the default no_condition (-1) results in a non-default
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// no_condition value (-2). As long as tests for no_condition check
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// for condition < 0, this will work as expected.
2919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monseninline Condition NegateCondition(Condition cc) {
2929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  return static_cast<Condition>(cc ^ 1);
2939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
2949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Commute a condition such that {a cond b == b cond' a}.
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Condition CommuteCondition(Condition cc) {
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (cc) {
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case below:
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return above;
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case above:
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return below;
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case above_equal:
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return below_equal;
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case below_equal:
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return above_equal;
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case less:
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return greater;
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case greater:
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return less;
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case greater_equal:
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return less_equal;
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case less_equal:
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return greater_equal;
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return cc;
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochenum RoundingMode {
322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  kRoundToNearest = 0x0,
323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  kRoundDown = 0x1,
324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  kRoundUp = 0x2,
325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  kRoundToZero = 0x3
326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Machine instruction Immediates
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Immediate BASE_EMBEDDED {
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit Immediate(int32_t value) : value_(value) {}
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit Immediate(Smi* value) {
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(SmiValuesAre31Bits());  // Only available for 31-bit SMI.
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    value_ = static_cast<int32_t>(reinterpret_cast<intptr_t>(value));
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int32_t value_;
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class Assembler;
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Machine instruction Operands
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum ScaleFactor {
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_1 = 0,
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_2 = 1,
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_4 = 2,
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_8 = 3,
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_int_size = times_4,
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  times_pointer_size = (kPointerSize == 8) ? times_8 : times_4
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Operand BASE_EMBEDDED {
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // [base + disp/r]
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Operand(Register base, int32_t disp);
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // [base + index*scale + disp/r]
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Operand(Register base,
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Register index,
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          ScaleFactor scale,
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int32_t disp);
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // [index*scale + disp/r]
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Operand(Register index,
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          ScaleFactor scale,
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int32_t disp);
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
376f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Offset from existing memory operand.
377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Offset is added to existing displacement as 32-bit signed values and
378f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // this must not overflow.
379f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Operand(const Operand& base, int32_t offset);
380f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // [rip + disp/r]
382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit Operand(Label* label);
383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Checks whether either base or index register is the given register.
3851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Does not check the "reg" part of the Operand.
3861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool AddressUsesRegister(Register reg) const;
3871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
38844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Queries related to the size of the generated instruction.
38944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Whether the generated instruction will have a REX prefix.
39044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool requires_rex() const { return rex_ != 0; }
39144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Size of the ModR/M, SIB and displacement parts of the generated
39244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // instruction.
39344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int operand_size() const { return len_; }
39444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte rex_;
397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  byte buf_[9];
3981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The number of bytes of buf_ in use.
3991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  byte len_;
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the ModR/M byte without an encoded 'reg' register. The
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // register is encoded later as part of the emit_operand operation.
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // set_modrm can be called before or after set_sib and set_disp*.
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void set_modrm(int mod, Register rm);
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the SIB byte if one is needed. Sets the length to 2 rather than 1.
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void set_sib(ScaleFactor scale, Register index, Register base);
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adds operand displacement fields (offsets added to the memory address).
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Needs to be called after set_sib, not before it.
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void set_disp8(int disp);
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void set_disp32(int disp);
413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void set_disp64(int64_t disp);  // for labels.
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class Assembler;
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ASSEMBLER_INSTRUCTION_LIST(V) \
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(add)                              \
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(and)                              \
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(cmp)                              \
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(dec)                              \
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(idiv)                             \
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(div)                              \
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(imul)                             \
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(inc)                              \
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(lea)                              \
429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(mov)                              \
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(movzxb)                           \
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(movzxw)                           \
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(neg)                              \
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(not)                              \
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(or)                               \
435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(repmovs)                          \
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(sbb)                              \
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(sub)                              \
438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(test)                             \
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(xchg)                             \
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(xor)
441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Shift instructions on operands/registers with kPointerSize, kInt32Size and
444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// kInt64Size.
445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define SHIFT_INSTRUCTION_LIST(V)       \
446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(rol, 0x0)                           \
447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(ror, 0x1)                           \
448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(rcl, 0x2)                           \
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(rcr, 0x3)                           \
450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(shl, 0x4)                           \
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(shr, 0x5)                           \
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V(sar, 0x7)                           \
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
45544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass Assembler : public AssemblerBase {
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We check before assembling an instruction that there is sufficient
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // space to write an instruction and its relocation information.
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The relocation writer's position must be kGap bytes above the end of
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the generated instructions. This leaves enough space for the
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // longest possible x64 instruction, 15 bytes, and the longest possible
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // (There is a 15 byte limit on x64 instruction length that rules out some
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // otherwise valid instructions.)
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This allows for a single, fast space check per instruction.
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kGap = 32;
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create an assembler. Instructions and relocation information are emitted
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // into a buffer, with the instructions starting from the beginning and the
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // relocation information starting from the end of the buffer. See CodeDesc
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // for a detailed comment on the layout (globals.h).
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the provided buffer is NULL, the assembler allocates and grows its own
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // buffer, and buffer_size determines the initial buffer size. The buffer is
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // owned by the assembler and deallocated upon destruction of the assembler.
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the provided buffer is not NULL, the assembler uses the provided buffer
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // for code generation and assumes its size to be buffer_size. If the buffer
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is too small, a fatal error occurs. No deallocation of the buffer is done
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // upon destruction of the assembler.
4828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Assembler(Isolate* isolate, void* buffer, int buffer_size);
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual ~Assembler() { }
48444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // GetCode emits any pending (non-emitted) code and fills the descriptor
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // desc. GetCode() is idempotent; it returns the same result if no other
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Assembler functions are invoked in between GetCode() calls.
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void GetCode(CodeDesc* desc);
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Read/Modify the code target in the relative branch/call instruction at pc.
4913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // On the x64 architecture, we use relative jumps with a 32-bit displacement
4923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // to jump to other Code objects in the Code space in the heap.
4933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Jumps to C functions are done indirectly through a 64-bit register holding
4943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // the absolute address of the target.
4953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // These functions convert between absolute Addresses of Code objects and
4963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // the relative displacements stored in the code.
497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static inline Address target_address_at(Address pc, Address constant_pool);
498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static inline void set_target_address_at(
499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Isolate* isolate, Address pc, Address constant_pool, Address target,
500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline Address target_address_at(Address pc, Code* code) {
502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Address constant_pool = code ? code->constant_pool() : NULL;
503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return target_address_at(pc, constant_pool);
504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static inline void set_target_address_at(
506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Isolate* isolate, Address pc, Code* code, Address target,
507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED) {
508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Address constant_pool = code ? code->constant_pool() : NULL;
509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    set_target_address_at(isolate, pc, constant_pool, target,
510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                          icache_flush_mode);
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Return the code target address at a call site from the return address
514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // of that call in the instruction stream.
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline Address target_address_from_return_address(Address pc);
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
517d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This sets the branch destination (which is in the instruction on x64).
518d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This is for calls and branches within generated code.
5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline static void deserialization_set_special_target_at(
520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Isolate* isolate, Address instruction_payload, Code* code,
521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Address target) {
522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    set_target_address_at(isolate, instruction_payload, code, target);
523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
524d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // This sets the internal reference at the pc.
526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline static void deserialization_set_target_internal_reference_at(
527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Isolate* isolate, Address pc, Address target,
528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline RelocInfo::Mode RelocInfoNone() {
531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (kPointerSize == kInt64Size) {
532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return RelocInfo::NONE64;
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(kPointerSize == kInt32Size);
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return RelocInfo::NONE32;
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
537d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
538d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  inline Handle<Object> code_target_object_handle_at(Address pc);
540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline Address runtime_entry_at(Address pc);
541d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Number of bytes taken up by the branch target in the code.
5423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kSpecialTargetSize = 4;  // Use 32-bit displacement.
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Distance between the address of the code target in the call instruction
5443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // and the return address pushed on the stack.
5453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  static const int kCallTargetAddressOffset = 4;  // Use 32-bit displacement.
546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The length of call(kScratchRegister).
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kCallScratchRegisterInstructionLength = 3;
548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The length of call(Immediate32).
5491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const int kShortCallInstructionLength = 5;
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The length of movq(kScratchRegister, address).
551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kMoveAddressIntoScratchRegisterInstructionLength =
552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      2 + kPointerSize;
553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The length of movq(kScratchRegister, address) and call(kScratchRegister).
554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kCallSequenceLength =
555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kMoveAddressIntoScratchRegisterInstructionLength +
556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kCallScratchRegisterInstructionLength;
557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // The debug break slot must be able to contain an indirect call sequence.
559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kDebugBreakSlotLength = kCallSequenceLength;
560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Distance between start of patched debug break slot and the emitted address
561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // to jump to.
562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kPatchDebugBreakSlotAddressOffset =
563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kMoveAddressIntoScratchRegisterInstructionLength - kPointerSize;
5647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
5659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // One byte opcode for test eax,0xXXXXXXXX.
5669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  static const byte kTestEaxByte = 0xA9;
5671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // One byte opcode for test al, 0xXX.
5681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const byte kTestAlByte = 0xA8;
5691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // One byte opcode for nop.
5701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const byte kNopByte = 0x90;
5711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // One byte prefix for a short conditional jump.
5731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const byte kJccShortPrefix = 0x70;
5741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const byte kJncShortOpcode = kJccShortPrefix | not_carry;
5751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const byte kJcShortOpcode = kJccShortPrefix | carry;
576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const byte kJnzShortOpcode = kJccShortPrefix | not_zero;
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const byte kJzShortOpcode = kJccShortPrefix | zero;
5781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // VEX prefix encodings.
580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  enum SIMDPrefix { kNone = 0x0, k66 = 0x1, kF3 = 0x2, kF2 = 0x3 };
581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  enum VectorLength { kL128 = 0x0, kL256 = 0x4, kLIG = kL128, kLZ = kL128 };
582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  enum VexW { kW0 = 0x0, kW1 = 0x80, kWIG = kW0 };
583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  enum LeadingOpcode { k0F = 0x1, k0F38 = 0x2, k0F3A = 0x3 };
5847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Code generation
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Function names correspond one-to-one to x64 instruction mnemonics.
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Unless specified otherwise, instructions operate on 64-bit operands.
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If we need versions of an assembly instruction that operate on different
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // width arguments, we add a single-letter suffix specifying the width.
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This is done for the following instructions: mov, cmp, inc, dec,
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // add, sub, and test.
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // There are no versions of these instructions without the suffix.
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'.
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // - Instructions on 16-bit (word) operands/registers have a trailing 'w'.
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // - Instructions on 32-bit (doubleword) operands/registers use 'l'.
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // - Instructions on 64-bit (quadword) operands/registers use 'q'.
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // - Instructions on operands/registers with pointer size use 'p'.
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kPointerSize == kInt64Size || kPointerSize == kInt32Size);
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DECLARE_INSTRUCTION(instruction)                \
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<class P1>                                    \
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void instruction##p(P1 p1) {                          \
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    emit_##instruction(p1, kPointerSize);               \
608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }                                                     \
609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                        \
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<class P1>                                    \
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void instruction##l(P1 p1) {                          \
612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    emit_##instruction(p1, kInt32Size);                 \
613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }                                                     \
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                        \
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<class P1>                                    \
616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void instruction##q(P1 p1) {                          \
617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    emit_##instruction(p1, kInt64Size);                 \
618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }                                                     \
619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                        \
620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<class P1, class P2>                          \
621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void instruction##p(P1 p1, P2 p2) {                   \
622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    emit_##instruction(p1, p2, kPointerSize);           \
623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }                                                     \
624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                        \
625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<class P1, class P2>                          \
626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void instruction##l(P1 p1, P2 p2) {                   \
627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    emit_##instruction(p1, p2, kInt32Size);             \
628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }                                                     \
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                        \
630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<class P1, class P2>                          \
631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void instruction##q(P1 p1, P2 p2) {                   \
632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    emit_##instruction(p1, p2, kInt64Size);             \
633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }                                                     \
634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                        \
635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<class P1, class P2, class P3>                \
636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void instruction##p(P1 p1, P2 p2, P3 p3) {            \
637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    emit_##instruction(p1, p2, p3, kPointerSize);       \
638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }                                                     \
639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                        \
640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<class P1, class P2, class P3>                \
641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void instruction##l(P1 p1, P2 p2, P3 p3) {            \
642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    emit_##instruction(p1, p2, p3, kInt32Size);         \
643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }                                                     \
644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                        \
645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<class P1, class P2, class P3>                \
646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void instruction##q(P1 p1, P2 p2, P3 p3) {            \
647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    emit_##instruction(p1, p2, p3, kInt64Size);         \
648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ASSEMBLER_INSTRUCTION_LIST(DECLARE_INSTRUCTION)
650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef DECLARE_INSTRUCTION
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Insert the smallest number of nop instructions
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // possible to align the pc offset to a multiple
6541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // of m, where m must be a power of 2.
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Align(int m);
656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Insert the smallest number of zero bytes possible to align the pc offset
657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // to a mulitple of m. m must be a power of 2 (>= 2).
658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void DataAlign(int m);
6593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Nop(int bytes = 1);
6609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Aligns code to something that's optimal for a jump target for the platform.
6619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  void CodeTargetAlign();
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stack
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void pushfq();
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void popfq();
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void pushq(Immediate value);
6681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Push a 32 bit integer, and guarantee that it is actually pushed as a
6691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // 32 bit value, the normal push will optimize the 8 bit case.
670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void pushq_imm32(int32_t imm32);
671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void pushq(Register src);
672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void pushq(const Operand& src);
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void popq(Register dst);
675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void popq(const Operand& dst);
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void enter(Immediate size);
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void leave();
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Moves
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movb(Register dst, const Operand& src);
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movb(Register dst, Immediate imm);
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movb(const Operand& dst, Register src);
684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void movb(const Operand& dst, Immediate imm);
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Move the low 16 bits of a 64-bit register value to a 16-bit
6873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // memory location.
688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void movw(Register dst, const Operand& src);
6893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void movw(const Operand& dst, Register src);
690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void movw(const Operand& dst, Immediate imm);
6913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move the offset of the label location relative to the current
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // position (after the move) to the destination.
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movl(const Operand& dst, Label* src);
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loads a pointer into a register with a relocation mode.
697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void movp(Register dst, void* ptr, RelocInfo::Mode rmode);
698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loads a 64-bit immediate into a register.
700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void movq(Register dst, int64_t value);
701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void movq(Register dst, uint64_t value);
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
703958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void movsxbl(Register dst, Register src);
704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void movsxbl(Register dst, const Operand& src);
7053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void movsxbq(Register dst, const Operand& src);
706958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void movsxwl(Register dst, Register src);
707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void movsxwl(Register dst, const Operand& src);
7083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void movsxwq(Register dst, const Operand& src);
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movsxlq(Register dst, Register src);
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movsxlq(Register dst, const Operand& src);
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
712d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Repeated moves.
713d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
714d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void repmovsb();
715d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void repmovsw();
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void repmovsp() { emit_repmovs(kPointerSize); }
717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void repmovsl() { emit_repmovs(kInt32Size); }
718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void repmovsq() { emit_repmovs(kInt64Size); }
719d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
72044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Instruction to load from an immediate 64-bit pointer into RAX.
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void load_rax(void* ptr, RelocInfo::Mode rmode);
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void load_rax(ExternalReference ext);
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Conditional moves.
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmovq(Condition cc, Register dst, Register src);
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmovq(Condition cc, Register dst, const Operand& src);
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmovl(Condition cc, Register dst, Register src);
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmovl(Condition cc, Register dst, const Operand& src);
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpb(Register dst, Immediate src) {
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_8(0x7, dst, src);
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpb_al(Immediate src);
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpb(Register dst, Register src) {
737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op_8(0x3A, dst, src);
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpb(Register dst, const Operand& src) {
741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op_8(0x3A, dst, src);
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpb(const Operand& dst, Register src) {
745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op_8(0x38, src, dst);
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpb(const Operand& dst, Immediate src) {
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_8(0x7, dst, src);
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpw(const Operand& dst, Immediate src) {
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_16(0x7, dst, src);
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpw(Register dst, Immediate src) {
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_16(0x7, dst, src);
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpw(Register dst, const Operand& src) {
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_16(0x3B, dst, src);
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpw(Register dst, Register src) {
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_16(0x3B, dst, src);
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpw(const Operand& dst, Register src) {
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_16(0x39, src, dst);
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  void andb(Register dst, Immediate src) {
7734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    immediate_arithmetic_op_8(0x4, dst, src);
7744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
7753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void decb(Register dst);
7773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void decb(const Operand& dst);
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Sign-extends rax into rdx:rax.
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cqo();
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Sign-extends eax into edx:eax.
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cdq();
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
784958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Multiply eax by src, put the result in edx:eax.
785958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mull(Register src);
786958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mull(const Operand& src);
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Multiply rax by src, put the result in rdx:rax.
788958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mulq(Register src);
789958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
790958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define DECLARE_SHIFT_INSTRUCTION(instruction, subcode)                       \
791958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void instruction##p(Register dst, Immediate imm8) {                         \
792958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    shift(dst, imm8, subcode, kPointerSize);                                  \
793958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }                                                                           \
794958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                                              \
795958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void instruction##l(Register dst, Immediate imm8) {                         \
796958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    shift(dst, imm8, subcode, kInt32Size);                                    \
797958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }                                                                           \
798958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                                              \
799958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void instruction##q(Register dst, Immediate imm8) {                         \
800958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    shift(dst, imm8, subcode, kInt64Size);                                    \
801958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }                                                                           \
802958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                                              \
803958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void instruction##p(Operand dst, Immediate imm8) {                          \
804958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    shift(dst, imm8, subcode, kPointerSize);                                  \
805958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }                                                                           \
806958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                                              \
807958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void instruction##l(Operand dst, Immediate imm8) {                          \
808958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    shift(dst, imm8, subcode, kInt32Size);                                    \
809958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }                                                                           \
810958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                                              \
811958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void instruction##q(Operand dst, Immediate imm8) {                          \
812958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    shift(dst, imm8, subcode, kInt64Size);                                    \
813958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }                                                                           \
814958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                                              \
815958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void instruction##p_cl(Register dst) { shift(dst, subcode, kPointerSize); } \
816958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                                              \
817958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void instruction##l_cl(Register dst) { shift(dst, subcode, kInt32Size); }   \
818958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                                              \
819958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void instruction##q_cl(Register dst) { shift(dst, subcode, kInt64Size); }   \
820958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                                              \
821958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void instruction##p_cl(Operand dst) { shift(dst, subcode, kPointerSize); }  \
822958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                                              \
823958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void instruction##l_cl(Operand dst) { shift(dst, subcode, kInt32Size); }    \
824958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                                              \
825958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void instruction##q_cl(Operand dst) { shift(dst, subcode, kInt64Size); }
826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SHIFT_INSTRUCTION_LIST(DECLARE_SHIFT_INSTRUCTION)
827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef DECLARE_SHIFT_INSTRUCTION
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shifts dst:src left by cl bits, affecting only dst.
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shld(Register dst, Register src);
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shifts src:dst right by cl bits, affecting only dst.
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shrd(Register dst, Register src);
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void store_rax(void* dst, RelocInfo::Mode mode);
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void store_rax(ExternalReference ref);
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subb(Register dst, Immediate src) {
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_8(0x5, dst, src);
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void testb(Register dst, Register src);
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void testb(Register reg, Immediate mask);
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void testb(const Operand& op, Immediate mask);
845e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void testb(const Operand& op, Register reg);
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Bit operations.
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void bt(const Operand& dst, Register src);
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void bts(const Operand& dst, Register src);
850014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bsrq(Register dst, Register src);
851014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bsrq(Register dst, const Operand& src);
852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bsrl(Register dst, Register src);
853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bsrl(Register dst, const Operand& src);
854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bsfq(Register dst, Register src);
855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bsfq(Register dst, const Operand& src);
856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bsfl(Register dst, Register src);
857014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bsfl(Register dst, const Operand& src);
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Miscellaneous
8603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void clc();
86144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void cld();
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cpuid();
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void hlt();
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void int3();
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void nop();
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void ret(int imm16);
867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void ud2();
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void setcc(Condition cc, Register reg);
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Label operations & relative jumps (PPUM Appendix D)
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Takes a branch opcode (cc) and a label (L) and generates
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // either a backward branch or a forward branch and links it
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to the label fixup chain. Usage:
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Label L;    // unbound label
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // j(cc, &L);  // forward branch to unbound label
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bind(&L);   // bind label to the current pc
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // j(cc, &L);  // backward branch to bound label
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bind(&L);   // illegal: a label may be bound only once
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Note: The same Label can be used for forward and backward branches
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // but it may be bound only once.
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void bind(Label* L);  // binds an unbound label L to the current code position
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calls
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call near relative 32-bit displacement, relative to next instruction.
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void call(Label* L);
890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void call(Address entry, RelocInfo::Mode rmode);
891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void call(Handle<Code> target,
8923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            TypeFeedbackId ast_id = TypeFeedbackId::None());
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Calls directly to the given address using a relative offset.
8961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Should only ever be used in Code objects for calls within the
8971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // same Code object. Should not be used when generating new code (use labels),
8981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // but only when patching existing code.
8991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void call(Address target);
9001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call near absolute indirect, address in register
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void call(Register adr);
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jumps
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump short or near relative.
9063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Use a 32-bit signed displacement.
907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Unconditional jump to L
908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void jmp(Label* L, Label::Distance distance = Label::kFar);
909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void jmp(Address entry, RelocInfo::Mode rmode);
9103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void jmp(Handle<Code> target, RelocInfo::Mode rmode);
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump near absolute indirect (r64)
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void jmp(Register adr);
914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void jmp(const Operand& src);
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Conditional jumps
917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void j(Condition cc,
918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         Label* L,
919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         Label::Distance distance = Label::kFar);
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void j(Condition cc, Address entry, RelocInfo::Mode rmode);
9213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode);
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Floating-point operations
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fld(int i);
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fld1();
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fldz();
9286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void fldpi();
929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void fldln2();
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fld_s(const Operand& adr);
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fld_d(const Operand& adr);
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fstp_s(const Operand& adr);
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fstp_d(const Operand& adr);
9363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void fstp(int index);
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fild_s(const Operand& adr);
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fild_d(const Operand& adr);
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fist_s(const Operand& adr);
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fistp_s(const Operand& adr);
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fistp_d(const Operand& adr);
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fisttp_s(const Operand& adr);
947d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void fisttp_d(const Operand& adr);
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fabs();
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fchs();
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fadd(int i);
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fsub(int i);
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fmul(int i);
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fdiv(int i);
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fisub_s(const Operand& adr);
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void faddp(int i = 1);
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fsubp(int i = 1);
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fsubrp(int i = 1);
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fmulp(int i = 1);
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fdivp(int i = 1);
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fprem();
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fprem1();
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fxch(int i = 1);
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fincstp();
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void ffree(int i = 0);
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void ftst();
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fucomp(int i);
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fucompp();
9743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void fucomi(int i);
9753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void fucomip();
9763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fcompp();
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fnstsw_ax();
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fwait();
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fnclex();
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fsin();
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fcos();
9843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void fptan();
985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void fyl2x();
9863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void f2xm1();
9873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void fscale();
9883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void fninit();
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void frndint();
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void sahf();
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // SSE instructions
995958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void addss(XMMRegister dst, XMMRegister src);
996958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void addss(XMMRegister dst, const Operand& src);
997958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void subss(XMMRegister dst, XMMRegister src);
998958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void subss(XMMRegister dst, const Operand& src);
999958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mulss(XMMRegister dst, XMMRegister src);
1000958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void mulss(XMMRegister dst, const Operand& src);
1001958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void divss(XMMRegister dst, XMMRegister src);
1002958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void divss(XMMRegister dst, const Operand& src);
1003958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void maxss(XMMRegister dst, XMMRegister src);
1005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void maxss(XMMRegister dst, const Operand& src);
1006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void minss(XMMRegister dst, XMMRegister src);
1007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void minss(XMMRegister dst, const Operand& src);
1008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void sqrtss(XMMRegister dst, XMMRegister src);
1010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void sqrtss(XMMRegister dst, const Operand& src);
1011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1012958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void ucomiss(XMMRegister dst, XMMRegister src);
1013958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void ucomiss(XMMRegister dst, const Operand& src);
1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void movaps(XMMRegister dst, XMMRegister src);
1015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Don't use this unless it's important to keep the
1017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // top half of the destination register unchanged.
1018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Use movaps when moving float values and movd for integer
1019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // values in xmm registers.
1020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void movss(XMMRegister dst, XMMRegister src);
1021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void movss(XMMRegister dst, const Operand& src);
1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void movss(const Operand& dst, XMMRegister src);
1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void shufps(XMMRegister dst, XMMRegister src, byte imm8);
1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void cvttss2si(Register dst, const Operand& src);
1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void cvttss2si(Register dst, XMMRegister src);
1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void cvtlsi2ss(XMMRegister dst, Register src);
1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void andps(XMMRegister dst, XMMRegister src);
1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void andps(XMMRegister dst, const Operand& src);
1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void orps(XMMRegister dst, XMMRegister src);
1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void orps(XMMRegister dst, const Operand& src);
1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void xorps(XMMRegister dst, XMMRegister src);
1035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void xorps(XMMRegister dst, const Operand& src);
1036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void addps(XMMRegister dst, XMMRegister src);
1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void addps(XMMRegister dst, const Operand& src);
1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void subps(XMMRegister dst, XMMRegister src);
1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void subps(XMMRegister dst, const Operand& src);
1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void mulps(XMMRegister dst, XMMRegister src);
1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void mulps(XMMRegister dst, const Operand& src);
1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void divps(XMMRegister dst, XMMRegister src);
1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void divps(XMMRegister dst, const Operand& src);
1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void movmskps(Register dst, XMMRegister src);
1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // SSE2 instructions
10496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void movd(XMMRegister dst, Register src);
1050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void movd(XMMRegister dst, const Operand& src);
10516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void movd(Register dst, XMMRegister src);
10526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void movq(XMMRegister dst, Register src);
10536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void movq(Register dst, XMMRegister src);
1054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void movq(XMMRegister dst, XMMRegister src);
10556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Don't use this unless it's important to keep the
1057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // top half of the destination register unchanged.
1058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Use movapd when moving double values and movq for integer
1059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // values in xmm registers.
1060053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  void movsd(XMMRegister dst, XMMRegister src);
1061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void movsd(const Operand& dst, XMMRegister src);
10636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void movsd(XMMRegister dst, const Operand& src);
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void movdqa(const Operand& dst, XMMRegister src);
10661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void movdqa(XMMRegister dst, const Operand& src);
10671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void movdqu(const Operand& dst, XMMRegister src);
1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void movdqu(XMMRegister dst, const Operand& src);
1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void movapd(XMMRegister dst, XMMRegister src);
1072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void psllq(XMMRegister reg, byte imm8);
1074958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void psrlq(XMMRegister reg, byte imm8);
1075958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void pslld(XMMRegister reg, byte imm8);
1076958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void psrld(XMMRegister reg, byte imm8);
10778defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cvttsd2si(Register dst, const Operand& src);
10791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void cvttsd2si(Register dst, XMMRegister src);
1080014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void cvttss2siq(Register dst, XMMRegister src);
1081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void cvttss2siq(Register dst, const Operand& src);
108225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  void cvttsd2siq(Register dst, XMMRegister src);
1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void cvttsd2siq(Register dst, const Operand& src);
1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cvtlsi2sd(XMMRegister dst, const Operand& src);
1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cvtlsi2sd(XMMRegister dst, Register src);
1087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void cvtqsi2ss(XMMRegister dst, const Operand& src);
1089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void cvtqsi2ss(XMMRegister dst, Register src);
1090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cvtqsi2sd(XMMRegister dst, const Operand& src);
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cvtqsi2sd(XMMRegister dst, Register src);
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10948defd9ff6930b4e24729971a61cf7469daf119beSteve Block
10956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void cvtss2sd(XMMRegister dst, XMMRegister src);
10968defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void cvtss2sd(XMMRegister dst, const Operand& src);
10978defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void cvtsd2ss(XMMRegister dst, XMMRegister src);
1098958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void cvtsd2ss(XMMRegister dst, const Operand& src);
10998defd9ff6930b4e24729971a61cf7469daf119beSteve Block
11008defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void cvtsd2si(Register dst, XMMRegister src);
11018defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void cvtsd2siq(Register dst, XMMRegister src);
11026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addsd(XMMRegister dst, XMMRegister src);
1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void addsd(XMMRegister dst, const Operand& src);
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subsd(XMMRegister dst, XMMRegister src);
1106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void subsd(XMMRegister dst, const Operand& src);
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void mulsd(XMMRegister dst, XMMRegister src);
1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void mulsd(XMMRegister dst, const Operand& src);
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void divsd(XMMRegister dst, XMMRegister src);
1110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void divsd(XMMRegister dst, const Operand& src);
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void maxsd(XMMRegister dst, XMMRegister src);
1113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void maxsd(XMMRegister dst, const Operand& src);
1114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void minsd(XMMRegister dst, XMMRegister src);
1115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void minsd(XMMRegister dst, const Operand& src);
1116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1117e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void andpd(XMMRegister dst, XMMRegister src);
1118e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void orpd(XMMRegister dst, XMMRegister src);
1119402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void xorpd(XMMRegister dst, XMMRegister src);
11206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void sqrtsd(XMMRegister dst, XMMRegister src);
1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void sqrtsd(XMMRegister dst, const Operand& src);
1122402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1123402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void ucomisd(XMMRegister dst, XMMRegister src);
11248defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void ucomisd(XMMRegister dst, const Operand& src);
1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void cmpltsd(XMMRegister dst, XMMRegister src);
1126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void pcmpeqd(XMMRegister dst, XMMRegister src);
1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void movmskpd(Register dst, XMMRegister src);
1129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void punpckldq(XMMRegister dst, XMMRegister src);
1131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void punpckhdq(XMMRegister dst, XMMRegister src);
1132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // SSE 4.1 instruction
1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void extractps(Register dst, XMMRegister src, byte imm8);
1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void pextrd(Register dst, XMMRegister src, int8_t imm8);
1137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void pinsrd(XMMRegister dst, Register src, int8_t imm8);
1139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void pinsrd(XMMRegister dst, const Operand& src, int8_t imm8);
1140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void roundss(XMMRegister dst, XMMRegister src, RoundingMode mode);
1142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode);
1143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // AVX instruction
1145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmadd132sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0x99, dst, src1, src2);
1147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmadd213sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0xa9, dst, src1, src2);
1150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmadd231sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0xb9, dst, src1, src2);
1153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmadd132sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0x99, dst, src1, src2);
1156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmadd213sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0xa9, dst, src1, src2);
1159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmadd231sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0xb9, dst, src1, src2);
1162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmsub132sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0x9b, dst, src1, src2);
1165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmsub213sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0xab, dst, src1, src2);
1168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmsub231sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0xbb, dst, src1, src2);
1171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmsub132sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0x9b, dst, src1, src2);
1174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmsub213sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0xab, dst, src1, src2);
1177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmsub231sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0xbb, dst, src1, src2);
1180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmadd132sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0x9d, dst, src1, src2);
1183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmadd213sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0xad, dst, src1, src2);
1186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmadd231sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0xbd, dst, src1, src2);
1189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1190958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmadd132sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0x9d, dst, src1, src2);
1192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmadd213sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0xad, dst, src1, src2);
1195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmadd231sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0xbd, dst, src1, src2);
1198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmsub132sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0x9f, dst, src1, src2);
1201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmsub213sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0xaf, dst, src1, src2);
1204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmsub231sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0xbf, dst, src1, src2);
1207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmsub132sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0x9f, dst, src1, src2);
1210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmsub213sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0xaf, dst, src1, src2);
1213958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmsub231sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmasd(0xbf, dst, src1, src2);
1216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1217958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmasd(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2);
1218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmasd(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2);
1219958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmadd132ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0x99, dst, src1, src2);
1222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmadd213ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0xa9, dst, src1, src2);
1225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmadd231ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0xb9, dst, src1, src2);
1228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmadd132ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0x99, dst, src1, src2);
1231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmadd213ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0xa9, dst, src1, src2);
1234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmadd231ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0xb9, dst, src1, src2);
1237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmsub132ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0x9b, dst, src1, src2);
1240958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmsub213ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0xab, dst, src1, src2);
1243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmsub231ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0xbb, dst, src1, src2);
1246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmsub132ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0x9b, dst, src1, src2);
1249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmsub213ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0xab, dst, src1, src2);
1252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmsub231ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0xbb, dst, src1, src2);
1255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmadd132ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0x9d, dst, src1, src2);
1258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmadd213ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0xad, dst, src1, src2);
1261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmadd231ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0xbd, dst, src1, src2);
1264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmadd132ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0x9d, dst, src1, src2);
1267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmadd213ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0xad, dst, src1, src2);
1270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmadd231ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0xbd, dst, src1, src2);
1273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmsub132ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0x9f, dst, src1, src2);
1276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmsub213ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0xaf, dst, src1, src2);
1279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmsub231ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0xbf, dst, src1, src2);
1282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmsub132ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0x9f, dst, src1, src2);
1285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmsub213ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0xaf, dst, src1, src2);
1288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfnmsub231ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vfmass(0xbf, dst, src1, src2);
1291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmass(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2);
1293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void vfmass(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2);
1294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vmovd(XMMRegister dst, Register src);
1296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vmovd(XMMRegister dst, const Operand& src);
1297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vmovd(Register dst, XMMRegister src);
1298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vmovq(XMMRegister dst, Register src);
1299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vmovq(XMMRegister dst, const Operand& src);
1300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vmovq(Register dst, XMMRegister src);
1301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vmovsd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x10, dst, src1, src2);
1304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vmovsd(XMMRegister dst, const Operand& src) {
1306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x10, dst, xmm0, src);
1307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vmovsd(const Operand& dst, XMMRegister src) {
1309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x11, src, xmm0, dst);
1310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define AVX_SP_3(instr, opcode) \
1313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AVX_S_3(instr, opcode)        \
1314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AVX_P_3(instr, opcode)
1315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define AVX_S_3(instr, opcode)  \
1317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AVX_3(instr##ss, opcode, vss) \
1318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AVX_3(instr##sd, opcode, vsd)
1319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define AVX_P_3(instr, opcode)  \
1321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AVX_3(instr##ps, opcode, vps) \
1322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AVX_3(instr##pd, opcode, vpd)
1323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define AVX_3(instr, opcode, impl)                                     \
1325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void instr(XMMRegister dst, XMMRegister src1, XMMRegister src2) {    \
1326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    impl(opcode, dst, src1, src2);                                     \
1327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }                                                                    \
1328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void instr(XMMRegister dst, XMMRegister src1, const Operand& src2) { \
1329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    impl(opcode, dst, src1, src2);                                     \
1330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AVX_SP_3(vsqrt, 0x51);
1333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AVX_SP_3(vadd, 0x58);
1334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AVX_SP_3(vsub, 0x5c);
1335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AVX_SP_3(vmul, 0x59);
1336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AVX_SP_3(vdiv, 0x5e);
1337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AVX_SP_3(vmin, 0x5d);
1338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AVX_SP_3(vmax, 0x5f);
1339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AVX_P_3(vand, 0x54);
1340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AVX_P_3(vor, 0x56);
1341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AVX_P_3(vxor, 0x57);
1342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AVX_3(vpcmpeqd, 0x76, vpd);
1343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AVX_3(vcvtsd2ss, 0x5a, vsd);
1344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef AVX_3
1346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef AVX_S_3
1347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef AVX_P_3
1348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef AVX_SP_3
1349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vpsrlq(XMMRegister dst, XMMRegister src, byte imm8) {
1351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    XMMRegister iop = {2};
1352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vpd(0x73, iop, dst, src);
1353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    emit(imm8);
1354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1355014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vpsllq(XMMRegister dst, XMMRegister src, byte imm8) {
1356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    XMMRegister iop = {6};
1357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vpd(0x73, iop, dst, src);
1358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    emit(imm8);
1359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vcvtss2sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x5a, dst, src1, src2, kF3, k0F, kWIG);
1362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vcvtss2sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x5a, dst, src1, src2, kF3, k0F, kWIG);
1365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vcvtlsi2sd(XMMRegister dst, XMMRegister src1, Register src2) {
1367014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    XMMRegister isrc2 = {src2.code()};
1368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x2a, dst, src1, isrc2, kF2, k0F, kW0);
1369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vcvtlsi2sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x2a, dst, src1, src2, kF2, k0F, kW0);
1372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vcvtqsi2ss(XMMRegister dst, XMMRegister src1, Register src2) {
1374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    XMMRegister isrc2 = {src2.code()};
1375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x2a, dst, src1, isrc2, kF3, k0F, kW1);
1376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vcvtqsi2ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x2a, dst, src1, src2, kF3, k0F, kW1);
1379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vcvtqsi2sd(XMMRegister dst, XMMRegister src1, Register src2) {
1381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    XMMRegister isrc2 = {src2.code()};
1382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x2a, dst, src1, isrc2, kF2, k0F, kW1);
1383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vcvtqsi2sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x2a, dst, src1, src2, kF2, k0F, kW1);
1386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vcvttsd2si(Register dst, XMMRegister src) {
1388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    XMMRegister idst = {dst.code()};
1389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x2c, idst, xmm0, src, kF2, k0F, kW0);
1390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vcvttsd2si(Register dst, const Operand& src) {
1392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    XMMRegister idst = {dst.code()};
1393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x2c, idst, xmm0, src, kF2, k0F, kW0);
1394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vcvttss2siq(Register dst, XMMRegister src) {
1396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    XMMRegister idst = {dst.code()};
1397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x2c, idst, xmm0, src, kF3, k0F, kW1);
1398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vcvttss2siq(Register dst, const Operand& src) {
1400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    XMMRegister idst = {dst.code()};
1401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x2c, idst, xmm0, src, kF3, k0F, kW1);
1402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vcvttsd2siq(Register dst, XMMRegister src) {
1404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    XMMRegister idst = {dst.code()};
1405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x2c, idst, xmm0, src, kF2, k0F, kW1);
1406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vcvttsd2siq(Register dst, const Operand& src) {
1408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    XMMRegister idst = {dst.code()};
1409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x2c, idst, xmm0, src, kF2, k0F, kW1);
1410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vcvtsd2si(Register dst, XMMRegister src) {
1412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    XMMRegister idst = {dst.code()};
1413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x2d, idst, xmm0, src, kF2, k0F, kW0);
1414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vucomisd(XMMRegister dst, XMMRegister src) {
1416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x2e, dst, xmm0, src, k66, k0F, kWIG);
1417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vucomisd(XMMRegister dst, const Operand& src) {
1419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x2e, dst, xmm0, src, k66, k0F, kWIG);
1420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vroundss(XMMRegister dst, XMMRegister src1, XMMRegister src2,
1422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                RoundingMode mode) {
1423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x0a, dst, src1, src2, k66, k0F3A, kWIG);
1424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    emit(static_cast<byte>(mode) | 0x8);  // Mask precision exception.
1425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vroundsd(XMMRegister dst, XMMRegister src1, XMMRegister src2,
1427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                RoundingMode mode) {
1428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(0x0b, dst, src1, src2, k66, k0F3A, kWIG);
1429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    emit(static_cast<byte>(mode) | 0x8);  // Mask precision exception.
1430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1432014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vsd(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(op, dst, src1, src2, kF2, k0F, kWIG);
1434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vsd(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2) {
1436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vsd(op, dst, src1, src2, kF2, k0F, kWIG);
1437014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vsd(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2,
1439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           SIMDPrefix pp, LeadingOpcode m, VexW w);
1440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vsd(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2,
1441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           SIMDPrefix pp, LeadingOpcode m, VexW w);
1442014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vmovss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vss(0x10, dst, src1, src2);
1445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vmovss(XMMRegister dst, const Operand& src) {
1447014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vss(0x10, dst, xmm0, src);
1448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vmovss(const Operand& dst, XMMRegister src) {
1450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vss(0x11, src, xmm0, dst);
1451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vucomiss(XMMRegister dst, XMMRegister src);
1453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vucomiss(XMMRegister dst, const Operand& src);
1454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vss(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2);
1455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vss(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2);
1456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vmovaps(XMMRegister dst, XMMRegister src) { vps(0x28, dst, xmm0, src); }
1458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vmovapd(XMMRegister dst, XMMRegister src) { vpd(0x28, dst, xmm0, src); }
1459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vmovmskpd(Register dst, XMMRegister src) {
1460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    XMMRegister idst = {dst.code()};
1461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    vpd(0x50, idst, xmm0, src);
1462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vps(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2);
1465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vps(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2);
1466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vpd(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2);
1467014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void vpd(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2);
1468014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // BMI instruction
1470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void andnq(Register dst, Register src1, Register src2) {
1471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi1q(0xf2, dst, src1, src2);
1472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void andnq(Register dst, Register src1, const Operand& src2) {
1474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi1q(0xf2, dst, src1, src2);
1475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void andnl(Register dst, Register src1, Register src2) {
1477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi1l(0xf2, dst, src1, src2);
1478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1479014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void andnl(Register dst, Register src1, const Operand& src2) {
1480014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi1l(0xf2, dst, src1, src2);
1481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bextrq(Register dst, Register src1, Register src2) {
1483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi1q(0xf7, dst, src2, src1);
1484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bextrq(Register dst, const Operand& src1, Register src2) {
1486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi1q(0xf7, dst, src2, src1);
1487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bextrl(Register dst, Register src1, Register src2) {
1489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi1l(0xf7, dst, src2, src1);
1490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bextrl(Register dst, const Operand& src1, Register src2) {
1492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi1l(0xf7, dst, src2, src1);
1493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void blsiq(Register dst, Register src) {
1495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register ireg = {3};
1496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi1q(0xf3, ireg, dst, src);
1497958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void blsiq(Register dst, const Operand& src) {
1499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register ireg = {3};
1500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi1q(0xf3, ireg, dst, src);
1501958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void blsil(Register dst, Register src) {
1503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register ireg = {3};
1504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi1l(0xf3, ireg, dst, src);
1505958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void blsil(Register dst, const Operand& src) {
1507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register ireg = {3};
1508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi1l(0xf3, ireg, dst, src);
1509958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void blsmskq(Register dst, Register src) {
1511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register ireg = {2};
1512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi1q(0xf3, ireg, dst, src);
1513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void blsmskq(Register dst, const Operand& src) {
1515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register ireg = {2};
1516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi1q(0xf3, ireg, dst, src);
1517958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void blsmskl(Register dst, Register src) {
1519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register ireg = {2};
1520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi1l(0xf3, ireg, dst, src);
1521958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void blsmskl(Register dst, const Operand& src) {
1523014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register ireg = {2};
1524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi1l(0xf3, ireg, dst, src);
1525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void blsrq(Register dst, Register src) {
1527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register ireg = {1};
1528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi1q(0xf3, ireg, dst, src);
1529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void blsrq(Register dst, const Operand& src) {
1531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register ireg = {1};
1532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi1q(0xf3, ireg, dst, src);
1533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1534014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void blsrl(Register dst, Register src) {
1535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register ireg = {1};
1536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi1l(0xf3, ireg, dst, src);
1537014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1538014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void blsrl(Register dst, const Operand& src) {
1539014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register ireg = {1};
1540014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi1l(0xf3, ireg, dst, src);
1541014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void tzcntq(Register dst, Register src);
1543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void tzcntq(Register dst, const Operand& src);
1544014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void tzcntl(Register dst, Register src);
1545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void tzcntl(Register dst, const Operand& src);
1546014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void lzcntq(Register dst, Register src);
1548014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void lzcntq(Register dst, const Operand& src);
1549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void lzcntl(Register dst, Register src);
1550014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void lzcntl(Register dst, const Operand& src);
1551958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void popcntq(Register dst, Register src);
1553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void popcntq(Register dst, const Operand& src);
1554014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void popcntl(Register dst, Register src);
1555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void popcntl(Register dst, const Operand& src);
1556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bzhiq(Register dst, Register src1, Register src2) {
1558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2q(kNone, 0xf5, dst, src2, src1);
1559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bzhiq(Register dst, const Operand& src1, Register src2) {
1561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2q(kNone, 0xf5, dst, src2, src1);
1562014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bzhil(Register dst, Register src1, Register src2) {
1564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2l(kNone, 0xf5, dst, src2, src1);
1565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bzhil(Register dst, const Operand& src1, Register src2) {
1567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2l(kNone, 0xf5, dst, src2, src1);
1568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void mulxq(Register dst1, Register dst2, Register src) {
1570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2q(kF2, 0xf6, dst1, dst2, src);
1571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void mulxq(Register dst1, Register dst2, const Operand& src) {
1573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2q(kF2, 0xf6, dst1, dst2, src);
1574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void mulxl(Register dst1, Register dst2, Register src) {
1576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2l(kF2, 0xf6, dst1, dst2, src);
1577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void mulxl(Register dst1, Register dst2, const Operand& src) {
1579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2l(kF2, 0xf6, dst1, dst2, src);
1580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void pdepq(Register dst, Register src1, Register src2) {
1582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2q(kF2, 0xf5, dst, src1, src2);
1583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void pdepq(Register dst, Register src1, const Operand& src2) {
1585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2q(kF2, 0xf5, dst, src1, src2);
1586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1587014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void pdepl(Register dst, Register src1, Register src2) {
1588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2l(kF2, 0xf5, dst, src1, src2);
1589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void pdepl(Register dst, Register src1, const Operand& src2) {
1591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2l(kF2, 0xf5, dst, src1, src2);
1592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void pextq(Register dst, Register src1, Register src2) {
1594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2q(kF3, 0xf5, dst, src1, src2);
1595014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void pextq(Register dst, Register src1, const Operand& src2) {
1597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2q(kF3, 0xf5, dst, src1, src2);
1598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void pextl(Register dst, Register src1, Register src2) {
1600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2l(kF3, 0xf5, dst, src1, src2);
1601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void pextl(Register dst, Register src1, const Operand& src2) {
1603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2l(kF3, 0xf5, dst, src1, src2);
1604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1605014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void sarxq(Register dst, Register src1, Register src2) {
1606014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2q(kF3, 0xf7, dst, src2, src1);
1607014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1608014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void sarxq(Register dst, const Operand& src1, Register src2) {
1609014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2q(kF3, 0xf7, dst, src2, src1);
1610014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1611014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void sarxl(Register dst, Register src1, Register src2) {
1612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2l(kF3, 0xf7, dst, src2, src1);
1613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1614014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void sarxl(Register dst, const Operand& src1, Register src2) {
1615014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2l(kF3, 0xf7, dst, src2, src1);
1616014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void shlxq(Register dst, Register src1, Register src2) {
1618014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2q(k66, 0xf7, dst, src2, src1);
1619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1620014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void shlxq(Register dst, const Operand& src1, Register src2) {
1621014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2q(k66, 0xf7, dst, src2, src1);
1622014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1623014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void shlxl(Register dst, Register src1, Register src2) {
1624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2l(k66, 0xf7, dst, src2, src1);
1625014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1626014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void shlxl(Register dst, const Operand& src1, Register src2) {
1627014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2l(k66, 0xf7, dst, src2, src1);
1628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void shrxq(Register dst, Register src1, Register src2) {
1630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2q(kF2, 0xf7, dst, src2, src1);
1631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void shrxq(Register dst, const Operand& src1, Register src2) {
1633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2q(kF2, 0xf7, dst, src2, src1);
1634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void shrxl(Register dst, Register src1, Register src2) {
1636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2l(kF2, 0xf7, dst, src2, src1);
1637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1638014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void shrxl(Register dst, const Operand& src1, Register src2) {
1639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bmi2l(kF2, 0xf7, dst, src2, src1);
1640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void rorxq(Register dst, Register src, byte imm8);
1642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void rorxq(Register dst, const Operand& src, byte imm8);
1643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void rorxl(Register dst, Register src, byte imm8);
1644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void rorxl(Register dst, const Operand& src, byte imm8);
1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the code size generated from label to here.
16473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int SizeOfCodeGeneratedSince(Label* label) {
16483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return pc_offset() - label->pos();
16493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1651014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Mark generator continuation.
1652014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void RecordGeneratorContinuation();
1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Mark address of a debug break slot.
1655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void RecordDebugBreakSlot(RelocInfo::Mode mode);
16567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Record a comment relocation entry that can be used by a disassembler.
1658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Use --code-comments to enable.
1659014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void RecordComment(const char* msg);
1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1661014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Record a deoptimization reason that can be used by a log or cpu profiler.
1662014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Use --trace-deopt to enable.
1663014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void RecordDeoptReason(const int reason, const SourcePosition position);
1664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void PatchConstantPoolAccessInstruction(int pc_offset, int offset,
1666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                          ConstantPoolEntry::Access access,
1667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                          ConstantPoolEntry::Type type) {
1668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // No embedded constant pool support.
1669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    UNREACHABLE();
1670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Writes a single word of data in the code stream.
1673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Used for inline tables, e.g., jump-tables.
1674b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void db(uint8_t data);
1675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void dd(uint32_t data);
1676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void dq(uint64_t data);
1677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void dp(uintptr_t data) { dq(data); }
1678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void dq(Label* label);
1679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
16803e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  PositionsRecorder* positions_recorder() { return &positions_recorder_; }
1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if there is less than kGap bytes available in the buffer.
1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If this is the case, we need to grow the buffer before emitting
1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // an instruction or relocation information.
1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline bool buffer_overflow() const {
1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return pc_ >= reloc_info_writer.pos() - kGap;
1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the number of bytes available in the buffer.
1690d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  inline int available_space() const {
1691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return static_cast<int>(reloc_info_writer.pos() - pc_);
1692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static bool IsNop(Address addr);
16957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Avoid overflows for displacements etc.
1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kMaximalBufferSize = 512*MB;
1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  byte byte_at(int pos)  { return buffer_[pos]; }
17003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
17013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
170244f0eee88ff00398ff7f715fab053374d808c90dSteve Block protected:
1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Call near indirect
1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void call(const Operand& operand);
1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
1707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* addr_at(int pos)  { return buffer_ + pos; }
1708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint32_t long_at(int pos)  {
1709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return *reinterpret_cast<uint32_t*>(addr_at(pos));
1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void long_at_put(int pos, uint32_t x)  {
1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // code emission
1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void GrowBuffer();
1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit(byte x) { *pc_++ = x; }
1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emitl(uint32_t x);
1720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void emitp(void* x, RelocInfo::Mode rmode);
1721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void emitq(uint64_t x);
1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emitw(uint16_t x);
1723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  inline void emit_code_target(Handle<Code> target,
1724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               RelocInfo::Mode rmode,
1725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               TypeFeedbackId ast_id = TypeFeedbackId::None());
1726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void emit_runtime_entry(Address entry, RelocInfo::Mode rmode);
1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit(Immediate x) { emitl(x.value_); }
1728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emits a REX prefix that encodes a 64-bit operand size and
1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the top bit of both register codes.
1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W is set.
1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_64(XMMRegister reg, Register rm_reg);
17346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  inline void emit_rex_64(Register reg, XMMRegister rm_reg);
17356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  inline void emit_rex_64(Register reg, Register rm_reg);
1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emits a REX prefix that encodes a 64-bit operand size and
1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the top bit of the destination, index, and base register codes.
1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The high bit of reg is used for REX.R, the high bit of op's base
1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // register is used for REX.B, and the high bit of op's index register
1741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is used for REX.X.  REX.W is set.
1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_64(Register reg, const Operand& op);
1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_64(XMMRegister reg, const Operand& op);
1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emits a REX prefix that encodes a 64-bit operand size and
1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the top bit of the register code.
1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The high bit of register is used for REX.B.
1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W is set and REX.R and REX.X are clear.
1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_64(Register rm_reg);
1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emits a REX prefix that encodes a 64-bit operand size and
1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the top bit of the index and base register codes.
1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The high bit of op's base register is used for REX.B, and the high
1754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bit of op's index register is used for REX.X.
1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W is set and REX.R clear.
1756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_64(const Operand& op);
1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit a REX prefix that only sets REX.W to choose a 64-bit operand size.
1759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_rex_64() { emit(0x48); }
1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W is clear.
1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_32(Register reg, Register rm_reg);
1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The high bit of reg is used for REX.R, the high bit of op's base
1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // register is used for REX.B, and the high bit of op's index register
1767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is used for REX.X.  REX.W is cleared.
1768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_32(Register reg, const Operand& op);
1769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // High bit of rm_reg goes to REX.B.
1771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W, REX.R and REX.X are clear.
1772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_32(Register rm_reg);
1773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // High bit of base goes to REX.B and high bit of index to REX.X.
1775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W and REX.R are clear.
1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_32(const Operand& op);
1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W is cleared.  If no REX bits are set, no byte is emitted.
1780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(Register reg, Register rm_reg);
1781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The high bit of reg is used for REX.R, the high bit of op's base
1783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // register is used for REX.B, and the high bit of op's index register
1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is used for REX.X.  REX.W is cleared.  If no REX bits are set, nothing
1785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is emitted.
1786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(Register reg, const Operand& op);
1787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // As for emit_optional_rex_32(Register, Register), except that
1789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the registers are XMM registers.
1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(XMMRegister reg, XMMRegister base);
1791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // As for emit_optional_rex_32(Register, Register), except that
17936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // one of the registers is an XMM registers.
1794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(XMMRegister reg, Register base);
1795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // As for emit_optional_rex_32(Register, Register), except that
17976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // one of the registers is an XMM registers.
17986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  inline void emit_optional_rex_32(Register reg, XMMRegister base);
17996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // As for emit_optional_rex_32(Register, const Operand&), except that
1801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the register is an XMM register.
1802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(XMMRegister reg, const Operand& op);
1803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Optionally do as emit_rex_32(Register) if the register number has
1805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the high bit set.
1806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(Register rm_reg);
1807958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  inline void emit_optional_rex_32(XMMRegister rm_reg);
1808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Optionally do as emit_rex_32(const Operand&) if the operand register
1810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // numbers have a high bit set.
1811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(const Operand& op);
1812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_rex(int size) {
1814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (size == kInt64Size) {
1815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      emit_rex_64();
1816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(size == kInt32Size);
1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<class P1>
1822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_rex(P1 p1, int size) {
1823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (size == kInt64Size) {
1824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      emit_rex_64(p1);
1825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(size == kInt32Size);
1827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      emit_optional_rex_32(p1);
1828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<class P1, class P2>
1832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_rex(P1 p1, P2 p2, int size) {
1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (size == kInt64Size) {
1834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      emit_rex_64(p1, p2);
1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(size == kInt32Size);
1837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      emit_optional_rex_32(p1, p2);
1838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1841958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Emit vex prefix
1842958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void emit_vex2_byte0() { emit(0xc5); }
1843958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  inline void emit_vex2_byte1(XMMRegister reg, XMMRegister v, VectorLength l,
1844958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                              SIMDPrefix pp);
1845958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void emit_vex3_byte0() { emit(0xc4); }
1846958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  inline void emit_vex3_byte1(XMMRegister reg, XMMRegister rm, LeadingOpcode m);
1847958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  inline void emit_vex3_byte1(XMMRegister reg, const Operand& rm,
1848958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                              LeadingOpcode m);
1849958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  inline void emit_vex3_byte2(VexW w, XMMRegister v, VectorLength l,
1850958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                              SIMDPrefix pp);
1851958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  inline void emit_vex_prefix(XMMRegister reg, XMMRegister v, XMMRegister rm,
1852958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                              VectorLength l, SIMDPrefix pp, LeadingOpcode m,
1853958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                              VexW w);
1854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void emit_vex_prefix(Register reg, Register v, Register rm,
1855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              VectorLength l, SIMDPrefix pp, LeadingOpcode m,
1856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              VexW w);
1857958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  inline void emit_vex_prefix(XMMRegister reg, XMMRegister v, const Operand& rm,
1858958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                              VectorLength l, SIMDPrefix pp, LeadingOpcode m,
1859958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                              VexW w);
1860014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void emit_vex_prefix(Register reg, Register v, const Operand& rm,
1861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              VectorLength l, SIMDPrefix pp, LeadingOpcode m,
1862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              VexW w);
1863958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit the ModR/M byte, and optionally the SIB byte and
1865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 1- or 4-byte offset for a memory operand.  Also encodes
1866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the second operand of the operation, a register or operation
1867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // subcode, into the reg field of the ModR/M byte.
1868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_operand(Register reg, const Operand& adr) {
1869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    emit_operand(reg.low_bits(), adr);
1870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit the ModR/M byte, and optionally the SIB byte and
1873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 1- or 4-byte offset for a memory operand.  Also used to encode
1874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // a three-bit opcode extension into the ModR/M byte.
1875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_operand(int rm, const Operand& adr);
1876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit a ModR/M byte with registers coded in the reg and rm_reg fields.
1878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_modrm(Register reg, Register rm_reg) {
1879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    emit(0xC0 | reg.low_bits() << 3 | rm_reg.low_bits());
1880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit a ModR/M byte with an operation subcode in the reg field and
1883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // a register in the rm_reg field.
1884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_modrm(int code, Register rm_reg) {
1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(is_uint3(code));
1886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    emit(0xC0 | code << 3 | rm_reg.low_bits());
1887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit the code-object-relative offset of the label's position
1890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_code_relative_offset(Label* label);
1891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The first argument is the reg field, the second argument is the r/m field.
1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_sse_operand(XMMRegister dst, XMMRegister src);
1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_sse_operand(XMMRegister reg, const Operand& adr);
1895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_sse_operand(Register reg, const Operand& adr);
1896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_sse_operand(XMMRegister dst, Register src);
1897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_sse_operand(Register dst, XMMRegister src);
1898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit machine code for one of the operations ADD, ADC, SUB, SBC,
1900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // AND, OR, XOR, or CMP.  The encodings of these operations are all
1901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // similar, differing just in the opcode or in the reg field of the
1902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ModR/M byte.
1903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void arithmetic_op_8(byte opcode, Register reg, Register rm_reg);
1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void arithmetic_op_8(byte opcode, Register reg, const Operand& rm_reg);
1905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void arithmetic_op_16(byte opcode, Register reg, Register rm_reg);
1906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg);
1907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Operate on operands/registers with pointer size, 32-bit or 64-bit size.
1908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void arithmetic_op(byte opcode, Register reg, Register rm_reg, int size);
1909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void arithmetic_op(byte opcode,
1910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     Register reg,
1911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const Operand& rm_reg,
1912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     int size);
1913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Operate on a byte in memory or register.
1914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void immediate_arithmetic_op_8(byte subcode,
1915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register dst,
1916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Immediate src);
1917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void immediate_arithmetic_op_8(byte subcode,
1918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 const Operand& dst,
1919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Immediate src);
1920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Operate on a word in memory or register.
1921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void immediate_arithmetic_op_16(byte subcode,
1922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Register dst,
1923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Immediate src);
1924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void immediate_arithmetic_op_16(byte subcode,
1925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  const Operand& dst,
1926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Immediate src);
1927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Operate on operands/registers with pointer size, 32-bit or 64-bit size.
1928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void immediate_arithmetic_op(byte subcode,
1929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register dst,
1930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Immediate src,
1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               int size);
1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void immediate_arithmetic_op(byte subcode,
1933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               const Operand& dst,
1934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Immediate src,
1935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               int size);
1936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit machine code for a shift operation.
1938958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void shift(Operand dst, Immediate shift_amount, int subcode, int size);
1939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void shift(Register dst, Immediate shift_amount, int subcode, int size);
1940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shift dst by cl % 64 bits.
1941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void shift(Register dst, int subcode, int size);
1942958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void shift(Operand dst, int subcode, int size);
1943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_farith(int b1, int b2, int i);
1945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // labels
1947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // void print(Label* L);
1948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void bind_to(Label* L, int pos);
1949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // record reloc info for current pc_
1951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Arithmetics
1954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_add(Register dst, Register src, int size) {
1955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op(0x03, dst, src, size);
1956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_add(Register dst, Immediate src, int size) {
1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    immediate_arithmetic_op(0x0, dst, src, size);
1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_add(Register dst, const Operand& src, int size) {
1963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op(0x03, dst, src, size);
1964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_add(const Operand& dst, Register src, int size) {
1967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op(0x1, src, dst, size);
1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_add(const Operand& dst, Immediate src, int size) {
1971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    immediate_arithmetic_op(0x0, dst, src, size);
1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_and(Register dst, Register src, int size) {
1975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op(0x23, dst, src, size);
1976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_and(Register dst, const Operand& src, int size) {
1979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op(0x23, dst, src, size);
1980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_and(const Operand& dst, Register src, int size) {
1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op(0x21, src, dst, size);
1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_and(Register dst, Immediate src, int size) {
1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    immediate_arithmetic_op(0x4, dst, src, size);
1988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_and(const Operand& dst, Immediate src, int size) {
1991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    immediate_arithmetic_op(0x4, dst, src, size);
1992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_cmp(Register dst, Register src, int size) {
1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op(0x3B, dst, src, size);
1996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_cmp(Register dst, const Operand& src, int size) {
1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op(0x3B, dst, src, size);
2000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_cmp(const Operand& dst, Register src, int size) {
2003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op(0x39, src, dst, size);
2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_cmp(Register dst, Immediate src, int size) {
2007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    immediate_arithmetic_op(0x7, dst, src, size);
2008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_cmp(const Operand& dst, Immediate src, int size) {
2011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    immediate_arithmetic_op(0x7, dst, src, size);
2012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_dec(Register dst, int size);
2015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_dec(const Operand& dst, int size);
2016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Divide rdx:rax by src.  Quotient in rax, remainder in rdx when size is 64.
2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Divide edx:eax by lower 32 bits of src.  Quotient in eax, remainder in edx
2019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // when size is 32.
2020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_idiv(Register src, int size);
2021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_div(Register src, int size);
2022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Signed multiply instructions.
2024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rdx:rax = rax * src when size is 64 or edx:eax = eax * src when size is 32.
2025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_imul(Register src, int size);
2026958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void emit_imul(const Operand& src, int size);
2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_imul(Register dst, Register src, int size);
2028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_imul(Register dst, const Operand& src, int size);
2029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_imul(Register dst, Register src, Immediate imm, int size);
2030958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void emit_imul(Register dst, const Operand& src, Immediate imm, int size);
2031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_inc(Register dst, int size);
2033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_inc(const Operand& dst, int size);
2034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_lea(Register dst, const Operand& src, int size);
2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_mov(Register dst, const Operand& src, int size);
2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_mov(Register dst, Register src, int size);
2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_mov(const Operand& dst, Register src, int size);
2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_mov(Register dst, Immediate value, int size);
2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_mov(const Operand& dst, Immediate value, int size);
2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_movzxb(Register dst, const Operand& src, int size);
2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_movzxb(Register dst, Register src, int size);
2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_movzxw(Register dst, const Operand& src, int size);
2046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_movzxw(Register dst, Register src, int size);
2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_neg(Register dst, int size);
2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_neg(const Operand& dst, int size);
2050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_not(Register dst, int size);
2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_not(const Operand& dst, int size);
2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_or(Register dst, Register src, int size) {
2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op(0x0B, dst, src, size);
2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_or(Register dst, const Operand& src, int size) {
2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op(0x0B, dst, src, size);
2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_or(const Operand& dst, Register src, int size) {
2063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op(0x9, src, dst, size);
2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_or(Register dst, Immediate src, int size) {
2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    immediate_arithmetic_op(0x1, dst, src, size);
2068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_or(const Operand& dst, Immediate src, int size) {
2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    immediate_arithmetic_op(0x1, dst, src, size);
2072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_repmovs(int size);
2075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_sbb(Register dst, Register src, int size) {
2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op(0x1b, dst, src, size);
2078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_sub(Register dst, Register src, int size) {
2081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op(0x2B, dst, src, size);
2082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_sub(Register dst, Immediate src, int size) {
2085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    immediate_arithmetic_op(0x5, dst, src, size);
2086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_sub(Register dst, const Operand& src, int size) {
2089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op(0x2B, dst, src, size);
2090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_sub(const Operand& dst, Register src, int size) {
2093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op(0x29, src, dst, size);
2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_sub(const Operand& dst, Immediate src, int size) {
2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    immediate_arithmetic_op(0x5, dst, src, size);
2098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_test(Register dst, Register src, int size);
2101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_test(Register reg, Immediate mask, int size);
2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_test(const Operand& op, Register reg, int size);
2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_test(const Operand& op, Immediate mask, int size);
2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_test(Register reg, const Operand& op, int size) {
2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return emit_test(op, reg, size);
2106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_xchg(Register dst, Register src, int size);
2109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_xchg(Register dst, const Operand& src, int size);
2110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_xor(Register dst, Register src, int size) {
2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (size == kInt64Size && dst.code() == src.code()) {
2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
2114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // there is no need to make this a 64 bit operation.
2115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      arithmetic_op(0x33, dst, src, kInt32Size);
2116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      arithmetic_op(0x33, dst, src, size);
2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_xor(Register dst, const Operand& src, int size) {
2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op(0x33, dst, src, size);
2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_xor(Register dst, Immediate src, int size) {
2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    immediate_arithmetic_op(0x6, dst, src, size);
2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_xor(const Operand& dst, Immediate src, int size) {
2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    immediate_arithmetic_op(0x6, dst, src, size);
2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void emit_xor(const Operand& dst, Register src, int size) {
2134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    arithmetic_op(0x31, src, dst, size);
2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Most BMI instructions are similiar.
2138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bmi1q(byte op, Register reg, Register vreg, Register rm);
2139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bmi1q(byte op, Register reg, Register vreg, const Operand& rm);
2140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bmi1l(byte op, Register reg, Register vreg, Register rm);
2141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bmi1l(byte op, Register reg, Register vreg, const Operand& rm);
2142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bmi2q(SIMDPrefix pp, byte op, Register reg, Register vreg, Register rm);
2143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bmi2q(SIMDPrefix pp, byte op, Register reg, Register vreg,
2144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             const Operand& rm);
2145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bmi2l(SIMDPrefix pp, byte op, Register reg, Register vreg, Register rm);
2146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bmi2l(SIMDPrefix pp, byte op, Register reg, Register vreg,
2147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             const Operand& rm);
2148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class CodePatcher;
2150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class EnsureSpace;
2151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class RegExpMacroAssemblerX64;
2152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // code generation
2154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RelocInfoWriter reloc_info_writer;
2155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Internal reference positions, required for (potential) patching in
2157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // GrowBuffer(); contains only those internal references whose labels
2158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // are already bound.
2159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  std::deque<int> internal_reference_positions_;
2160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
21613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  List< Handle<Code> > code_targets_;
2162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21633e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  PositionsRecorder positions_recorder_;
21643e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  friend class PositionsRecorder;
2165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
2166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper class that ensures that there is enough space for generating
2169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// instructions and relocation information.  The constructor makes
2170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// sure that there is enough space and (in debug mode) the destructor
2171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// checks that we did not generate too much.
2172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass EnsureSpace BASE_EMBEDDED {
2173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
2174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
2175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (assembler_->buffer_overflow()) assembler_->GrowBuffer();
2176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    space_before_ = assembler_->available_space();
2178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ~EnsureSpace() {
2183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int bytes_generated = space_before_ - assembler_->available_space();
2184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(bytes_generated < assembler_->kGap);
2185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
2189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Assembler* assembler_;
2190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int space_before_;
2192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
2194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
2196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
2197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_X64_ASSEMBLER_X64_H_
2199