assembler-x64.h revision 3ef787dbeca8a5fb1086949cda830dccee07bfbd
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright (c) 1994-2006 Sun Microsystems Inc.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// All Rights Reserved.
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// - Redistributions of source code must retain the above copyright notice,
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// this list of conditions and the following disclaimer.
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// - Redistribution in binary form must reproduce the above copyright
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer in the
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// documentation and/or other materials provided with the distribution.
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// - Neither the name of Sun Microsystems or the names of contributors may
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// be used to endorse or promote products derived from this software without
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// specific prior written permission.
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The original source code covered by the above license above has been
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modified significantly by Google Inc.
333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A lightweight X64 Assembler.
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_X64_ASSEMBLER_X64_H_
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_X64_ASSEMBLER_X64_H_
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
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.
483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline 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
533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline 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
583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline 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
633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline 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
9644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //  r12 - smi constant register
97b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  r13 - root register
98b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const int kNumRegisters = 16;
99b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const int kNumAllocatableRegisters = 10;
100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
101b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  static int ToAllocationIndex(Register reg) {
102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return kAllocationIndexByRegisterCode[reg.code()];
103b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
104b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
105b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  static Register FromAllocationIndex(int index) {
106b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Register result = { kRegisterCodeByAllocationIndex[index] };
108b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return result;
109b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
110b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const char* AllocationIndexToString(int index) {
112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    const char* const names[] = {
114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "rax",
115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "rbx",
116b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      "rdx",
117b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      "rcx",
118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "rdi",
119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "r8",
120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "r9",
121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "r11",
122b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      "r14",
12344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      "r15"
124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    };
125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return names[index];
126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static Register from_code(int code) {
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Register r = { code };
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return r;
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
1330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  bool is(Register reg) const { return code_ == reg.code_; }
1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rax, rbx, rcx and rdx are byte registers, the rest are not.
1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool is_byte_register() const { return code_ <= 3; }
1360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int code() const {
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(is_valid());
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return code_;
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int bit() const {
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 1 << code_;
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the high bit of the register code as a 0 or 1.  Used often
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // when constructing the REX prefix byte.
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int high_bit() const {
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return code_ >> 3;
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the 3 low bits of the register code.  Used when encoding registers
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in modR/M, SIB, and opcode bytes.
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int low_bits() const {
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return code_ & 0x7;
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Unfortunately we can't make this private in a struct when initializing
1563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // by assignment.
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int code_;
1581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
159b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch private:
160e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  static const int kRegisterCodeByAllocationIndex[kNumAllocatableRegisters];
161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  static const int kAllocationIndexByRegisterCode[kNumRegisters];
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_rax_Code = 0;
1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_rcx_Code = 1;
1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_rdx_Code = 2;
1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_rbx_Code = 3;
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_rsp_Code = 4;
1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_rbp_Code = 5;
1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_rsi_Code = 6;
1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_rdi_Code = 7;
1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_r8_Code = 8;
1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_r9_Code = 9;
1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_r10_Code = 10;
1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_r11_Code = 11;
1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_r12_Code = 12;
1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_r13_Code = 13;
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_r14_Code = 14;
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_r15_Code = 15;
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_no_reg_Code = -1;
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register rax = { kRegister_rax_Code };
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register rcx = { kRegister_rcx_Code };
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register rdx = { kRegister_rdx_Code };
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register rbx = { kRegister_rbx_Code };
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register rsp = { kRegister_rsp_Code };
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register rbp = { kRegister_rbp_Code };
1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register rsi = { kRegister_rsi_Code };
1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register rdi = { kRegister_rdi_Code };
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register r8 = { kRegister_r8_Code };
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register r9 = { kRegister_r9_Code };
1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register r10 = { kRegister_r10_Code };
1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register r11 = { kRegister_r11_Code };
1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register r12 = { kRegister_r12_Code };
1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register r13 = { kRegister_r13_Code };
1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register r14 = { kRegister_r14_Code };
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register r15 = { kRegister_r15_Code };
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register no_reg = { kRegister_no_reg_Code };
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct XMMRegister {
202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const int kNumRegisters = 16;
203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const int kNumAllocatableRegisters = 15;
204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static int ToAllocationIndex(XMMRegister reg) {
206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(reg.code() != 0);
207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return reg.code() - 1;
208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
210b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  static XMMRegister FromAllocationIndex(int index) {
211b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    ASSERT(0 <= index && index < kNumAllocatableRegisters);
212b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    XMMRegister result = { index + 1 };
213b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return result;
214b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
215b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const char* AllocationIndexToString(int index) {
217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    const char* const names[] = {
219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm1",
220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm2",
221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm3",
222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm4",
223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm5",
224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm6",
225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm7",
226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm8",
227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm9",
228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm10",
229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm11",
230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm12",
231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm13",
232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm14",
233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm15"
234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    };
235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return names[index];
236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static XMMRegister from_code(int code) {
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(code >= 0);
2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(code < kNumRegisters);
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    XMMRegister r = { code };
2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return r;
2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
245b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  bool is(XMMRegister reg) const { return code_ == reg.code_; }
2460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int code() const {
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(is_valid());
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return code_;
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the high bit of the register code as a 0 or 1.  Used often
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // when constructing the REX prefix byte.
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int high_bit() const {
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return code_ >> 3;
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the 3 low bits of the register code.  Used when encoding registers
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in modR/M, SIB, and opcode bytes.
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int low_bits() const {
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return code_ & 0x7;
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int code_;
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
265402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm0 = { 0 };
266402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm1 = { 1 };
267402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm2 = { 2 };
268402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm3 = { 3 };
269402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm4 = { 4 };
270402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm5 = { 5 };
271402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm6 = { 6 };
272402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm7 = { 7 };
273402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm8 = { 8 };
274402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm9 = { 9 };
275402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm10 = { 10 };
276402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm11 = { 11 };
277402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm12 = { 12 };
278402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm13 = { 13 };
279402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm14 = { 14 };
280402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm15 = { 15 };
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochtypedef XMMRegister DoubleRegister;
284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum Condition {
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // any value < 0 is considered no_condition
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  no_condition  = -1,
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  overflow      =  0,
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  no_overflow   =  1,
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  below         =  2,
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  above_equal   =  3,
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  equal         =  4,
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  not_equal     =  5,
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  below_equal   =  6,
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  above         =  7,
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  negative      =  8,
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  positive      =  9,
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  parity_even   = 10,
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  parity_odd    = 11,
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  less          = 12,
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  greater_equal = 13,
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  less_equal    = 14,
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  greater       = 15,
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Fake conditions that are handled by the
3083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // opcodes using them.
3093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  always        = 16,
3103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  never         = 17,
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // aliases
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  carry         = below,
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  not_carry     = above_equal,
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  zero          = equal,
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  not_zero      = not_equal,
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  sign          = negative,
3173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  not_sign      = positive,
3183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  last_condition = greater
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns the equivalent of !cc.
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Negation of the default no_condition (-1) results in a non-default
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// no_condition value (-2). As long as tests for no_condition check
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// for condition < 0, this will work as expected.
3269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monseninline Condition NegateCondition(Condition cc) {
3279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  return static_cast<Condition>(cc ^ 1);
3289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
3299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Corresponds to transposing the operands of a comparison.
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline Condition ReverseCondition(Condition cc) {
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (cc) {
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case below:
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return above;
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case above:
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return below;
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case above_equal:
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return below_equal;
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case below_equal:
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return above_equal;
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case less:
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return greater;
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case greater:
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return less;
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case greater_equal:
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return less_equal;
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case less_equal:
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return greater_equal;
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return cc;
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Machine instruction Immediates
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Immediate BASE_EMBEDDED {
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit Immediate(int32_t value) : value_(value) {}
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int32_t value_;
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class Assembler;
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Machine instruction Operands
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum ScaleFactor {
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_1 = 0,
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_2 = 1,
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_4 = 2,
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_8 = 3,
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_int_size = times_4,
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_pointer_size = times_8
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Operand BASE_EMBEDDED {
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // [base + disp/r]
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Operand(Register base, int32_t disp);
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // [base + index*scale + disp/r]
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Operand(Register base,
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Register index,
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          ScaleFactor scale,
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int32_t disp);
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // [index*scale + disp/r]
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Operand(Register index,
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          ScaleFactor scale,
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int32_t disp);
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
399f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Offset from existing memory operand.
400f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Offset is added to existing displacement as 32-bit signed values and
401f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // this must not overflow.
402f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Operand(const Operand& base, int32_t offset);
403f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Checks whether either base or index register is the given register.
4051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Does not check the "reg" part of the Operand.
4061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool AddressUsesRegister(Register reg) const;
4071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
40844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Queries related to the size of the generated instruction.
40944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Whether the generated instruction will have a REX prefix.
41044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool requires_rex() const { return rex_ != 0; }
41144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Size of the ModR/M, SIB and displacement parts of the generated
41244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // instruction.
41344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int operand_size() const { return len_; }
41444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte rex_;
4177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  byte buf_[6];
4181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The number of bytes of buf_ in use.
4191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  byte len_;
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the ModR/M byte without an encoded 'reg' register. The
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // register is encoded later as part of the emit_operand operation.
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // set_modrm can be called before or after set_sib and set_disp*.
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void set_modrm(int mod, Register rm);
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the SIB byte if one is needed. Sets the length to 2 rather than 1.
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void set_sib(ScaleFactor scale, Register index, Register base);
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adds operand displacement fields (offsets added to the memory address).
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Needs to be called after set_sib, not before it.
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void set_disp8(int disp);
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void set_disp32(int disp);
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class Assembler;
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CpuFeatures keeps track of which features are supported by the target CPU.
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Supported features must be enabled by a Scope before use.
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Example:
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   if (CpuFeatures::IsSupported(SSE3)) {
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     CpuFeatures::Scope fscope(SSE3);
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     // Generate SSE3 floating point code.
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   } else {
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     // Generate standard x87 or SSE2 floating point code.
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   }
4478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass CpuFeatures : public AllStatic {
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Detect features of the target CPU. Set safe defaults if the serializer
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is enabled (snapshots must be portable).
4518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  static void Probe();
45244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check whether a feature is supported by the target CPU.
4548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  static bool IsSupported(CpuFeature f) {
4558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(initialized_);
4563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (f == SSE2 && !FLAG_enable_sse2) return false;
4573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (f == SSE3 && !FLAG_enable_sse3) return false;
4583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (f == CMOV && !FLAG_enable_cmov) return false;
4593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (f == RDTSC && !FLAG_enable_rdtsc) return false;
4603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (f == SAHF && !FLAG_enable_sahf) return false;
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return (supported_ & (V8_UINT64_C(1) << f)) != 0;
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
4648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef DEBUG
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check whether a feature is currently enabled.
4668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  static bool IsEnabled(CpuFeature f) {
4678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(initialized_);
4688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Isolate* isolate = Isolate::UncheckedCurrent();
4698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (isolate == NULL) {
4708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      // When no isolate is available, work as if we're running in
4718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      // release mode.
4728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return IsSupported(f);
4738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
4748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    uint64_t enabled = isolate->enabled_cpu_features();
4758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return (enabled & (V8_UINT64_C(1) << f)) != 0;
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif
4788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enable a specified feature within a scope.
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  class Scope BASE_EMBEDDED {
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
482589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block   public:
4848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    explicit Scope(CpuFeature f) {
4858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      uint64_t mask = V8_UINT64_C(1) << f;
4868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      ASSERT(CpuFeatures::IsSupported(f));
48744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ASSERT(!Serializer::enabled() ||
4888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch             (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
4898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      isolate_ = Isolate::UncheckedCurrent();
4908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      old_enabled_ = 0;
4918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (isolate_ != NULL) {
4928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        old_enabled_ = isolate_->enabled_cpu_features();
4938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        isolate_->set_enabled_cpu_features(old_enabled_ | mask);
4948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
49544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
49644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ~Scope() {
4978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
4988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (isolate_ != NULL) {
4998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        isolate_->set_enabled_cpu_features(old_enabled_);
5008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
502589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block   private:
50444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Isolate* isolate_;
5058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    uint64_t old_enabled_;
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else
507589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block   public:
509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    explicit Scope(CpuFeature f) {}
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
51244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch private:
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Safe defaults include SSE2 and CMOV for X64. It is always available, if
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // anyone checks, but they shouldn't need to check.
51644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // The required user mode extensions in X64 are (from AMD64 ABI Table A.1):
51744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   fpu, tsc, cx8, cmov, mmx, sse, sse2, fxsr, syscall
518d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static const uint64_t kDefaultCpuFeatures = (1 << SSE2 | 1 << CMOV);
51944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef DEBUG
5218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  static bool initialized_;
5228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif
5238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  static uint64_t supported_;
5248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  static uint64_t found_by_runtime_probing_;
52544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
52644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
53044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass Assembler : public AssemblerBase {
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We check before assembling an instruction that there is sufficient
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // space to write an instruction and its relocation information.
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The relocation writer's position must be kGap bytes above the end of
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the generated instructions. This leaves enough space for the
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // longest possible x64 instruction, 15 bytes, and the longest possible
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // (There is a 15 byte limit on x64 instruction length that rules out some
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // otherwise valid instructions.)
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This allows for a single, fast space check per instruction.
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kGap = 32;
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create an assembler. Instructions and relocation information are emitted
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // into a buffer, with the instructions starting from the beginning and the
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // relocation information starting from the end of the buffer. See CodeDesc
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // for a detailed comment on the layout (globals.h).
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the provided buffer is NULL, the assembler allocates and grows its own
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // buffer, and buffer_size determines the initial buffer size. The buffer is
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // owned by the assembler and deallocated upon destruction of the assembler.
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the provided buffer is not NULL, the assembler uses the provided buffer
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // for code generation and assumes its size to be buffer_size. If the buffer
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is too small, a fatal error occurs. No deallocation of the buffer is done
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // upon destruction of the assembler.
5578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Assembler(Isolate* isolate, void* buffer, int buffer_size);
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ~Assembler();
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
56044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Overrides the default provided by FLAG_debug_code.
56144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
56244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // GetCode emits any pending (non-emitted) code and fills the descriptor
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // desc. GetCode() is idempotent; it returns the same result if no other
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Assembler functions are invoked in between GetCode() calls.
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void GetCode(CodeDesc* desc);
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Read/Modify the code target in the relative branch/call instruction at pc.
5693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // On the x64 architecture, we use relative jumps with a 32-bit displacement
5703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // to jump to other Code objects in the Code space in the heap.
5713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Jumps to C functions are done indirectly through a 64-bit register holding
5723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // the absolute address of the target.
5733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // These functions convert between absolute Addresses of Code objects and
5743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // the relative displacements stored in the code.
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static inline Address target_address_at(Address pc);
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static inline void set_target_address_at(Address pc, Address target);
577d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
578d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This sets the branch destination (which is in the instruction on x64).
579d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This is for calls and branches within generated code.
5803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline static void deserialization_set_special_target_at(
5813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Address instruction_payload, Address target) {
582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    set_target_address_at(instruction_payload, target);
583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
585d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This sets the branch destination (which is a load instruction on x64).
586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This is for calls and branches to runtime code.
587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  inline static void set_external_target_at(Address instruction_payload,
588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                            Address target) {
589d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    *reinterpret_cast<Address*>(instruction_payload) = target;
590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
591d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  inline Handle<Object> code_target_object_handle_at(Address pc);
593d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Number of bytes taken up by the branch target in the code.
5943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kSpecialTargetSize = 4;  // Use 32-bit displacement.
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Distance between the address of the code target in the call instruction
5963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // and the return address pushed on the stack.
5973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  static const int kCallTargetAddressOffset = 4;  // Use 32-bit displacement.
5983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Distance between the start of the JS return sequence and where the
5993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // 32-bit displacement of a near call would be, relative to the pushed
6003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // return address.  TODO: Use return sequence length instead.
6013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
6023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  static const int kPatchReturnSequenceAddressOffset = 13 - 4;
6037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Distance between start of patched debug break slot and where the
6047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // 32-bit displacement of a near call would be, relative to the pushed
6057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // return address.  TODO: Use return sequence length instead.
6067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
6077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  static const int kPatchDebugBreakSlotAddressOffset = 13 - 4;
6083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // TODO(X64): Rename this, removing the "Real", after changing the above.
6093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  static const int kRealPatchReturnSequenceAddressOffset = 2;
610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Some x64 JS code is padded with int3 to make it large
6121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // enough to hold an instruction when the debugger patches it.
6131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const int kJumpInstructionLength = 13;
614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static const int kCallInstructionLength = 13;
615d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static const int kJSReturnSequenceLength = 13;
6161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const int kShortCallInstructionLength = 5;
617d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // The debug break slot must be able to contain a call instruction.
6197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  static const int kDebugBreakSlotLength = kCallInstructionLength;
6207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
6219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // One byte opcode for test eax,0xXXXXXXXX.
6229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  static const byte kTestEaxByte = 0xA9;
6231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // One byte opcode for test al, 0xXX.
6241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const byte kTestAlByte = 0xA8;
6251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // One byte opcode for nop.
6261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const byte kNopByte = 0x90;
6271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // One byte prefix for a short conditional jump.
6291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const byte kJccShortPrefix = 0x70;
6301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const byte kJncShortOpcode = kJccShortPrefix | not_carry;
6311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const byte kJcShortOpcode = kJccShortPrefix | carry;
6321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Code generation
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Function names correspond one-to-one to x64 instruction mnemonics.
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Unless specified otherwise, instructions operate on 64-bit operands.
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If we need versions of an assembly instruction that operate on different
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // width arguments, we add a single-letter suffix specifying the width.
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This is done for the following instructions: mov, cmp, inc, dec,
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // add, sub, and test.
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // There are no versions of these instructions without the suffix.
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'.
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // - Instructions on 16-bit (word) operands/registers have a trailing 'w'.
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // - Instructions on 32-bit (doubleword) operands/registers use 'l'.
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // - Instructions on 64-bit (quadword) operands/registers use 'q'.
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Some mnemonics, such as "and", are the same as C++ keywords.
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Naming conflicts with C++ keywords are resolved by adding a trailing '_'.
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Insert the smallest number of nop instructions
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // possible to align the pc offset to a multiple
6561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // of m, where m must be a power of 2.
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Align(int m);
6583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Nop(int bytes = 1);
6599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Aligns code to something that's optimal for a jump target for the platform.
6609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  void CodeTargetAlign();
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stack
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void pushfq();
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void popfq();
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void push(Immediate value);
6671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Push a 32 bit integer, and guarantee that it is actually pushed as a
6681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // 32 bit value, the normal push will optimize the 8 bit case.
6691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void push_imm32(int32_t imm32);
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void push(Register src);
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void push(const Operand& src);
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void pop(Register dst);
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void pop(const Operand& dst);
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void enter(Immediate size);
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void leave();
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Moves
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movb(Register dst, const Operand& src);
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movb(Register dst, Immediate imm);
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movb(const Operand& dst, Register src);
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Move the low 16 bits of a 64-bit register value to a 16-bit
6853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // memory location.
6863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void movw(const Operand& dst, Register src);
6873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movl(Register dst, Register src);
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movl(Register dst, const Operand& src);
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movl(const Operand& dst, Register src);
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movl(const Operand& dst, Immediate imm);
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load a 32-bit immediate value, zero-extended to 64 bits.
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movl(Register dst, Immediate imm32);
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move 64 bit register value to 64-bit memory location.
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movq(const Operand& dst, Register src);
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move 64 bit memory location to 64-bit register value.
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movq(Register dst, const Operand& src);
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movq(Register dst, Register src);
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Sign extends immediate 32-bit value to 64 bits.
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movq(Register dst, Immediate x);
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move the offset of the label location relative to the current
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // position (after the move) to the destination.
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movl(const Operand& dst, Label* src);
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move sign extended immediate to memory location.
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movq(const Operand& dst, Immediate value);
70844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Instructions to load a 64-bit immediate into a register.
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All 64-bit immediates must have a relocation mode.
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movq(Register dst, void* ptr, RelocInfo::Mode rmode);
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movq(Register dst, int64_t value, RelocInfo::Mode rmode);
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movq(Register dst, const char* s, RelocInfo::Mode rmode);
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Moves the address of the external reference into the register.
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movq(Register dst, ExternalReference ext);
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movq(Register dst, Handle<Object> handle, RelocInfo::Mode rmode);
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void movsxbq(Register dst, const Operand& src);
7183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void movsxwq(Register dst, const Operand& src);
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movsxlq(Register dst, Register src);
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movsxlq(Register dst, const Operand& src);
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movzxbq(Register dst, const Operand& src);
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movzxbl(Register dst, const Operand& src);
7233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void movzxwq(Register dst, const Operand& src);
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movzxwl(Register dst, const Operand& src);
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
726d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Repeated moves.
727d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
728d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void repmovsb();
729d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void repmovsw();
730d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void repmovsl();
731d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void repmovsq();
732d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
73344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Instruction to load from an immediate 64-bit pointer into RAX.
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void load_rax(void* ptr, RelocInfo::Mode rmode);
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void load_rax(ExternalReference ext);
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Conditional moves.
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmovq(Condition cc, Register dst, Register src);
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmovq(Condition cc, Register dst, const Operand& src);
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmovl(Condition cc, Register dst, Register src);
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmovl(Condition cc, Register dst, const Operand& src);
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Exchange two registers
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void xchg(Register dst, Register src);
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Arithmetics
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addl(Register dst, Register src) {
748f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    arithmetic_op_32(0x03, dst, src);
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addl(Register dst, Immediate src) {
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_32(0x0, dst, src);
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addl(Register dst, const Operand& src) {
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_32(0x03, dst, src);
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addl(const Operand& dst, Immediate src) {
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_32(0x0, dst, src);
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void addl(const Operand& dst, Register src) {
7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    arithmetic_op_32(0x01, src, dst);
7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addq(Register dst, Register src) {
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x03, dst, src);
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addq(Register dst, const Operand& src) {
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x03, dst, src);
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addq(const Operand& dst, Register src) {
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x01, src, dst);
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addq(Register dst, Immediate src) {
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x0, dst, src);
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addq(const Operand& dst, Immediate src) {
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x0, dst, src);
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
78725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  void sbbl(Register dst, Register src) {
788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    arithmetic_op_32(0x1b, dst, src);
78925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  }
79025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
7911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void sbbq(Register dst, Register src) {
7921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    arithmetic_op(0x1b, dst, src);
7931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
7941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpb(Register dst, Immediate src) {
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_8(0x7, dst, src);
797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpb_al(Immediate src);
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpb(Register dst, Register src) {
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x3A, dst, src);
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpb(Register dst, const Operand& src) {
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x3A, dst, src);
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpb(const Operand& dst, Register src) {
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x38, src, dst);
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpb(const Operand& dst, Immediate src) {
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_8(0x7, dst, src);
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpw(const Operand& dst, Immediate src) {
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_16(0x7, dst, src);
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpw(Register dst, Immediate src) {
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_16(0x7, dst, src);
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpw(Register dst, const Operand& src) {
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_16(0x3B, dst, src);
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpw(Register dst, Register src) {
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_16(0x3B, dst, src);
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpw(const Operand& dst, Register src) {
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_16(0x39, src, dst);
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpl(Register dst, Register src) {
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_32(0x3B, dst, src);
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpl(Register dst, const Operand& src) {
842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_32(0x3B, dst, src);
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpl(const Operand& dst, Register src) {
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_32(0x39, src, dst);
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpl(Register dst, Immediate src) {
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_32(0x7, dst, src);
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpl(const Operand& dst, Immediate src) {
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_32(0x7, dst, src);
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpq(Register dst, Register src) {
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x3B, dst, src);
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpq(Register dst, const Operand& src) {
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x3B, dst, src);
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpq(const Operand& dst, Register src) {
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x39, src, dst);
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpq(Register dst, Immediate src) {
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x7, dst, src);
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpq(const Operand& dst, Immediate src) {
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x7, dst, src);
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void and_(Register dst, Register src) {
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x23, dst, src);
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void and_(Register dst, const Operand& src) {
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x23, dst, src);
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void and_(const Operand& dst, Register src) {
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x21, src, dst);
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void and_(Register dst, Immediate src) {
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x4, dst, src);
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void and_(const Operand& dst, Immediate src) {
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x4, dst, src);
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void andl(Register dst, Immediate src) {
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_32(0x4, dst, src);
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void andl(Register dst, Register src) {
9023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    arithmetic_op_32(0x23, dst, src);
9033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
9043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void andl(Register dst, const Operand& src) {
9061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    arithmetic_op_32(0x23, dst, src);
9071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
9081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  void andb(Register dst, Immediate src) {
9104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    immediate_arithmetic_op_8(0x4, dst, src);
9114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
9123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void decq(Register dst);
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void decq(const Operand& dst);
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void decl(Register dst);
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void decl(const Operand& dst);
9173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void decb(Register dst);
9183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void decb(const Operand& dst);
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Sign-extends rax into rdx:rax.
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cqo();
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Sign-extends eax into edx:eax.
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cdq();
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Divide rdx:rax by src.  Quotient in rax, remainder in rdx.
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void idivq(Register src);
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Divide edx:eax by lower 32 bits of src.  Quotient in eax, rem. in edx.
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void idivl(Register src);
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Signed multiply instructions.
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void imul(Register src);                               // rdx:rax = rax * src.
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void imul(Register dst, Register src);                 // dst = dst * src.
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void imul(Register dst, const Operand& src);           // dst = dst * src.
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void imul(Register dst, Register src, Immediate imm);  // dst = src * imm.
9356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Signed 32-bit multiply instructions.
9366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void imull(Register dst, Register src);                 // dst = dst * src.
9371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void imull(Register dst, const Operand& src);           // dst = dst * src.
9386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void imull(Register dst, Register src, Immediate imm);  // dst = src * imm.
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void incq(Register dst);
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void incq(const Operand& dst);
9429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  void incl(Register dst);
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void incl(const Operand& dst);
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void lea(Register dst, const Operand& src);
9466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void leal(Register dst, const Operand& src);
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Multiply rax by src, put the result in rdx:rax.
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void mul(Register src);
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void neg(Register dst);
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void neg(const Operand& dst);
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void negl(Register dst);
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void not_(Register dst);
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void not_(const Operand& dst);
9576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void notl(Register dst);
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void or_(Register dst, Register src) {
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x0B, dst, src);
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void orl(Register dst, Register src) {
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_32(0x0B, dst, src);
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void or_(Register dst, const Operand& src) {
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x0B, dst, src);
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void orl(Register dst, const Operand& src) {
9721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    arithmetic_op_32(0x0B, dst, src);
9731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
9741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void or_(const Operand& dst, Register src) {
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x09, src, dst);
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void or_(Register dst, Immediate src) {
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x1, dst, src);
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void orl(Register dst, Immediate src) {
9843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    immediate_arithmetic_op_32(0x1, dst, src);
9853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
9863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void or_(const Operand& dst, Immediate src) {
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x1, dst, src);
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void orl(const Operand& dst, Immediate src) {
9923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    immediate_arithmetic_op_32(0x1, dst, src);
9933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
9943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void rcl(Register dst, Immediate imm8) {
9973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shift(dst, imm8, 0x2);
9983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
9993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void rol(Register dst, Immediate imm8) {
10013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shift(dst, imm8, 0x0);
10023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
10033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void rcr(Register dst, Immediate imm8) {
10053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shift(dst, imm8, 0x3);
10063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
10073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void ror(Register dst, Immediate imm8) {
10093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    shift(dst, imm8, 0x1);
10103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shifts dst:src left by cl bits, affecting only dst.
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shld(Register dst, Register src);
1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shifts src:dst right by cl bits, affecting only dst.
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shrd(Register dst, Register src);
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shifts dst right, duplicating sign bit, by shift_amount bits.
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shifting by 1 is handled efficiently.
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void sar(Register dst, Immediate shift_amount) {
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift(dst, shift_amount, 0x7);
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shifts dst right, duplicating sign bit, by shift_amount bits.
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shifting by 1 is handled efficiently.
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void sarl(Register dst, Immediate shift_amount) {
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift_32(dst, shift_amount, 0x7);
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shifts dst right, duplicating sign bit, by cl % 64 bits.
1031d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void sar_cl(Register dst) {
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift(dst, 0x7);
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shifts dst right, duplicating sign bit, by cl % 64 bits.
1036d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void sarl_cl(Register dst) {
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift_32(dst, 0x7);
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shl(Register dst, Immediate shift_amount) {
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift(dst, shift_amount, 0x4);
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1044d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void shl_cl(Register dst) {
1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift(dst, 0x4);
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1048d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void shll_cl(Register dst) {
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift_32(dst, 0x4);
1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shll(Register dst, Immediate shift_amount) {
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift_32(dst, shift_amount, 0x4);
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shr(Register dst, Immediate shift_amount) {
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift(dst, shift_amount, 0x5);
1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1060d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void shr_cl(Register dst) {
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift(dst, 0x5);
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1064d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void shrl_cl(Register dst) {
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift_32(dst, 0x5);
1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shrl(Register dst, Immediate shift_amount) {
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift_32(dst, shift_amount, 0x5);
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void store_rax(void* dst, RelocInfo::Mode mode);
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void store_rax(ExternalReference ref);
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subq(Register dst, Register src) {
1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x2B, dst, src);
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subq(Register dst, const Operand& src) {
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x2B, dst, src);
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subq(const Operand& dst, Register src) {
1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x29, src, dst);
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subq(Register dst, Immediate src) {
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x5, dst, src);
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subq(const Operand& dst, Immediate src) {
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x5, dst, src);
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subl(Register dst, Register src) {
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_32(0x2B, dst, src);
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1099e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void subl(Register dst, const Operand& src) {
1100e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    arithmetic_op_32(0x2B, dst, src);
1101e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
1102e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subl(const Operand& dst, Immediate src) {
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_32(0x5, dst, src);
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subl(Register dst, Immediate src) {
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_32(0x5, dst, src);
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subb(Register dst, Immediate src) {
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op_8(0x5, dst, src);
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void testb(Register dst, Register src);
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void testb(Register reg, Immediate mask);
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void testb(const Operand& op, Immediate mask);
1118e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void testb(const Operand& op, Register reg);
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void testl(Register dst, Register src);
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void testl(Register reg, Immediate mask);
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void testl(const Operand& op, Immediate mask);
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void testq(const Operand& op, Register reg);
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void testq(Register dst, Register src);
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void testq(Register dst, Immediate mask);
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void xor_(Register dst, Register src) {
1127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (dst.code() == src.code()) {
1128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      arithmetic_op_32(0x33, dst, src);
1129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
1130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      arithmetic_op(0x33, dst, src);
1131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void xorl(Register dst, Register src) {
1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op_32(0x33, dst, src);
1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void xorl(Register dst, const Operand& src) {
11391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    arithmetic_op_32(0x33, dst, src);
11401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
11411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
11421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void xorl(Register dst, Immediate src) {
11431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    immediate_arithmetic_op_32(0x6, dst, src);
11441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
11451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
11461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void xorl(const Operand& dst, Immediate src) {
11471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    immediate_arithmetic_op_32(0x6, dst, src);
11481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
11491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void xor_(Register dst, const Operand& src) {
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x33, dst, src);
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void xor_(const Operand& dst, Register src) {
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    arithmetic_op(0x31, src, dst);
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void xor_(Register dst, Immediate src) {
1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x6, dst, src);
1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void xor_(const Operand& dst, Immediate src) {
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    immediate_arithmetic_op(0x6, dst, src);
1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Bit operations.
1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void bt(const Operand& dst, Register src);
1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void bts(const Operand& dst, Register src);
1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Miscellaneous
11713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void clc();
117244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void cld();
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cpuid();
1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void hlt();
1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void int3();
1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void nop();
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void rdtsc();
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void ret(int imm16);
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void setcc(Condition cc, Register reg);
1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Label operations & relative jumps (PPUM Appendix D)
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Takes a branch opcode (cc) and a label (L) and generates
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // either a backward branch or a forward branch and links it
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to the label fixup chain. Usage:
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Label L;    // unbound label
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // j(cc, &L);  // forward branch to unbound label
1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bind(&L);   // bind label to the current pc
1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // j(cc, &L);  // backward branch to bound label
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bind(&L);   // illegal: a label may be bound only once
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Note: The same Label can be used for forward and backward branches
1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // but it may be bound only once.
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void bind(Label* L);  // binds an unbound label L to the current code position
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calls
1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call near relative 32-bit displacement, relative to next instruction.
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void call(Label* L);
1201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void call(Handle<Code> target,
12023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
1203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            unsigned ast_id = kNoASTId);
1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Calls directly to the given address using a relative offset.
12061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Should only ever be used in Code objects for calls within the
12071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // same Code object. Should not be used when generating new code (use labels),
12081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // but only when patching existing code.
12091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void call(Address target);
12101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call near absolute indirect, address in register
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void call(Register adr);
1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call near indirect
1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void call(const Operand& operand);
1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jumps
1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump short or near relative.
12193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Use a 32-bit signed displacement.
1220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Unconditional jump to L
1221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void jmp(Label* L, Label::Distance distance = Label::kFar);
12223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void jmp(Handle<Code> target, RelocInfo::Mode rmode);
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump near absolute indirect (r64)
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void jmp(Register adr);
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump near absolute indirect (m64)
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void jmp(const Operand& src);
1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Conditional jumps
1231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void j(Condition cc,
1232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         Label* L,
1233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         Label::Distance distance = Label::kFar);
12343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode);
1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Floating-point operations
1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fld(int i);
1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fld1();
1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fldz();
12416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void fldpi();
1242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void fldln2();
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fld_s(const Operand& adr);
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fld_d(const Operand& adr);
1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fstp_s(const Operand& adr);
1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fstp_d(const Operand& adr);
12493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void fstp(int index);
1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fild_s(const Operand& adr);
1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fild_d(const Operand& adr);
1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fist_s(const Operand& adr);
1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fistp_s(const Operand& adr);
1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fistp_d(const Operand& adr);
1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fisttp_s(const Operand& adr);
1260d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void fisttp_d(const Operand& adr);
1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fabs();
1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fchs();
1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fadd(int i);
1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fsub(int i);
1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fmul(int i);
1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fdiv(int i);
1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fisub_s(const Operand& adr);
1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void faddp(int i = 1);
1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fsubp(int i = 1);
1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fsubrp(int i = 1);
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fmulp(int i = 1);
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fdivp(int i = 1);
1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fprem();
1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fprem1();
1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fxch(int i = 1);
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fincstp();
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void ffree(int i = 0);
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void ftst();
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fucomp(int i);
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fucompp();
12873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void fucomi(int i);
12883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void fucomip();
12893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fcompp();
1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fnstsw_ax();
1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fwait();
1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fnclex();
1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fsin();
1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fcos();
12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void fptan();
1298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void fyl2x();
12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void f2xm1();
13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void fscale();
13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void fninit();
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void frndint();
1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void sahf();
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // SSE2 instructions
13086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void movd(XMMRegister dst, Register src);
13096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void movd(Register dst, XMMRegister src);
13106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void movq(XMMRegister dst, Register src);
13116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void movq(Register dst, XMMRegister src);
1312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void movq(XMMRegister dst, XMMRegister src);
13136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void extractps(Register dst, XMMRegister src, byte imm8);
13146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Don't use this unless it's important to keep the
1316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // top half of the destination register unchanged.
1317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Used movaps when moving double values and movq for integer
1318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // values in xmm registers.
1319053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  void movsd(XMMRegister dst, XMMRegister src);
1320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void movsd(const Operand& dst, XMMRegister src);
13226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void movsd(XMMRegister dst, const Operand& src);
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void movdqa(const Operand& dst, XMMRegister src);
13251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void movdqa(XMMRegister dst, const Operand& src);
13261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void movapd(XMMRegister dst, XMMRegister src);
1328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void movaps(XMMRegister dst, XMMRegister src);
1329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
13308defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void movss(XMMRegister dst, const Operand& src);
13318defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void movss(const Operand& dst, XMMRegister src);
13328defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cvttss2si(Register dst, const Operand& src);
13341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void cvttss2si(Register dst, XMMRegister src);
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cvttsd2si(Register dst, const Operand& src);
13361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void cvttsd2si(Register dst, XMMRegister src);
133725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  void cvttsd2siq(Register dst, XMMRegister src);
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cvtlsi2sd(XMMRegister dst, const Operand& src);
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cvtlsi2sd(XMMRegister dst, Register src);
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cvtqsi2sd(XMMRegister dst, const Operand& src);
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cvtqsi2sd(XMMRegister dst, Register src);
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13448defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void cvtlsi2ss(XMMRegister dst, Register src);
13458defd9ff6930b4e24729971a61cf7469daf119beSteve Block
13466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void cvtss2sd(XMMRegister dst, XMMRegister src);
13478defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void cvtss2sd(XMMRegister dst, const Operand& src);
13488defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void cvtsd2ss(XMMRegister dst, XMMRegister src);
13498defd9ff6930b4e24729971a61cf7469daf119beSteve Block
13508defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void cvtsd2si(Register dst, XMMRegister src);
13518defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void cvtsd2siq(Register dst, XMMRegister src);
13526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addsd(XMMRegister dst, XMMRegister src);
1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subsd(XMMRegister dst, XMMRegister src);
1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void mulsd(XMMRegister dst, XMMRegister src);
1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void divsd(XMMRegister dst, XMMRegister src);
1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1358e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void andpd(XMMRegister dst, XMMRegister src);
1359e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void orpd(XMMRegister dst, XMMRegister src);
1360402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void xorpd(XMMRegister dst, XMMRegister src);
1361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void xorps(XMMRegister dst, XMMRegister src);
13626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void sqrtsd(XMMRegister dst, XMMRegister src);
1363402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1364402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void ucomisd(XMMRegister dst, XMMRegister src);
13658defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void ucomisd(XMMRegister dst, const Operand& src);
1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  enum RoundingMode {
1368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    kRoundToNearest = 0x0,
1369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    kRoundDown      = 0x1,
1370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    kRoundUp        = 0x2,
1371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    kRoundToZero    = 0x3
1372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  };
1373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode);
1375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
13761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void movmskpd(Register dst, XMMRegister src);
13771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
13786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // The first argument is the reg field, the second argument is the r/m field.
1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_sse_operand(XMMRegister dst, XMMRegister src);
1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_sse_operand(XMMRegister reg, const Operand& adr);
1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_sse_operand(XMMRegister dst, Register src);
13826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void emit_sse_operand(Register dst, XMMRegister src);
1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Debugging
1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Print();
1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the code size generated from label to here.
13883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int SizeOfCodeGeneratedSince(Label* label) {
13893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return pc_offset() - label->pos();
13903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Mark address of the ExitJSFrame code.
1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void RecordJSReturn();
1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Mark address of a debug break slot.
13967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  void RecordDebugBreakSlot();
13977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Record a comment relocation entry that can be used by a disassembler.
1399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Use --code-comments to enable.
1400e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void RecordComment(const char* msg, bool force = false);
1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Writes a single word of data in the code stream.
1403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Used for inline tables, e.g., jump-tables.
1404b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void db(uint8_t data);
1405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void dd(uint32_t data);
1406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
14070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int pc_offset() const { return static_cast<int>(pc_ - buffer_); }
14083e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
14093e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  PositionsRecorder* positions_recorder() { return &positions_recorder_; }
1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if there is less than kGap bytes available in the buffer.
1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If this is the case, we need to grow the buffer before emitting
1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // an instruction or relocation information.
1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline bool buffer_overflow() const {
1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return pc_ >= reloc_info_writer.pos() - kGap;
1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the number of bytes available in the buffer.
1419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  inline int available_space() const {
1420d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return static_cast<int>(reloc_info_writer.pos() - pc_);
1421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static bool IsNop(Address addr);
14247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Avoid overflows for displacements etc.
1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kMaximalBufferSize = 512*MB;
1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kMinimalBufferSize = 4*KB;
1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  byte byte_at(int pos)  { return buffer_[pos]; }
14303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
14313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
143244f0eee88ff00398ff7f715fab053374d808c90dSteve Block protected:
143344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool emit_debug_code() const { return emit_debug_code_; }
143444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* addr_at(int pos)  { return buffer_ + pos; }
1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint32_t long_at(int pos)  {
1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return *reinterpret_cast<uint32_t*>(addr_at(pos));
1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void long_at_put(int pos, uint32_t x)  {
1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // code emission
1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void GrowBuffer();
1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit(byte x) { *pc_++ = x; }
1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emitl(uint32_t x);
1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emitq(uint64_t x, RelocInfo::Mode rmode);
1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emitw(uint16_t x);
1451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  inline void emit_code_target(Handle<Code> target,
1452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               RelocInfo::Mode rmode,
1453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               unsigned ast_id = kNoASTId);
1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit(Immediate x) { emitl(x.value_); }
1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emits a REX prefix that encodes a 64-bit operand size and
1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the top bit of both register codes.
1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W is set.
1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_64(XMMRegister reg, Register rm_reg);
14616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  inline void emit_rex_64(Register reg, XMMRegister rm_reg);
14626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  inline void emit_rex_64(Register reg, Register rm_reg);
1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emits a REX prefix that encodes a 64-bit operand size and
1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the top bit of the destination, index, and base register codes.
1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The high bit of reg is used for REX.R, the high bit of op's base
1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // register is used for REX.B, and the high bit of op's index register
1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is used for REX.X.  REX.W is set.
1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_64(Register reg, const Operand& op);
1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_64(XMMRegister reg, const Operand& op);
1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emits a REX prefix that encodes a 64-bit operand size and
1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the top bit of the register code.
1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The high bit of register is used for REX.B.
1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W is set and REX.R and REX.X are clear.
1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_64(Register rm_reg);
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emits a REX prefix that encodes a 64-bit operand size and
1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the top bit of the index and base register codes.
1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The high bit of op's base register is used for REX.B, and the high
1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bit of op's index register is used for REX.X.
1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W is set and REX.R clear.
1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_64(const Operand& op);
1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit a REX prefix that only sets REX.W to choose a 64-bit operand size.
1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_rex_64() { emit(0x48); }
1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W is clear.
1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_32(Register reg, Register rm_reg);
1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The high bit of reg is used for REX.R, the high bit of op's base
1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // register is used for REX.B, and the high bit of op's index register
1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is used for REX.X.  REX.W is cleared.
1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_32(Register reg, const Operand& op);
1496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // High bit of rm_reg goes to REX.B.
1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W, REX.R and REX.X are clear.
1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_32(Register rm_reg);
1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // High bit of base goes to REX.B and high bit of index to REX.X.
1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W and REX.R are clear.
1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_rex_32(const Operand& op);
1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // REX.W is cleared.  If no REX bits are set, no byte is emitted.
1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(Register reg, Register rm_reg);
1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The high bit of reg is used for REX.R, the high bit of op's base
1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // register is used for REX.B, and the high bit of op's index register
1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is used for REX.X.  REX.W is cleared.  If no REX bits are set, nothing
1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is emitted.
1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(Register reg, const Operand& op);
1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // As for emit_optional_rex_32(Register, Register), except that
1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the registers are XMM registers.
1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(XMMRegister reg, XMMRegister base);
1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // As for emit_optional_rex_32(Register, Register), except that
15206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // one of the registers is an XMM registers.
1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(XMMRegister reg, Register base);
1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // As for emit_optional_rex_32(Register, Register), except that
15246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // one of the registers is an XMM registers.
15256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  inline void emit_optional_rex_32(Register reg, XMMRegister base);
15266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // As for emit_optional_rex_32(Register, const Operand&), except that
1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the register is an XMM register.
1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(XMMRegister reg, const Operand& op);
1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Optionally do as emit_rex_32(Register) if the register number has
1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the high bit set.
1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(Register rm_reg);
1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Optionally do as emit_rex_32(const Operand&) if the operand register
1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // numbers have a high bit set.
1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_optional_rex_32(const Operand& op);
1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit the ModR/M byte, and optionally the SIB byte and
1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 1- or 4-byte offset for a memory operand.  Also encodes
1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the second operand of the operation, a register or operation
1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // subcode, into the reg field of the ModR/M byte.
1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_operand(Register reg, const Operand& adr) {
1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    emit_operand(reg.low_bits(), adr);
1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit the ModR/M byte, and optionally the SIB byte and
1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 1- or 4-byte offset for a memory operand.  Also used to encode
1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // a three-bit opcode extension into the ModR/M byte.
1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_operand(int rm, const Operand& adr);
1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit a ModR/M byte with registers coded in the reg and rm_reg fields.
1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_modrm(Register reg, Register rm_reg) {
1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    emit(0xC0 | reg.low_bits() << 3 | rm_reg.low_bits());
1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit a ModR/M byte with an operation subcode in the reg field and
1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // a register in the rm_reg field.
1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_modrm(int code, Register rm_reg) {
1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(is_uint3(code));
1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    emit(0xC0 | code << 3 | rm_reg.low_bits());
1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit the code-object-relative offset of the label's position
1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_code_relative_offset(Label* label);
1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit machine code for one of the operations ADD, ADC, SUB, SBC,
1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // AND, OR, XOR, or CMP.  The encodings of these operations are all
1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // similar, differing just in the opcode or in the reg field of the
1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ModR/M byte.
1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void arithmetic_op_16(byte opcode, Register reg, Register rm_reg);
1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg);
1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void arithmetic_op_32(byte opcode, Register reg, Register rm_reg);
1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void arithmetic_op_32(byte opcode, Register reg, const Operand& rm_reg);
1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void arithmetic_op(byte opcode, Register reg, Register rm_reg);
1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void arithmetic_op(byte opcode, Register reg, const Operand& rm_reg);
1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void immediate_arithmetic_op(byte subcode, Register dst, Immediate src);
1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void immediate_arithmetic_op(byte subcode, const Operand& dst, Immediate src);
1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Operate on a byte in memory or register.
1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void immediate_arithmetic_op_8(byte subcode,
1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register dst,
1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Immediate src);
1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void immediate_arithmetic_op_8(byte subcode,
1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 const Operand& dst,
1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Immediate src);
1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Operate on a word in memory or register.
1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void immediate_arithmetic_op_16(byte subcode,
1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Register dst,
1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Immediate src);
1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void immediate_arithmetic_op_16(byte subcode,
1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  const Operand& dst,
1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Immediate src);
1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Operate on a 32-bit word in memory or register.
1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void immediate_arithmetic_op_32(byte subcode,
1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Register dst,
1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Immediate src);
1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void immediate_arithmetic_op_32(byte subcode,
1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  const Operand& dst,
1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Immediate src);
1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit machine code for a shift operation.
1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shift(Register dst, Immediate shift_amount, int subcode);
1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shift_32(Register dst, Immediate shift_amount, int subcode);
1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shift dst by cl % 64 bits.
1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shift(Register dst, int subcode);
1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shift_32(Register dst, int subcode);
1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_farith(int b1, int b2, int i);
1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // labels
1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // void print(Label* L);
1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void bind_to(Label* L, int pos);
1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // record reloc info for current pc_
1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class CodePatcher;
1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class EnsureSpace;
1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class RegExpMacroAssemblerX64;
1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Code buffer:
1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The buffer into which code and relocation info are generated.
1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* buffer_;
1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int buffer_size_;
1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // True if the assembler owns the buffer, false if buffer is external.
1627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool own_buffer_;
1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // code generation
1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* pc_;  // the program counter; moves forward
1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RelocInfoWriter reloc_info_writer;
1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  List< Handle<Code> > code_targets_;
1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16353e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  PositionsRecorder positions_recorder_;
163644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
163744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool emit_debug_code_;
163844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
16393e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  friend class PositionsRecorder;
1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper class that ensures that there is enough space for generating
1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// instructions and relocation information.  The constructor makes
1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// sure that there is enough space and (in debug mode) the destructor
1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// checks that we did not generate too much.
1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass EnsureSpace BASE_EMBEDDED {
1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (assembler_->buffer_overflow()) assembler_->GrowBuffer();
1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    space_before_ = assembler_->available_space();
1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ~EnsureSpace() {
1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int bytes_generated = space_before_ - assembler_->available_space();
1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(bytes_generated < assembler_->kGap);
1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Assembler* assembler_;
1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int space_before_;
1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_X64_ASSEMBLER_X64_H_
1673