assembler-x64.h revision b0fe1620dcb4135ac3ab2d66ff93072373911299
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.
33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Copyright 2010 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
40d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "serialize.h"
41d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Utility functions
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test whether a 64-bit value is in a specific range.
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline bool is_uint32(int64_t x) {
498defd9ff6930b4e24729971a61cf7469daf119beSteve Block  static const uint64_t kMaxUInt32 = V8_UINT64_C(0xffffffff);
508defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return static_cast<uint64_t>(x) <= kMaxUInt32;
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline bool is_int32(int64_t x) {
548defd9ff6930b4e24729971a61cf7469daf119beSteve Block  static const int64_t kMinInt32 = -V8_INT64_C(0x80000000);
558defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return is_uint32(x - kMinInt32);
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline bool uint_is_int32(uint64_t x) {
598defd9ff6930b4e24729971a61cf7469daf119beSteve Block  static const uint64_t kMaxInt32 = V8_UINT64_C(0x7fffffff);
608defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return x <= kMaxInt32;
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline bool is_uint32(uint64_t x) {
648defd9ff6930b4e24729971a61cf7469daf119beSteve Block  static const uint64_t kMaxUInt32 = V8_UINT64_C(0xffffffff);
658defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return x <= kMaxUInt32;
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CPU Registers.
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 1) We would prefer to use an enum, but enum values are assignment-
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// compatible with int, which has caused code-generation bugs.
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 2) We would prefer to use a class instead of a struct but we don't like
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the register initialization to depend on the particular initialization
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// order (which appears to be different on OS X, Linux, and Windows for the
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// installed versions of C++ we tried). Using a struct permits C-style
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "initialization". Also, the Register objects cannot be const as this
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// forces initialization stubs in MSVC, making us dependent on initialization
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// order.
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 3) By not using an enum, we are possibly preventing the compiler from
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// doing certain constant folds, which may significantly reduce the
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// code generated for some assembly instructions (because they boil down
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to a few constants). If this is a problem, we could change the code
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// such that we use an enum in optimized mode, and the struct in debug
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// mode. This way we get the compile-time error checking in debug mode
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and best performance in optimized code.
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct Register {
91b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The non-allocatable registers are:
92b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  rsp - stack pointer
93b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  rbp - frame pointer
94b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  rsi - context register
95b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  r10 - fixed scratch register
96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  r13 - root register
97b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  r15 - smi constant register
98b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const int kNumRegisters = 16;
99b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const int kNumAllocatableRegisters = 10;
100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const char* AllocationIndexToString(int index) {
102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    const char* const names[] = {
104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "rax",
105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "rcx",
106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "rdx",
107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "rbx",
108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "rdi",
109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "r8",
110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "r9",
111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "r11",
112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "r12",
113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "r14"
114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    };
115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return names[index];
116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static Register toRegister(int code) {
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Register r = { code };
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return r;
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
1230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  bool is(Register reg) const { return code_ == reg.code_; }
1240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int code() const {
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(is_valid());
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return code_;
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int bit() const {
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 1 << code_;
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the high bit of the register code as a 0 or 1.  Used often
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // when constructing the REX prefix byte.
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int high_bit() const {
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return code_ >> 3;
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the 3 low bits of the register code.  Used when encoding registers
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in modR/M, SIB, and opcode bytes.
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int low_bits() const {
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return code_ & 0x7;
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Unfortunately we can't make this private in a struct when initializing
1443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // by assignment.
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int code_;
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
148402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register rax = { 0 };
149402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register rcx = { 1 };
150402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register rdx = { 2 };
151402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register rbx = { 3 };
152402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register rsp = { 4 };
153402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register rbp = { 5 };
154402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register rsi = { 6 };
155402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register rdi = { 7 };
156402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register r8 = { 8 };
157402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register r9 = { 9 };
158402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register r10 = { 10 };
159402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register r11 = { 11 };
160402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register r12 = { 12 };
161402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register r13 = { 13 };
162402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register r14 = { 14 };
163402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register r15 = { 15 };
164402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register no_reg = { -1 };
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct XMMRegister {
168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const int kNumRegisters = 16;
169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const int kNumAllocatableRegisters = 15;
170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static int ToAllocationIndex(XMMRegister reg) {
172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(reg.code() != 0);
173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return reg.code() - 1;
174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const char* AllocationIndexToString(int index) {
177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    const char* const names[] = {
179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm1",
180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm2",
181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm3",
182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm4",
183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm5",
184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm6",
185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm7",
186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm8",
187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm9",
188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm10",
189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm11",
190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm12",
191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm13",
192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm14",
193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm15"
194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    };
195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return names[index];
196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
1990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int code() const {
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(is_valid());
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return code_;
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the high bit of the register code as a 0 or 1.  Used often
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // when constructing the REX prefix byte.
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int high_bit() const {
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return code_ >> 3;
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the 3 low bits of the register code.  Used when encoding registers
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in modR/M, SIB, and opcode bytes.
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int low_bits() const {
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return code_ & 0x7;
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int code_;
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
218402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm0 = { 0 };
219402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm1 = { 1 };
220402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm2 = { 2 };
221402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm3 = { 3 };
222402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm4 = { 4 };
223402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm5 = { 5 };
224402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm6 = { 6 };
225402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm7 = { 7 };
226402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm8 = { 8 };
227402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm9 = { 9 };
228402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm10 = { 10 };
229402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm11 = { 11 };
230402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm12 = { 12 };
231402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm13 = { 13 };
232402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm14 = { 14 };
233402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm15 = { 15 };
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochtypedef XMMRegister DoubleRegister;
237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum Condition {
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // any value < 0 is considered no_condition
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  no_condition  = -1,
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  overflow      =  0,
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  no_overflow   =  1,
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  below         =  2,
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  above_equal   =  3,
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  equal         =  4,
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  not_equal     =  5,
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  below_equal   =  6,
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  above         =  7,
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  negative      =  8,
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  positive      =  9,
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  parity_even   = 10,
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  parity_odd    = 11,
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  less          = 12,
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  greater_equal = 13,
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  less_equal    = 14,
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  greater       = 15,
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Fake conditions that are handled by the
2613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // opcodes using them.
2623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  always        = 16,
2633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  never         = 17,
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // aliases
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  carry         = below,
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  not_carry     = above_equal,
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  zero          = equal,
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  not_zero      = not_equal,
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  sign          = negative,
2703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  not_sign      = positive,
2713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  last_condition = greater
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns the equivalent of !cc.
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Negation of the default no_condition (-1) results in a non-default
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// no_condition value (-2). As long as tests for no_condition check
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// for condition < 0, this will work as expected.
2799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monseninline Condition NegateCondition(Condition cc) {
2809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  return static_cast<Condition>(cc ^ 1);
2819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
2829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Corresponds to transposing the operands of a comparison.
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline Condition ReverseCondition(Condition cc) {
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (cc) {
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case below:
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return above;
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case above:
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return below;
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case above_equal:
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return below_equal;
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case below_equal:
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return above_equal;
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case less:
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return greater;
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case greater:
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return less;
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case greater_equal:
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return less_equal;
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case less_equal:
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return greater_equal;
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return cc;
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum Hint {
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  no_hint = 0,
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  not_taken = 0x2e,
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  taken = 0x3e
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The result of negating a hint is as if the corresponding condition
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// were negated by NegateCondition.  That is, no_hint is mapped to
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// itself and not_taken and taken are mapped to each other.
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline Hint NegateHint(Hint hint) {
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return (hint == no_hint)
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ? no_hint
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : ((hint == not_taken) ? taken : not_taken);
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Machine instruction Immediates
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Immediate BASE_EMBEDDED {
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit Immediate(int32_t value) : value_(value) {}
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int32_t value_;
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class Assembler;
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Machine instruction Operands
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum ScaleFactor {
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_1 = 0,
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_2 = 1,
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_4 = 2,
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_8 = 3,
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_int_size = times_4,
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_pointer_size = times_8
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Operand BASE_EMBEDDED {
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // [base + disp/r]
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Operand(Register base, int32_t disp);
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // [base + index*scale + disp/r]
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Operand(Register base,
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Register index,
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          ScaleFactor scale,
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int32_t disp);
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // [index*scale + disp/r]
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Operand(Register index,
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          ScaleFactor scale,
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int32_t disp);
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
368f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Offset from existing memory operand.
369f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Offset is added to existing displacement as 32-bit signed values and
370f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // this must not overflow.
371f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Operand(const Operand& base, int32_t offset);
372f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte rex_;
3757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  byte buf_[6];
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The number of bytes in buf_.
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unsigned int len_;
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the ModR/M byte without an encoded 'reg' register. The
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // register is encoded later as part of the emit_operand operation.
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // set_modrm can be called before or after set_sib and set_disp*.
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void set_modrm(int mod, Register rm);
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the SIB byte if one is needed. Sets the length to 2 rather than 1.
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void set_sib(ScaleFactor scale, Register index, Register base);
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adds operand displacement fields (offsets added to the memory address).
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Needs to be called after set_sib, not before it.
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void set_disp8(int disp);
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void set_disp32(int disp);
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class Assembler;
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CpuFeatures keeps track of which features are supported by the target CPU.
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Supported features must be enabled by a Scope before use.
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Example:
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   if (CpuFeatures::IsSupported(SSE3)) {
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     CpuFeatures::Scope fscope(SSE3);
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     // Generate SSE3 floating point code.
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   } else {
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     // Generate standard x87 or SSE2 floating point code.
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   }
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CpuFeatures : public AllStatic {
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Detect features of the target CPU. Set safe defaults if the serializer
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is enabled (snapshots must be portable).
409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static void Probe(bool portable);
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check whether a feature is supported by the target CPU.
411d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static bool IsSupported(CpuFeature f) {
4123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (f == SSE2 && !FLAG_enable_sse2) return false;
4133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (f == SSE3 && !FLAG_enable_sse3) return false;
4143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (f == CMOV && !FLAG_enable_cmov) return false;
4153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (f == RDTSC && !FLAG_enable_rdtsc) return false;
4163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (f == SAHF && !FLAG_enable_sahf) return false;
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return (supported_ & (V8_UINT64_C(1) << f)) != 0;
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check whether a feature is currently enabled.
420d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static bool IsEnabled(CpuFeature f) {
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return (enabled_ & (V8_UINT64_C(1) << f)) != 0;
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enable a specified feature within a scope.
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  class Scope BASE_EMBEDDED {
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block   public:
427d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    explicit Scope(CpuFeature f) {
428d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      uint64_t mask = (V8_UINT64_C(1) << f);
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(CpuFeatures::IsSupported(f));
430d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      ASSERT(!Serializer::enabled() || (found_by_runtime_probing_ & mask) == 0);
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      old_enabled_ = CpuFeatures::enabled_;
432d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      CpuFeatures::enabled_ |= mask;
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ~Scope() { CpuFeatures::enabled_ = old_enabled_; }
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block   private:
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint64_t old_enabled_;
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block   public:
439d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    explicit Scope(CpuFeature f) {}
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Safe defaults include SSE2 and CMOV for X64. It is always available, if
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // anyone checks, but they shouldn't need to check.
445d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static const uint64_t kDefaultCpuFeatures = (1 << SSE2 | 1 << CMOV);
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static uint64_t supported_;
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static uint64_t enabled_;
448d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static uint64_t found_by_runtime_probing_;
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Assembler : public Malloced {
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We check before assembling an instruction that there is sufficient
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // space to write an instruction and its relocation information.
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The relocation writer's position must be kGap bytes above the end of
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the generated instructions. This leaves enough space for the
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // longest possible x64 instruction, 15 bytes, and the longest possible
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // (There is a 15 byte limit on x64 instruction length that rules out some
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // otherwise valid instructions.)
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This allows for a single, fast space check per instruction.
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kGap = 32;
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create an assembler. Instructions and relocation information are emitted
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // into a buffer, with the instructions starting from the beginning and the
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // relocation information starting from the end of the buffer. See CodeDesc
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // for a detailed comment on the layout (globals.h).
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the provided buffer is NULL, the assembler allocates and grows its own
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // buffer, and buffer_size determines the initial buffer size. The buffer is
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // owned by the assembler and deallocated upon destruction of the assembler.
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the provided buffer is not NULL, the assembler uses the provided buffer
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // for code generation and assumes its size to be buffer_size. If the buffer
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is too small, a fatal error occurs. No deallocation of the buffer is done
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // upon destruction of the assembler.
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Assembler(void* buffer, int buffer_size);
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ~Assembler();
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // GetCode emits any pending (non-emitted) code and fills the descriptor
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // desc. GetCode() is idempotent; it returns the same result if no other
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Assembler functions are invoked in between GetCode() calls.
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void GetCode(CodeDesc* desc);
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Read/Modify the code target in the relative branch/call instruction at pc.
4883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // On the x64 architecture, we use relative jumps with a 32-bit displacement
4893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // to jump to other Code objects in the Code space in the heap.
4903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Jumps to C functions are done indirectly through a 64-bit register holding
4913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // the absolute address of the target.
4923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // These functions convert between absolute Addresses of Code objects and
4933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // the relative displacements stored in the code.
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static inline Address target_address_at(Address pc);
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static inline void set_target_address_at(Address pc, Address target);
496d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
497d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This sets the branch destination (which is in the instruction on x64).
498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This is for calls and branches within generated code.
499d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  inline static void set_target_at(Address instruction_payload,
500d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                   Address target) {
501d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    set_target_address_at(instruction_payload, target);
502d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
503d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This sets the branch destination (which is a load instruction on x64).
505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This is for calls and branches to runtime code.
506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  inline static void set_external_target_at(Address instruction_payload,
507d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                            Address target) {
508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    *reinterpret_cast<Address*>(instruction_payload) = target;
509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  inline Handle<Object> code_target_object_handle_at(Address pc);
512d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Number of bytes taken up by the branch target in the code.
513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static const int kCallTargetSize = 4;      // Use 32-bit displacement.
514d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static const int kExternalTargetSize = 8;  // Use 64-bit absolute.
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Distance between the address of the code target in the call instruction
5163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // and the return address pushed on the stack.
5173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  static const int kCallTargetAddressOffset = 4;  // Use 32-bit displacement.
5183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Distance between the start of the JS return sequence and where the
5193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // 32-bit displacement of a near call would be, relative to the pushed
5203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // return address.  TODO: Use return sequence length instead.
5213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
5223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  static const int kPatchReturnSequenceAddressOffset = 13 - 4;
5237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Distance between start of patched debug break slot and where the
5247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // 32-bit displacement of a near call would be, relative to the pushed
5257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // return address.  TODO: Use return sequence length instead.
5267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
5277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  static const int kPatchDebugBreakSlotAddressOffset = 13 - 4;
5283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // TODO(X64): Rename this, removing the "Real", after changing the above.
5293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  static const int kRealPatchReturnSequenceAddressOffset = 2;
530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // The x64 JS return sequence is padded with int3 to make it large
532d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // enough to hold a call instruction when the debugger patches it.
533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static const int kCallInstructionLength = 13;
534d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static const int kJSReturnSequenceLength = 13;
535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // The debug break slot must be able to contain a call instruction.
5377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  static const int kDebugBreakSlotLength = kCallInstructionLength;
5387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
5397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Code generation
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Function names correspond one-to-one to x64 instruction mnemonics.
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Unless specified otherwise, instructions operate on 64-bit operands.
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If we need versions of an assembly instruction that operate on different
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // width arguments, we add a single-letter suffix specifying the width.
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This is done for the following instructions: mov, cmp, inc, dec,
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // add, sub, and test.
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // There are no versions of these instructions without the suffix.
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'.
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // - Instructions on 16-bit (word) operands/registers have a trailing 'w'.
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // - Instructions on 32-bit (doubleword) operands/registers use 'l'.
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // - Instructions on 64-bit (quadword) operands/registers use 'q'.
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Some mnemonics, such as "and", are the same as C++ keywords.
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Naming conflicts with C++ keywords are resolved by adding a trailing '_'.
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Insert the smallest number of nop instructions
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // possible to align the pc offset to a multiple
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // of m. m must be a power of 2.
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Align(int m);
5639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Aligns code to something that's optimal for a jump target for the platform.
5649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  void CodeTargetAlign();
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stack
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void pushfq();
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void popfq();
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void push(Immediate value);
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void push(Register src);
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void push(const Operand& src);
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void pop(Register dst);
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void pop(const Operand& dst);
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void enter(Immediate size);
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void leave();
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Moves
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movb(Register dst, const Operand& src);
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movb(Register dst, Immediate imm);
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movb(const Operand& dst, Register src);
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Move the low 16 bits of a 64-bit register value to a 16-bit
5863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // memory location.
5873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void movw(const Operand& dst, Register src);
5883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movl(Register dst, Register src);
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movl(Register dst, const Operand& src);
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movl(const Operand& dst, Register src);
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movl(const Operand& dst, Immediate imm);
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load a 32-bit immediate value, zero-extended to 64 bits.
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movl(Register dst, Immediate imm32);
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move 64 bit register value to 64-bit memory location.
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movq(const Operand& dst, Register src);
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move 64 bit memory location to 64-bit register value.
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movq(Register dst, const Operand& src);
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movq(Register dst, Register src);
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Sign extends immediate 32-bit value to 64 bits.
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movq(Register dst, Immediate x);
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move the offset of the label location relative to the current
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // position (after the move) to the destination.
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movl(const Operand& dst, Label* src);
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move sign extended immediate to memory location.
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movq(const Operand& dst, Immediate value);
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // New x64 instructions to load a 64-bit immediate into a register.
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All 64-bit immediates must have a relocation mode.
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movq(Register dst, void* ptr, RelocInfo::Mode rmode);
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movq(Register dst, int64_t value, RelocInfo::Mode rmode);
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movq(Register dst, const char* s, RelocInfo::Mode rmode);
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Moves the address of the external reference into the register.
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movq(Register dst, ExternalReference ext);
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movq(Register dst, Handle<Object> handle, RelocInfo::Mode rmode);
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void movsxbq(Register dst, const Operand& src);
6193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void movsxwq(Register dst, const Operand& src);
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movsxlq(Register dst, Register src);
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movsxlq(Register dst, const Operand& src);
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movzxbq(Register dst, const Operand& src);
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movzxbl(Register dst, const Operand& src);
6243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void movzxwq(Register dst, const Operand& src);
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movzxwl(Register dst, const Operand& src);
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
627d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Repeated moves.
628d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
629d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void repmovsb();
630d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void repmovsw();
631d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void repmovsl();
632d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void repmovsq();
633d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // New x64 instruction to load from an immediate 64-bit pointer into RAX.
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void load_rax(void* ptr, RelocInfo::Mode rmode);
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void load_rax(ExternalReference ext);
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Conditional moves.
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmovq(Condition cc, Register dst, Register src);
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmovq(Condition cc, Register dst, const Operand& src);
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmovl(Condition cc, Register dst, Register src);
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmovl(Condition cc, Register dst, const Operand& src);
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Exchange two registers
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void xchg(Register dst, Register src);
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Arithmetics
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addl(Register dst, Register src) {
649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    arithmetic_op_32(0x03, dst, src);
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addl(Register dst, Immediate src) {
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_32(0x0, dst, src);
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addl(Register dst, const Operand& src) {
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_32(0x03, dst, src);
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addl(const Operand& dst, Immediate src) {
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_32(0x0, dst, src);
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addq(Register dst, Register src) {
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x03, dst, src);
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addq(Register dst, const Operand& src) {
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x03, dst, src);
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addq(const Operand& dst, Register src) {
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x01, src, dst);
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addq(Register dst, Immediate src) {
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x0, dst, src);
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addq(const Operand& dst, Immediate src) {
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x0, dst, src);
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
68425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  void sbbl(Register dst, Register src) {
685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    arithmetic_op_32(0x1b, dst, src);
68625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  }
68725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpb(Register dst, Immediate src) {
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_8(0x7, dst, src);
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpb_al(Immediate src);
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpb(Register dst, Register src) {
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x3A, dst, src);
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpb(Register dst, const Operand& src) {
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x3A, dst, src);
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpb(const Operand& dst, Register src) {
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x38, src, dst);
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpb(const Operand& dst, Immediate src) {
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_8(0x7, dst, src);
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpw(const Operand& dst, Immediate src) {
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_16(0x7, dst, src);
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpw(Register dst, Immediate src) {
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_16(0x7, dst, src);
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpw(Register dst, const Operand& src) {
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_16(0x3B, dst, src);
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpw(Register dst, Register src) {
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_16(0x3B, dst, src);
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpw(const Operand& dst, Register src) {
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_16(0x39, src, dst);
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpl(Register dst, Register src) {
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_32(0x3B, dst, src);
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpl(Register dst, const Operand& src) {
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_32(0x3B, dst, src);
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpl(const Operand& dst, Register src) {
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_32(0x39, src, dst);
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpl(Register dst, Immediate src) {
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_32(0x7, dst, src);
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpl(const Operand& dst, Immediate src) {
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_32(0x7, dst, src);
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpq(Register dst, Register src) {
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x3B, dst, src);
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpq(Register dst, const Operand& src) {
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x3B, dst, src);
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpq(const Operand& dst, Register src) {
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x39, src, dst);
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpq(Register dst, Immediate src) {
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x7, dst, src);
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpq(const Operand& dst, Immediate src) {
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x7, dst, src);
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void and_(Register dst, Register src) {
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x23, dst, src);
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void and_(Register dst, const Operand& src) {
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x23, dst, src);
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void and_(const Operand& dst, Register src) {
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x21, src, dst);
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void and_(Register dst, Immediate src) {
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x4, dst, src);
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void and_(const Operand& dst, Immediate src) {
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x4, dst, src);
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void andl(Register dst, Immediate src) {
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_32(0x4, dst, src);
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void andl(Register dst, Register src) {
7953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    arithmetic_op_32(0x23, dst, src);
7963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
7973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  void andb(Register dst, Immediate src) {
7994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    immediate_arithmetic_op_8(0x4, dst, src);
8004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
8013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void decq(Register dst);
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void decq(const Operand& dst);
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void decl(Register dst);
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void decl(const Operand& dst);
8063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void decb(Register dst);
8073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void decb(const Operand& dst);
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Sign-extends rax into rdx:rax.
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cqo();
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Sign-extends eax into edx:eax.
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cdq();
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Divide rdx:rax by src.  Quotient in rax, remainder in rdx.
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void idivq(Register src);
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Divide edx:eax by lower 32 bits of src.  Quotient in eax, rem. in edx.
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void idivl(Register src);
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Signed multiply instructions.
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void imul(Register src);                               // rdx:rax = rax * src.
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void imul(Register dst, Register src);                 // dst = dst * src.
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void imul(Register dst, const Operand& src);           // dst = dst * src.
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void imul(Register dst, Register src, Immediate imm);  // dst = src * imm.
8246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Signed 32-bit multiply instructions.
8256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void imull(Register dst, Register src);                 // dst = dst * src.
8266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void imull(Register dst, Register src, Immediate imm);  // dst = src * imm.
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void incq(Register dst);
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void incq(const Operand& dst);
8309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  void incl(Register dst);
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void incl(const Operand& dst);
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void lea(Register dst, const Operand& src);
8346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void leal(Register dst, const Operand& src);
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Multiply rax by src, put the result in rdx:rax.
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void mul(Register src);
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void neg(Register dst);
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void neg(const Operand& dst);
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void negl(Register dst);
842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void not_(Register dst);
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void not_(const Operand& dst);
8456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void notl(Register dst);
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void or_(Register dst, Register src) {
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x0B, dst, src);
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void orl(Register dst, Register src) {
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_32(0x0B, dst, src);
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void or_(Register dst, const Operand& src) {
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x0B, dst, src);
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void or_(const Operand& dst, Register src) {
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x09, src, dst);
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void or_(Register dst, Immediate src) {
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x1, dst, src);
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void orl(Register dst, Immediate src) {
8683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    immediate_arithmetic_op_32(0x1, dst, src);
8693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
8703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void or_(const Operand& dst, Immediate src) {
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x1, dst, src);
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void orl(const Operand& dst, Immediate src) {
8763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    immediate_arithmetic_op_32(0x1, dst, src);
8773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
8783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void rcl(Register dst, Immediate imm8) {
8813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shift(dst, imm8, 0x2);
8823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
8833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void rol(Register dst, Immediate imm8) {
8853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shift(dst, imm8, 0x0);
8863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
8873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void rcr(Register dst, Immediate imm8) {
8893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shift(dst, imm8, 0x3);
8903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
8913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void ror(Register dst, Immediate imm8) {
8933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shift(dst, imm8, 0x1);
8943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shifts dst:src left by cl bits, affecting only dst.
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shld(Register dst, Register src);
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shifts src:dst right by cl bits, affecting only dst.
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shrd(Register dst, Register src);
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shifts dst right, duplicating sign bit, by shift_amount bits.
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shifting by 1 is handled efficiently.
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void sar(Register dst, Immediate shift_amount) {
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift(dst, shift_amount, 0x7);
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shifts dst right, duplicating sign bit, by shift_amount bits.
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shifting by 1 is handled efficiently.
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void sarl(Register dst, Immediate shift_amount) {
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift_32(dst, shift_amount, 0x7);
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shifts dst right, duplicating sign bit, by cl % 64 bits.
915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void sar_cl(Register dst) {
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift(dst, 0x7);
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shifts dst right, duplicating sign bit, by cl % 64 bits.
920d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void sarl_cl(Register dst) {
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift_32(dst, 0x7);
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shl(Register dst, Immediate shift_amount) {
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift(dst, shift_amount, 0x4);
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void shl_cl(Register dst) {
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift(dst, 0x4);
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
932d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void shll_cl(Register dst) {
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift_32(dst, 0x4);
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shll(Register dst, Immediate shift_amount) {
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift_32(dst, shift_amount, 0x4);
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shr(Register dst, Immediate shift_amount) {
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift(dst, shift_amount, 0x5);
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
944d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void shr_cl(Register dst) {
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift(dst, 0x5);
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
948d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void shrl_cl(Register dst) {
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift_32(dst, 0x5);
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shrl(Register dst, Immediate shift_amount) {
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift_32(dst, shift_amount, 0x5);
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void store_rax(void* dst, RelocInfo::Mode mode);
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void store_rax(ExternalReference ref);
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subq(Register dst, Register src) {
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x2B, dst, src);
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subq(Register dst, const Operand& src) {
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x2B, dst, src);
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subq(const Operand& dst, Register src) {
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x29, src, dst);
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subq(Register dst, Immediate src) {
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x5, dst, src);
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subq(const Operand& dst, Immediate src) {
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x5, dst, src);
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subl(Register dst, Register src) {
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_32(0x2B, dst, src);
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
983e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void subl(Register dst, const Operand& src) {
984e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    arithmetic_op_32(0x2B, dst, src);
985e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
986e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subl(const Operand& dst, Immediate src) {
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_32(0x5, dst, src);
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subl(Register dst, Immediate src) {
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_32(0x5, dst, src);
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subb(Register dst, Immediate src) {
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_8(0x5, dst, src);
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void testb(Register dst, Register src);
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void testb(Register reg, Immediate mask);
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void testb(const Operand& op, Immediate mask);
1002e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void testb(const Operand& op, Register reg);
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void testl(Register dst, Register src);
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void testl(Register reg, Immediate mask);
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void testl(const Operand& op, Immediate mask);
1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void testq(const Operand& op, Register reg);
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void testq(Register dst, Register src);
1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void testq(Register dst, Immediate mask);
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void xor_(Register dst, Register src) {
1011d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (dst.code() == src.code()) {
1012d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      arithmetic_op_32(0x33, dst, src);
1013d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
1014d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      arithmetic_op(0x33, dst, src);
1015d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void xorl(Register dst, Register src) {
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_32(0x33, dst, src);
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void xor_(Register dst, const Operand& src) {
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x33, dst, src);
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void xor_(const Operand& dst, Register src) {
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x31, src, dst);
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void xor_(Register dst, Immediate src) {
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x6, dst, src);
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void xor_(const Operand& dst, Immediate src) {
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x6, dst, src);
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Bit operations.
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void bt(const Operand& dst, Register src);
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void bts(const Operand& dst, Register src);
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Miscellaneous
10433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void clc();
1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cpuid();
1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void hlt();
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void int3();
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void nop();
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void nop(int n);
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void rdtsc();
1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void ret(int imm16);
1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void setcc(Condition cc, Register reg);
1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Label operations & relative jumps (PPUM Appendix D)
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Takes a branch opcode (cc) and a label (L) and generates
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // either a backward branch or a forward branch and links it
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to the label fixup chain. Usage:
1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Label L;    // unbound label
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // j(cc, &L);  // forward branch to unbound label
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bind(&L);   // bind label to the current pc
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // j(cc, &L);  // backward branch to bound label
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bind(&L);   // illegal: a label may be bound only once
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Note: The same Label can be used for forward and backward branches
1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // but it may be bound only once.
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void bind(Label* L);  // binds an unbound label L to the current code position
10690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  void bind(NearLabel* L);
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calls
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call near relative 32-bit displacement, relative to next instruction.
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void call(Label* L);
10743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void call(Handle<Code> target, RelocInfo::Mode rmode);
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call near absolute indirect, address in register
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void call(Register adr);
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call near indirect
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void call(const Operand& operand);
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jumps
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump short or near relative.
10843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Use a 32-bit signed displacement.
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void jmp(Label* L);  // unconditional jump to L
10863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void jmp(Handle<Code> target, RelocInfo::Mode rmode);
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump near absolute indirect (r64)
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void jmp(Register adr);
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump near absolute indirect (m64)
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void jmp(const Operand& src);
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Short jump
10950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  void jmp(NearLabel* L);
10960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Conditional jumps
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void j(Condition cc, Label* L);
10993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode);
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Conditional short jump
11020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  void j(Condition cc, NearLabel* L, Hint hint = no_hint);
11030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Floating-point operations
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fld(int i);
1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fld1();
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fldz();
11096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void fldpi();
1110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void fldln2();
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fld_s(const Operand& adr);
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fld_d(const Operand& adr);
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fstp_s(const Operand& adr);
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fstp_d(const Operand& adr);
11173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void fstp(int index);
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fild_s(const Operand& adr);
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fild_d(const Operand& adr);
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fist_s(const Operand& adr);
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fistp_s(const Operand& adr);
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fistp_d(const Operand& adr);
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fisttp_s(const Operand& adr);
1128d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void fisttp_d(const Operand& adr);
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fabs();
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fchs();
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fadd(int i);
1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fsub(int i);
1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fmul(int i);
1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fdiv(int i);
1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fisub_s(const Operand& adr);
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void faddp(int i = 1);
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fsubp(int i = 1);
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fsubrp(int i = 1);
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fmulp(int i = 1);
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fdivp(int i = 1);
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fprem();
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fprem1();
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fxch(int i = 1);
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fincstp();
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void ffree(int i = 0);
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void ftst();
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fucomp(int i);
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fucompp();
11553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void fucomi(int i);
11563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void fucomip();
11573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fcompp();
1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fnstsw_ax();
1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fwait();
1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fnclex();
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fsin();
1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fcos();
1165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void fyl2x();
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void frndint();
1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void sahf();
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // SSE2 instructions
11726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void movd(XMMRegister dst, Register src);
11736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void movd(Register dst, XMMRegister src);
11746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void movq(XMMRegister dst, Register src);
11756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void movq(Register dst, XMMRegister src);
11766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void extractps(Register dst, XMMRegister src, byte imm8);
11776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movsd(const Operand& dst, XMMRegister src);
11796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void movsd(XMMRegister dst, XMMRegister src);
11806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void movsd(XMMRegister dst, const Operand& src);
1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11828defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void movss(XMMRegister dst, const Operand& src);
11838defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void movss(const Operand& dst, XMMRegister src);
11848defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cvttss2si(Register dst, const Operand& src);
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cvttsd2si(Register dst, const Operand& src);
118725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  void cvttsd2siq(Register dst, XMMRegister src);
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cvtlsi2sd(XMMRegister dst, const Operand& src);
1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cvtlsi2sd(XMMRegister dst, Register src);
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cvtqsi2sd(XMMRegister dst, const Operand& src);
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cvtqsi2sd(XMMRegister dst, Register src);
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11948defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void cvtlsi2ss(XMMRegister dst, Register src);
11958defd9ff6930b4e24729971a61cf7469daf119beSteve Block
11966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void cvtss2sd(XMMRegister dst, XMMRegister src);
11978defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void cvtss2sd(XMMRegister dst, const Operand& src);
11988defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void cvtsd2ss(XMMRegister dst, XMMRegister src);
11998defd9ff6930b4e24729971a61cf7469daf119beSteve Block
12008defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void cvtsd2si(Register dst, XMMRegister src);
12018defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void cvtsd2siq(Register dst, XMMRegister src);
12026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addsd(XMMRegister dst, XMMRegister src);
1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subsd(XMMRegister dst, XMMRegister src);
1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void mulsd(XMMRegister dst, XMMRegister src);
1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void divsd(XMMRegister dst, XMMRegister src);
1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1208402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void xorpd(XMMRegister dst, XMMRegister src);
12096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void sqrtsd(XMMRegister dst, XMMRegister src);
1210402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1211402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void ucomisd(XMMRegister dst, XMMRegister src);
12128defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void ucomisd(XMMRegister dst, const Operand& src);
1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // The first argument is the reg field, the second argument is the r/m field.
1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_sse_operand(XMMRegister dst, XMMRegister src);
1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_sse_operand(XMMRegister reg, const Operand& adr);
1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_sse_operand(XMMRegister dst, Register src);
12186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void emit_sse_operand(Register dst, XMMRegister src);
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use either movsd or movlpd.
1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // void movdbl(XMMRegister dst, const Operand& src);
1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // void movdbl(const Operand& dst, XMMRegister src);
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Debugging
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Print();
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the code size generated from label to here.
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int SizeOfCodeGeneratedSince(Label* l) { return pc_offset() - l->pos(); }
1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Mark address of the ExitJSFrame code.
1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void RecordJSReturn();
1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Mark address of a debug break slot.
12347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  void RecordDebugBreakSlot();
12357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Record a comment relocation entry that can be used by a disassembler.
1237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Use --code-comments to enable.
1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void RecordComment(const char* msg);
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Writes a single word of data in the code stream.
1241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Used for inline tables, e.g., jump-tables.
1242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void db(uint8_t data) { UNIMPLEMENTED(); }
1243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void dd(uint32_t data);
1244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
12450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int pc_offset() const { return static_cast<int>(pc_ - buffer_); }
12463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
12473e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  PositionsRecorder* positions_recorder() { return &positions_recorder_; }
1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if there is less than kGap bytes available in the buffer.
1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If this is the case, we need to grow the buffer before emitting
1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // an instruction or relocation information.
1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline bool buffer_overflow() const {
1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return pc_ >= reloc_info_writer.pos() - kGap;
1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the number of bytes available in the buffer.
1257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  inline int available_space() const {
1258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return static_cast<int>(reloc_info_writer.pos() - pc_);
1259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  static bool IsNop(Address addr) { return *addr == 0x90; }
12627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Avoid overflows for displacements etc.
1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kMaximalBufferSize = 512*MB;
1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kMinimalBufferSize = 4*KB;
1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* addr_at(int pos)  { return buffer_ + pos; }
1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte byte_at(int pos)  { return buffer_[pos]; }
12700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint32_t long_at(int pos)  {
1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return *reinterpret_cast<uint32_t*>(addr_at(pos));
1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void long_at_put(int pos, uint32_t x)  {
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // code emission
1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void GrowBuffer();
1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit(byte x) { *pc_++ = x; }
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emitl(uint32_t x);
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emitq(uint64_t x, RelocInfo::Mode rmode);
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emitw(uint16_t x);
12853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  inline void emit_code_target(Handle<Code> target, RelocInfo::Mode rmode);
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit(Immediate x) { emitl(x.value_); }
1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emits a REX prefix that encodes a 64-bit operand size and
1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the top bit of both register codes.
1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W is set.
1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_64(XMMRegister reg, Register rm_reg);
12936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  inline void emit_rex_64(Register reg, XMMRegister rm_reg);
12946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  inline void emit_rex_64(Register reg, Register rm_reg);
1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emits a REX prefix that encodes a 64-bit operand size and
1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the top bit of the destination, index, and base register codes.
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The high bit of reg is used for REX.R, the high bit of op's base
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // register is used for REX.B, and the high bit of op's index register
1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is used for REX.X.  REX.W is set.
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_64(Register reg, const Operand& op);
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_64(XMMRegister reg, const Operand& op);
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emits a REX prefix that encodes a 64-bit operand size and
1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the top bit of the register code.
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The high bit of register is used for REX.B.
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W is set and REX.R and REX.X are clear.
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_64(Register rm_reg);
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emits a REX prefix that encodes a 64-bit operand size and
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the top bit of the index and base register codes.
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The high bit of op's base register is used for REX.B, and the high
1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bit of op's index register is used for REX.X.
1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W is set and REX.R clear.
1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_64(const Operand& op);
1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit a REX prefix that only sets REX.W to choose a 64-bit operand size.
1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_rex_64() { emit(0x48); }
1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W is clear.
1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_32(Register reg, Register rm_reg);
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The high bit of reg is used for REX.R, the high bit of op's base
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // register is used for REX.B, and the high bit of op's index register
1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is used for REX.X.  REX.W is cleared.
1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_32(Register reg, const Operand& op);
1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // High bit of rm_reg goes to REX.B.
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W, REX.R and REX.X are clear.
1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_32(Register rm_reg);
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // High bit of base goes to REX.B and high bit of index to REX.X.
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W and REX.R are clear.
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_32(const Operand& op);
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W is cleared.  If no REX bits are set, no byte is emitted.
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(Register reg, Register rm_reg);
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The high bit of reg is used for REX.R, the high bit of op's base
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // register is used for REX.B, and the high bit of op's index register
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is used for REX.X.  REX.W is cleared.  If no REX bits are set, nothing
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is emitted.
1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(Register reg, const Operand& op);
1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // As for emit_optional_rex_32(Register, Register), except that
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the registers are XMM registers.
1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(XMMRegister reg, XMMRegister base);
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // As for emit_optional_rex_32(Register, Register), except that
13526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // one of the registers is an XMM registers.
1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(XMMRegister reg, Register base);
1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // As for emit_optional_rex_32(Register, Register), except that
13566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // one of the registers is an XMM registers.
13576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  inline void emit_optional_rex_32(Register reg, XMMRegister base);
13586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // As for emit_optional_rex_32(Register, const Operand&), except that
1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the register is an XMM register.
1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(XMMRegister reg, const Operand& op);
1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Optionally do as emit_rex_32(Register) if the register number has
1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the high bit set.
1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(Register rm_reg);
1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Optionally do as emit_rex_32(const Operand&) if the operand register
1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // numbers have a high bit set.
1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(const Operand& op);
1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit the ModR/M byte, and optionally the SIB byte and
1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 1- or 4-byte offset for a memory operand.  Also encodes
1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the second operand of the operation, a register or operation
1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // subcode, into the reg field of the ModR/M byte.
1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_operand(Register reg, const Operand& adr) {
1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    emit_operand(reg.low_bits(), adr);
1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit the ModR/M byte, and optionally the SIB byte and
1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 1- or 4-byte offset for a memory operand.  Also used to encode
1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // a three-bit opcode extension into the ModR/M byte.
1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_operand(int rm, const Operand& adr);
1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit a ModR/M byte with registers coded in the reg and rm_reg fields.
1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_modrm(Register reg, Register rm_reg) {
1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    emit(0xC0 | reg.low_bits() << 3 | rm_reg.low_bits());
1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit a ModR/M byte with an operation subcode in the reg field and
1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // a register in the rm_reg field.
1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_modrm(int code, Register rm_reg) {
1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(is_uint3(code));
1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    emit(0xC0 | code << 3 | rm_reg.low_bits());
1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit the code-object-relative offset of the label's position
1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_code_relative_offset(Label* label);
1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit machine code for one of the operations ADD, ADC, SUB, SBC,
1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // AND, OR, XOR, or CMP.  The encodings of these operations are all
1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // similar, differing just in the opcode or in the reg field of the
1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ModR/M byte.
1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void arithmetic_op_16(byte opcode, Register reg, Register rm_reg);
1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg);
1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void arithmetic_op_32(byte opcode, Register reg, Register rm_reg);
1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void arithmetic_op_32(byte opcode, Register reg, const Operand& rm_reg);
1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void arithmetic_op(byte opcode, Register reg, Register rm_reg);
1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void arithmetic_op(byte opcode, Register reg, const Operand& rm_reg);
1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void immediate_arithmetic_op(byte subcode, Register dst, Immediate src);
1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void immediate_arithmetic_op(byte subcode, const Operand& dst, Immediate src);
1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Operate on a byte in memory or register.
1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void immediate_arithmetic_op_8(byte subcode,
1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register dst,
1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Immediate src);
1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void immediate_arithmetic_op_8(byte subcode,
1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 const Operand& dst,
1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Immediate src);
1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Operate on a word in memory or register.
1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void immediate_arithmetic_op_16(byte subcode,
1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Register dst,
1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Immediate src);
1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void immediate_arithmetic_op_16(byte subcode,
1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  const Operand& dst,
1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Immediate src);
1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Operate on a 32-bit word in memory or register.
1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void immediate_arithmetic_op_32(byte subcode,
1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Register dst,
1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Immediate src);
1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void immediate_arithmetic_op_32(byte subcode,
1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  const Operand& dst,
1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Immediate src);
1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit machine code for a shift operation.
1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shift(Register dst, Immediate shift_amount, int subcode);
1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shift_32(Register dst, Immediate shift_amount, int subcode);
1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shift dst by cl % 64 bits.
1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shift(Register dst, int subcode);
1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shift_32(Register dst, int subcode);
1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_farith(int b1, int b2, int i);
1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // labels
1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // void print(Label* L);
1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void bind_to(Label* L, int pos);
1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // record reloc info for current pc_
1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class CodePatcher;
1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class EnsureSpace;
1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class RegExpMacroAssemblerX64;
1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Code buffer:
1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The buffer into which code and relocation info are generated.
1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* buffer_;
1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int buffer_size_;
1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // True if the assembler owns the buffer, false if buffer is external.
1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool own_buffer_;
1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // A previously allocated buffer of kMinimalBufferSize bytes, or NULL.
1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static byte* spare_buffer_;
1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // code generation
1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* pc_;  // the program counter; moves forward
1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RelocInfoWriter reloc_info_writer;
1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  List< Handle<Code> > code_targets_;
1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // push-pop elimination
1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* last_pc_;
1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14713e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  PositionsRecorder positions_recorder_;
14723e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  friend class PositionsRecorder;
1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper class that ensures that there is enough space for generating
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// instructions and relocation information.  The constructor makes
1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// sure that there is enough space and (in debug mode) the destructor
1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// checks that we did not generate too much.
1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass EnsureSpace BASE_EMBEDDED {
1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (assembler_->buffer_overflow()) assembler_->GrowBuffer();
1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    space_before_ = assembler_->available_space();
1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ~EnsureSpace() {
1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int bytes_generated = space_before_ - assembler_->available_space();
1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(bytes_generated < assembler_->kGap);
1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
1497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Assembler* assembler_;
1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int space_before_;
1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_X64_ASSEMBLER_X64_H_
1506