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.
331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Copyright 2011 the V8 project authors. All rights reserved.
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A light-weight IA32 Assembler.
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_IA32_ASSEMBLER_IA32_H_
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_IA32_ASSEMBLER_IA32_H_
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4044f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "isolate.h"
41d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "serialize.h"
42d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CPU Registers.
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 1) We would prefer to use an enum, but enum values are assignment-
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// compatible with int, which has caused code-generation bugs.
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 2) We would prefer to use a class instead of a struct but we don't like
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the register initialization to depend on the particular initialization
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// order (which appears to be different on OS X, Linux, and Windows for the
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// installed versions of C++ we tried). Using a struct permits C-style
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "initialization". Also, the Register objects cannot be const as this
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// forces initialization stubs in MSVC, making us dependent on initialization
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// order.
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 3) By not using an enum, we are possibly preventing the compiler from
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// doing certain constant folds, which may significantly reduce the
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// code generated for some assembly instructions (because they boil down
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to a few constants). If this is a problem, we could change the code
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// such that we use an enum in optimized mode, and the struct in debug
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// mode. This way we get the compile-time error checking in debug mode
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and best performance in optimized code.
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct Register {
681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const int kNumAllocatableRegisters = 6;
69b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const int kNumRegisters = 8;
70b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static inline const char* AllocationIndexToString(int index);
72b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static inline int ToAllocationIndex(Register reg);
74b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static inline Register FromAllocationIndex(int index);
76b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
77b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static Register from_code(int code) {
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(code >= 0);
793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(code < kNumRegisters);
80b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Register r = { code };
81b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return r;
82b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
83b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  bool is(Register reg) const { return code_ == reg.code_; }
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // eax, ebx, ecx and edx are byte registers, the rest are not.
860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  bool is_byte_register() const { return code_ <= 3; }
870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int code() const {
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(is_valid());
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return code_;
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int bit() const {
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(is_valid());
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 1 << code_;
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Unfortunately we can't make this private in a struct.
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int code_;
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_eax_Code = 0;
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_ecx_Code = 1;
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_edx_Code = 2;
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_ebx_Code = 3;
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_esp_Code = 4;
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_ebp_Code = 5;
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_esi_Code = 6;
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_edi_Code = 7;
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_no_reg_Code = -1;
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register eax = { kRegister_eax_Code };
1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register ecx = { kRegister_ecx_Code };
1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register edx = { kRegister_edx_Code };
1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register ebx = { kRegister_ebx_Code };
1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register esp = { kRegister_esp_Code };
1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register ebp = { kRegister_ebp_Code };
1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register esi = { kRegister_esi_Code };
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register edi = { kRegister_edi_Code };
1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register no_reg = { kRegister_no_reg_Code };
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockinline const char* Register::AllocationIndexToString(int index) {
1221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(index >= 0 && index < kNumAllocatableRegisters);
1231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // This is the mapping of allocation indices to registers.
1241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  const char* const kNames[] = { "eax", "ecx", "edx", "ebx", "esi", "edi" };
1251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return kNames[index];
1261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
1271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockinline int Register::ToAllocationIndex(Register reg) {
1301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(reg.is_valid() && !reg.is(esp) && !reg.is(ebp));
1311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (reg.code() >= 6) ? reg.code() - 2 : reg.code();
1321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
1331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockinline Register Register::FromAllocationIndex(int index)  {
1361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(index >= 0 && index < kNumAllocatableRegisters);
1371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (index >= 4) ? from_code(index + 2) : from_code(index);
1381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
1391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct XMMRegister {
142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const int kNumAllocatableRegisters = 7;
143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const int kNumRegisters = 8;
144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static int ToAllocationIndex(XMMRegister reg) {
146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(reg.code() != 0);
147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return reg.code() - 1;
148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static XMMRegister FromAllocationIndex(int index) {
151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return from_code(index + 1);
153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const char* AllocationIndexToString(int index) {
156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    const char* const names[] = {
158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm1",
159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm2",
160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm3",
161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm4",
162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm5",
163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm6",
164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "xmm7"
165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    };
166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return names[index];
167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static XMMRegister from_code(int code) {
170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    XMMRegister r = { code };
171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return r;
172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool is(XMMRegister reg) const { return code_ == reg.code_; }
1760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int code() const {
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(is_valid());
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return code_;
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int code_;
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm0 = { 0 };
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm1 = { 1 };
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm2 = { 2 };
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm3 = { 3 };
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm4 = { 4 };
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm5 = { 5 };
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm6 = { 6 };
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm7 = { 7 };
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochtypedef XMMRegister DoubleRegister;
196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum Condition {
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // any value < 0 is considered no_condition
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  no_condition  = -1,
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  overflow      =  0,
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  no_overflow   =  1,
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  below         =  2,
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  above_equal   =  3,
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  equal         =  4,
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  not_equal     =  5,
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  below_equal   =  6,
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  above         =  7,
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  negative      =  8,
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  positive      =  9,
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  parity_even   = 10,
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  parity_odd    = 11,
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  less          = 12,
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  greater_equal = 13,
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  less_equal    = 14,
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  greater       = 15,
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // aliases
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  carry         = below,
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  not_carry     = above_equal,
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  zero          = equal,
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  not_zero      = not_equal,
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  sign          = negative,
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  not_sign      = positive
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns the equivalent of !cc.
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Negation of the default no_condition (-1) results in a non-default
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// no_condition value (-2). As long as tests for no_condition check
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// for condition < 0, this will work as expected.
2339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monseninline Condition NegateCondition(Condition cc) {
2349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  return static_cast<Condition>(cc ^ 1);
2359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
2369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Corresponds to transposing the operands of a comparison.
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline Condition ReverseCondition(Condition cc) {
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (cc) {
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case below:
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return above;
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case above:
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return below;
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case above_equal:
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return below_equal;
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case below_equal:
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return above_equal;
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case less:
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return greater;
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case greater:
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return less;
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case greater_equal:
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return less_equal;
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case less_equal:
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return greater_equal;
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return cc;
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Machine instruction Immediates
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Immediate BASE_EMBEDDED {
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline explicit Immediate(int x);
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline explicit Immediate(const ExternalReference& ext);
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline explicit Immediate(Handle<Object> handle);
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline explicit Immediate(Smi* value);
272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  inline explicit Immediate(Address addr);
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static Immediate CodeRelativeOffset(Label* label) {
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return Immediate(label);
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_zero() const { return x_ == 0 && rmode_ == RelocInfo::NONE; }
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_int8() const {
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return -128 <= x_ && x_ < 128 && rmode_ == RelocInfo::NONE;
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_int16() const {
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return -32768 <= x_ && x_ < 32768 && rmode_ == RelocInfo::NONE;
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline explicit Immediate(Label* value);
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int x_;
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RelocInfo::Mode rmode_;
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class Assembler;
293053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  friend class MacroAssembler;
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Machine instruction Operands
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum ScaleFactor {
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_1 = 0,
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_2 = 1,
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_4 = 2,
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  times_8 = 3,
3054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  times_int_size = times_4,
3064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  times_half_pointer_size = times_2,
307402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  times_pointer_size = times_4,
308402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  times_twice_pointer_size = times_8
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Operand BASE_EMBEDDED {
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
3146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // XMM reg
3156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  INLINE(explicit Operand(XMMRegister xmm_reg));
3166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // [disp/r]
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  INLINE(explicit Operand(int32_t disp, RelocInfo::Mode rmode));
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // disp only must always be relocated
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // [base + disp/r]
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit Operand(Register base, int32_t disp,
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   RelocInfo::Mode rmode = RelocInfo::NONE);
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // [base + index*scale + disp/r]
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit Operand(Register base,
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   Register index,
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   ScaleFactor scale,
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   int32_t disp,
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   RelocInfo::Mode rmode = RelocInfo::NONE);
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // [index*scale + disp/r]
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit Operand(Register index,
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   ScaleFactor scale,
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   int32_t disp,
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   RelocInfo::Mode rmode = RelocInfo::NONE);
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static Operand StaticVariable(const ExternalReference& ext) {
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return Operand(reinterpret_cast<int32_t>(ext.address()),
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   RelocInfo::EXTERNAL_REFERENCE);
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static Operand StaticArray(Register index,
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             ScaleFactor scale,
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             const ExternalReference& arr) {
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return Operand(index, scale, reinterpret_cast<int32_t>(arr.address()),
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   RelocInfo::EXTERNAL_REFERENCE);
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static Operand Cell(Handle<JSGlobalPropertyCell> cell) {
351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return Operand(reinterpret_cast<int32_t>(cell.location()),
352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                   RelocInfo::GLOBAL_PROPERTY_CELL);
353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns true if this Operand is a wrapper for the specified register.
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_reg(Register reg) const;
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Returns true if this Operand is a wrapper for one register.
3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool is_reg_only() const;
3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Asserts that this Operand is a wrapper for one register and returns the
3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // register.
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg() const;
3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // reg
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  INLINE(explicit Operand(Register reg));
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the ModRM byte without an encoded 'reg' register. The
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // register is encoded later as part of the emit_operand operation.
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void set_modrm(int mod, Register rm);
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void set_sib(ScaleFactor scale, Register index, Register base);
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void set_disp8(int8_t disp);
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void set_dispr(int32_t disp, RelocInfo::Mode rmode);
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  byte buf_[6];
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The number of bytes in buf_.
3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  unsigned int len_;
3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Only valid if len_ > 4.
3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RelocInfo::Mode rmode_;
3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class Assembler;
3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  friend class MacroAssembler;
3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  friend class LCodeGen;
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A Displacement describes the 32bit immediate field of an instruction which
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// may be used together with a Label in order to refer to a yet unknown code
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// position. Displacements stored in the instruction stream are used to describe
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the instruction and to chain a list of instructions using the same Label.
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A Displacement contains 2 different fields:
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// next field: position of next displacement in the chain (0 = end of list)
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// type field: instruction type
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A next value of null (0) indicates the end of a chain (note that there can
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// be no displacement at position zero, because there is always at least one
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// instruction byte before the displacement).
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Displacement _data field layout
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// |31.....2|1......0|
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// [  next  |  type  |
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Displacement BASE_EMBEDDED {
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  enum Type {
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UNCONDITIONAL_JUMP,
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CODE_RELATIVE,
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    OTHER
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int data() const { return data_; }
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Type type() const { return TypeField::decode(data_); }
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void next(Label* L) const {
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int n = NextField::decode(data_);
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    n > 0 ? L->link_to(n) : L->Unuse();
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void link_to(Label* L) { init(L, type()); }
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit Displacement(int data) { data_ = data; }
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Displacement(Label* L, Type type) { init(L, type); }
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void print() {
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("%s (%x) ", (type() == UNCONDITIONAL_JUMP ? "jmp" : "[other]"),
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       NextField::decode(data_));
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int data_;
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  class TypeField: public BitField<Type, 0, 2> {};
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  class NextField: public BitField<int,  2, 32-2> {};
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void init(Label* L, Type type);
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CpuFeatures keeps track of which features are supported by the target CPU.
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Supported features must be enabled by a Scope before use.
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Example:
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   if (CpuFeatures::IsSupported(SSE2)) {
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     CpuFeatures::Scope fscope(SSE2);
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     // Generate SSE2 floating point code.
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   } else {
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     // Generate standard x87 floating point code.
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   }
4538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass CpuFeatures : public AllStatic {
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
4558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Detect features of the target CPU. Set safe defaults if the serializer
4568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // is enabled (snapshots must be portable).
4578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  static void Probe();
458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check whether a feature is supported by the target CPU.
4608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  static bool IsSupported(CpuFeature f) {
4618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(initialized_);
4623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (f == SSE2 && !FLAG_enable_sse2) return false;
4633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (f == SSE3 && !FLAG_enable_sse3) return false;
464f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    if (f == SSE4_1 && !FLAG_enable_sse4_1) return false;
4653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (f == CMOV && !FLAG_enable_cmov) return false;
4663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (f == RDTSC && !FLAG_enable_rdtsc) return false;
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return (supported_ & (static_cast<uint64_t>(1) << f)) != 0;
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
4708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef DEBUG
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check whether a feature is currently enabled.
4728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  static bool IsEnabled(CpuFeature f) {
4738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(initialized_);
4748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Isolate* isolate = Isolate::UncheckedCurrent();
4758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (isolate == NULL) {
4768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      // When no isolate is available, work as if we're running in
4778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      // release mode.
4788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return IsSupported(f);
4798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
4808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    uint64_t enabled = isolate->enabled_cpu_features();
4818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return (enabled & (static_cast<uint64_t>(1) << f)) != 0;
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif
4848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enable a specified feature within a scope.
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  class Scope BASE_EMBEDDED {
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
488589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block   public:
4908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    explicit Scope(CpuFeature f) {
491d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      uint64_t mask = static_cast<uint64_t>(1) << f;
4928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      ASSERT(CpuFeatures::IsSupported(f));
49344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ASSERT(!Serializer::enabled() ||
4948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch             (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
4958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      isolate_ = Isolate::UncheckedCurrent();
4968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      old_enabled_ = 0;
4978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (isolate_ != NULL) {
4988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        old_enabled_ = isolate_->enabled_cpu_features();
4998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        isolate_->set_enabled_cpu_features(old_enabled_ | mask);
5008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
50144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
50244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ~Scope() {
5038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
5048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (isolate_ != NULL) {
5058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        isolate_->set_enabled_cpu_features(old_enabled_);
5068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
508589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block   private:
51044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Isolate* isolate_;
5118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    uint64_t old_enabled_;
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else
513589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block   public:
515d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    explicit Scope(CpuFeature f) {}
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
51844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  class TryForceFeatureScope BASE_EMBEDDED {
5208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch   public:
5218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    explicit TryForceFeatureScope(CpuFeature f)
5228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        : old_supported_(CpuFeatures::supported_) {
5238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (CanForce()) {
5248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        CpuFeatures::supported_ |= (static_cast<uint64_t>(1) << f);
5258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
5268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
52744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ~TryForceFeatureScope() {
5298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (CanForce()) {
5308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        CpuFeatures::supported_ = old_supported_;
5318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
5328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
53344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch   private:
5358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    static bool CanForce() {
5368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      // It's only safe to temporarily force support of CPU features
5378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      // when there's only a single isolate, which is guaranteed when
5388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      // the serializer is enabled.
5398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return Serializer::enabled();
5408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
5418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
5428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    const uint64_t old_supported_;
5438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  };
5448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
5458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch private:
5468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef DEBUG
5478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  static bool initialized_;
5488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif
5498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  static uint64_t supported_;
5508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  static uint64_t found_by_runtime_probing_;
55144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
55244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
55644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass Assembler : public AssemblerBase {
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We check before assembling an instruction that there is sufficient
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // space to write an instruction and its relocation information.
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The relocation writer's position must be kGap bytes above the end of
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the generated instructions. This leaves enough space for the
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // longest possible ia32 instruction, 15 bytes, and the longest possible
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // (There is a 15 byte limit on ia32 instruction length that rules out some
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // otherwise valid instructions.)
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This allows for a single, fast space check per instruction.
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kGap = 32;
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create an assembler. Instructions and relocation information are emitted
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // into a buffer, with the instructions starting from the beginning and the
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // relocation information starting from the end of the buffer. See CodeDesc
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // for a detailed comment on the layout (globals.h).
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the provided buffer is NULL, the assembler allocates and grows its own
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // buffer, and buffer_size determines the initial buffer size. The buffer is
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // owned by the assembler and deallocated upon destruction of the assembler.
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the provided buffer is not NULL, the assembler uses the provided buffer
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // for code generation and assumes its size to be buffer_size. If the buffer
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is too small, a fatal error occurs. No deallocation of the buffer is done
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // upon destruction of the assembler.
5838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // TODO(vitalyr): the assembler does not need an isolate.
5848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Assembler(Isolate* isolate, void* buffer, int buffer_size);
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ~Assembler();
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
58744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Overrides the default provided by FLAG_debug_code.
58844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
58944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // GetCode emits any pending (non-emitted) code and fills the descriptor
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // desc. GetCode() is idempotent; it returns the same result if no other
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Assembler functions are invoked in between GetCode() calls.
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void GetCode(CodeDesc* desc);
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Read/Modify the code target in the branch/call instruction at pc.
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline static Address target_address_at(Address pc);
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline static void set_target_address_at(Address pc, Address target);
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This sets the branch destination (which is in the instruction on x86).
600d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This is for calls and branches within generated code.
6013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline static void deserialization_set_special_target_at(
6023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Address instruction_payload, Address target) {
603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    set_target_address_at(instruction_payload, target);
604d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
605d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This sets the branch destination (which is in the instruction on x86).
607d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This is for calls and branches to runtime code.
608d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  inline static void set_external_target_at(Address instruction_payload,
609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                            Address target) {
610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    set_target_address_at(instruction_payload, target);
611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kSpecialTargetSize = kPointerSize;
614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Distance between the address of the code target in the call instruction
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // and the return address
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kCallTargetAddressOffset = kPointerSize;
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Distance between start of patched return sequence and the emitted address
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to jump to.
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kPatchReturnSequenceAddressOffset = 1;  // JMP imm32.
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Distance between start of patched debug break slot and the emitted address
6237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // to jump to.
6247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  static const int kPatchDebugBreakSlotAddressOffset = 1;  // JMP imm32.
6257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static const int kCallInstructionLength = 5;
627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static const int kJSReturnSequenceLength = 6;
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // The debug break slot must be able to contain a call instruction.
6307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  static const int kDebugBreakSlotLength = kCallInstructionLength;
6317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // One byte opcode for test al, 0xXX.
633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const byte kTestAlByte = 0xA8;
634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // One byte opcode for nop.
635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const byte kNopByte = 0x90;
636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // One byte opcode for a short unconditional jump.
638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const byte kJmpShortOpcode = 0xEB;
639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // One byte prefix for a short conditional jump.
640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const byte kJccShortPrefix = 0x70;
641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const byte kJncShortOpcode = kJccShortPrefix | not_carry;
642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const byte kJcShortOpcode = kJccShortPrefix | carry;
643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Code generation
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // - function names correspond one-to-one to ia32 instruction mnemonics
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // - unless specified otherwise, instructions operate on 32bit operands
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // - instructions on 8bit (byte) operands/registers have a trailing '_b'
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // - instructions on 16bit (word) operands/registers have a trailing '_w'
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // - naming conflicts with C++ keywords are resolved via a trailing '_'
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // NOTE ON INTERFACE: Currently, the interface is not very consistent
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in the sense that some operations (e.g. mov()) can be called in more
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the one way to generate the same instruction: The Register argument
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // can in some cases be replaced with an Operand(Register) argument.
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This should be cleaned up and made more orthogonal. The questions
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is: should we always use Operands instead of Registers where an
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Operand is possible, or should we have a Register (overloaded) form
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // instead? We must be careful to make sure that the selected instruction
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is obvious from the parameters to avoid hard-to-find code generation
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bugs.
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Insert the smallest number of nop instructions
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // possible to align the pc offset to a multiple
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // of m. m must be a power of 2.
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Align(int m);
6683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Nop(int bytes = 1);
6699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Aligns code to something that's optimal for a jump target for the platform.
6709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  void CodeTargetAlign();
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stack
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void pushad();
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void popad();
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void pushfd();
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void popfd();
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void push(const Immediate& x);
680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void push_imm32(int32_t imm32);
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void push(Register src);
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void push(const Operand& src);
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void pop(Register dst);
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void pop(const Operand& dst);
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void enter(const Immediate& size);
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void leave();
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Moves
6913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void mov_b(Register dst, Register src) { mov_b(dst, Operand(src)); }
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void mov_b(Register dst, const Operand& src);
6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void mov_b(Register dst, int8_t imm8) { mov_b(Operand(dst), imm8); }
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void mov_b(const Operand& dst, int8_t imm8);
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void mov_b(const Operand& dst, Register src);
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void mov_w(Register dst, const Operand& src);
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void mov_w(const Operand& dst, Register src);
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void mov(Register dst, int32_t imm32);
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void mov(Register dst, const Immediate& x);
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void mov(Register dst, Handle<Object> handle);
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void mov(Register dst, const Operand& src);
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void mov(Register dst, Register src);
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void mov(const Operand& dst, const Immediate& x);
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void mov(const Operand& dst, Handle<Object> handle);
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void mov(const Operand& dst, Register src);
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void movsx_b(Register dst, Register src) { movsx_b(dst, Operand(src)); }
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movsx_b(Register dst, const Operand& src);
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void movsx_w(Register dst, Register src) { movsx_w(dst, Operand(src)); }
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movsx_w(Register dst, const Operand& src);
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void movzx_b(Register dst, Register src) { movzx_b(dst, Operand(src)); }
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movzx_b(Register dst, const Operand& src);
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void movzx_w(Register dst, Register src) { movzx_w(dst, Operand(src)); }
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movzx_w(Register dst, const Operand& src);
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Conditional moves
7223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void cmov(Condition cc, Register dst, Register src) {
7233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    cmov(cc, dst, Operand(src));
7243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmov(Condition cc, Register dst, const Operand& src);
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Flag management.
7286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void cld();
7296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Repetitive string instructions.
731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void rep_movs();
7326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void rep_stos();
733f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  void stos();
734e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Exchange two registers
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void xchg(Register dst, Register src);
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Arithmetics
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void adc(Register dst, int32_t imm32);
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void adc(Register dst, const Operand& src);
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void add(Register dst, Register src) { add(dst, Operand(src)); }
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void add(Register dst, const Operand& src);
7443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void add(const Operand& dst, Register src);
7453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void add(Register dst, const Immediate& imm) { add(Operand(dst), imm); }
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void add(const Operand& dst, const Immediate& x);
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void and_(Register dst, int32_t imm32);
74959151504615d929945dc59db37bf1166937748c6Steve Block  void and_(Register dst, const Immediate& x);
7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void and_(Register dst, Register src) { and_(dst, Operand(src)); }
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void and_(Register dst, const Operand& src);
7523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void and_(const Operand& dst, Register src);
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void and_(const Operand& dst, const Immediate& x);
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void cmpb(Register reg, int8_t imm8) { cmpb(Operand(reg), imm8); }
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpb(const Operand& op, int8_t imm8);
7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void cmpb(Register reg, const Operand& op);
7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void cmpb(const Operand& op, Register reg);
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpb_al(const Operand& op);
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpw_ax(const Operand& op);
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmpw(const Operand& op, Immediate imm16);
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmp(Register reg, int32_t imm32);
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmp(Register reg, Handle<Object> handle);
7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void cmp(Register reg0, Register reg1) { cmp(reg0, Operand(reg1)); }
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmp(Register reg, const Operand& op);
7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void cmp(Register reg, const Immediate& imm) { cmp(Operand(reg), imm); }
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmp(const Operand& op, const Immediate& imm);
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cmp(const Operand& op, Handle<Object> handle);
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void dec_b(Register dst);
7710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  void dec_b(const Operand& dst);
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void dec(Register dst);
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void dec(const Operand& dst);
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cdq();
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void idiv(Register src);
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Signed multiply instructions.
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void imul(Register src);                               // edx:eax = eax * src.
7823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void imul(Register dst, Register src) { imul(dst, Operand(src)); }
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void imul(Register dst, const Operand& src);           // dst = dst * src.
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void imul(Register dst, Register src, int32_t imm32);  // dst = src * imm32.
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void inc(Register dst);
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void inc(const Operand& dst);
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void lea(Register dst, const Operand& src);
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Unsigned multiply instruction.
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void mul(Register src);                                // edx:eax = eax * reg.
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void neg(Register dst);
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void not_(Register dst);
797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void or_(Register dst, int32_t imm32);
7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void or_(Register dst, Register src) { or_(dst, Operand(src)); }
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void or_(Register dst, const Operand& src);
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void or_(const Operand& dst, Register src);
8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void or_(Register dst, const Immediate& imm) { or_(Operand(dst), imm); }
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void or_(const Operand& dst, const Immediate& x);
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void rcl(Register dst, uint8_t imm8);
806756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void rcr(Register dst, uint8_t imm8);
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void sar(Register dst, uint8_t imm8);
809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void sar_cl(Register dst);
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void sbb(Register dst, const Operand& src);
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void shld(Register dst, Register src) { shld(dst, Operand(src)); }
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shld(Register dst, const Operand& src);
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shl(Register dst, uint8_t imm8);
817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void shl_cl(Register dst);
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void shrd(Register dst, Register src) { shrd(dst, Operand(src)); }
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shrd(Register dst, const Operand& src);
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shr(Register dst, uint8_t imm8);
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void shr_cl(Register dst);
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void sub(Register dst, const Immediate& imm) { sub(Operand(dst), imm); }
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void sub(const Operand& dst, const Immediate& x);
8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void sub(Register dst, Register src) { sub(dst, Operand(src)); }
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void sub(Register dst, const Operand& src);
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void sub(const Operand& dst, Register src);
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void test(Register reg, const Immediate& imm);
8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void test(Register reg0, Register reg1) { test(reg0, Operand(reg1)); }
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void test(Register reg, const Operand& op);
834e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void test_b(Register reg, const Operand& op);
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void test(const Operand& op, const Immediate& imm);
8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void test_b(Register reg, uint8_t imm8) { test_b(Operand(reg), imm8); }
8377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  void test_b(const Operand& op, uint8_t imm8);
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void xor_(Register dst, int32_t imm32);
8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void xor_(Register dst, Register src) { xor_(dst, Operand(src)); }
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void xor_(Register dst, const Operand& src);
8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void xor_(const Operand& dst, Register src);
8433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void xor_(Register dst, const Immediate& imm) { xor_(Operand(dst), imm); }
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void xor_(const Operand& dst, const Immediate& x);
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Bit operations.
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void bt(const Operand& dst, Register src);
8483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void bts(Register dst, Register src) { bts(Operand(dst), src); }
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void bts(const Operand& dst, Register src);
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Miscellaneous
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void hlt();
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void int3();
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void nop();
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void rdtsc();
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void ret(int imm16);
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Label operations & relative jumps (PPUM Appendix D)
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Takes a branch opcode (cc) and a label (L) and generates
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // either a backward branch or a forward branch and links it
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to the label fixup chain. Usage:
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Label L;    // unbound label
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // j(cc, &L);  // forward branch to unbound label
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bind(&L);   // bind label to the current pc
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // j(cc, &L);  // backward branch to bound label
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bind(&L);   // illegal: a label may be bound only once
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Note: The same Label can be used for forward and backward branches
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // but it may be bound only once.
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void bind(Label* L);  // binds an unbound label L to the current code position
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calls
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void call(Label* L);
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void call(byte* entry, RelocInfo::Mode rmode);
878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int CallSize(const Operand& adr);
8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void call(Register reg) { call(Operand(reg)); }
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void call(const Operand& adr);
881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int CallSize(Handle<Code> code, RelocInfo::Mode mode);
882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void call(Handle<Code> code,
8833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            unsigned ast_id = kNoASTId);
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jumps
887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // unconditional jump to L
888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void jmp(Label* L, Label::Distance distance = Label::kFar);
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void jmp(byte* entry, RelocInfo::Mode rmode);
8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void jmp(Register reg) { jmp(Operand(reg)); }
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void jmp(const Operand& adr);
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void jmp(Handle<Code> code, RelocInfo::Mode rmode);
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Conditional jumps
895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void j(Condition cc,
896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         Label* L,
897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         Label::Distance distance = Label::kFar);
898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void j(Condition cc, byte* entry, RelocInfo::Mode rmode);
899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void j(Condition cc, Handle<Code> code);
9000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Floating-point operations
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fld(int i);
903402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void fstp(int i);
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fld1();
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fldz();
907402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void fldpi();
908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void fldln2();
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fld_s(const Operand& adr);
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fld_d(const Operand& adr);
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fstp_s(const Operand& adr);
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fstp_d(const Operand& adr);
915402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void fst_d(const Operand& adr);
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fild_s(const Operand& adr);
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fild_d(const Operand& adr);
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fist_s(const Operand& adr);
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fistp_s(const Operand& adr);
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fistp_d(const Operand& adr);
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // The fisttp instructions require SSE3.
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fisttp_s(const Operand& adr);
927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void fisttp_d(const Operand& adr);
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fabs();
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fchs();
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fcos();
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fsin();
9333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void fptan();
934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void fyl2x();
9353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void f2xm1();
9363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void fscale();
9373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void fninit();
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fadd(int i);
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fsub(int i);
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fmul(int i);
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fdiv(int i);
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fisub_s(const Operand& adr);
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void faddp(int i = 1);
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fsubp(int i = 1);
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fsubrp(int i = 1);
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fmulp(int i = 1);
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fdivp(int i = 1);
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fprem();
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fprem1();
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fxch(int i = 1);
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fincstp();
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void ffree(int i = 0);
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void ftst();
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fucomp(int i);
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fucompp();
9613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void fucomi(int i);
9623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void fucomip();
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fcompp();
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fnstsw_ax();
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fwait();
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void fnclex();
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void frndint();
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void sahf();
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void setcc(Condition cc, Register reg);
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cpuid();
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // SSE2 instructions
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cvttss2si(Register dst, const Operand& src);
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cvttsd2si(Register dst, const Operand& src);
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void cvtsi2sd(XMMRegister dst, Register src) { cvtsi2sd(dst, Operand(src)); }
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void cvtsi2sd(XMMRegister dst, const Operand& src);
9816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void cvtss2sd(XMMRegister dst, XMMRegister src);
98244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void cvtsd2ss(XMMRegister dst, XMMRegister src);
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void addsd(XMMRegister dst, XMMRegister src);
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void subsd(XMMRegister dst, XMMRegister src);
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void mulsd(XMMRegister dst, XMMRegister src);
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void divsd(XMMRegister dst, XMMRegister src);
988e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void xorpd(XMMRegister dst, XMMRegister src);
989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void xorps(XMMRegister dst, XMMRegister src);
9906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void sqrtsd(XMMRegister dst, XMMRegister src);
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  void andpd(XMMRegister dst, XMMRegister src);
9930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
9946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void ucomisd(XMMRegister dst, XMMRegister src);
9953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void ucomisd(XMMRegister dst, const Operand& src);
99669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
99769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  enum RoundingMode {
99869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    kRoundToNearest = 0x0,
99969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    kRoundDown      = 0x1,
100069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    kRoundUp        = 0x2,
100169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    kRoundToZero    = 0x3
100269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  };
100369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
100469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode);
100569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
10066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void movmskpd(Register dst, XMMRegister src);
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  void cmpltsd(XMMRegister dst, XMMRegister src);
10090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
10100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  void movaps(XMMRegister dst, XMMRegister src);
10110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
1012e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void movdqa(XMMRegister dst, const Operand& src);
1013e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void movdqa(const Operand& dst, XMMRegister src);
1014e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void movdqu(XMMRegister dst, const Operand& src);
1015e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void movdqu(const Operand& dst, XMMRegister src);
1016e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use either movsd or movlpd.
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movdbl(XMMRegister dst, const Operand& src);
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movdbl(const Operand& dst, XMMRegister src);
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void movd(XMMRegister dst, Register src) { movd(dst, Operand(src)); }
10226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void movd(XMMRegister dst, const Operand& src);
10233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void movd(Register dst, XMMRegister src) { movd(Operand(dst), src); }
10243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void movd(const Operand& dst, XMMRegister src);
10256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void movsd(XMMRegister dst, XMMRegister src);
10266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
102744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void movss(XMMRegister dst, const Operand& src);
10283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void movss(const Operand& dst, XMMRegister src);
102944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void movss(XMMRegister dst, XMMRegister src);
10303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void extractps(Register dst, XMMRegister src, byte imm8);
103144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void pand(XMMRegister dst, XMMRegister src);
10336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void pxor(XMMRegister dst, XMMRegister src);
1034b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void por(XMMRegister dst, XMMRegister src);
10356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void ptest(XMMRegister dst, XMMRegister src);
10366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void psllq(XMMRegister reg, int8_t shift);
1038b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void psllq(XMMRegister dst, XMMRegister src);
1039b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void psrlq(XMMRegister reg, int8_t shift);
1040b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void psrlq(XMMRegister dst, XMMRegister src);
1041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void pshufd(XMMRegister dst, XMMRegister src, int8_t shuffle);
10423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void pextrd(Register dst, XMMRegister src, int8_t offset) {
10433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    pextrd(Operand(dst), src, offset);
10443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void pextrd(const Operand& dst, XMMRegister src, int8_t offset);
10463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void pinsrd(XMMRegister dst, Register src, int8_t offset) {
10473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    pinsrd(dst, Operand(src), offset);
10483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
10491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void pinsrd(XMMRegister dst, const Operand& src, int8_t offset);
10500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
10517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Parallel XMM operations.
10523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void movntdqa(XMMRegister dst, const Operand& src);
10537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  void movntdq(const Operand& dst, XMMRegister src);
10547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Prefetch src position into cache level.
10557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Level 1, 2 or 3 specifies CPU cache level. Level 0 specifies a
10567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // non-temporal
10577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  void prefetch(const Operand& src, int level);
10587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // TODO(lrn): Need SFENCE for movnt?
10597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Debugging
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Print();
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the code size generated from label to here.
10643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int SizeOfCodeGeneratedSince(Label* label) {
10653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return pc_offset() - label->pos();
10663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Mark address of the ExitJSFrame code.
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void RecordJSReturn();
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Mark address of a debug break slot.
10727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  void RecordDebugBreakSlot();
10737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Record a comment relocation entry that can be used by a disassembler.
1075e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Use --code-comments to enable, or provide "force = true" flag to always
1076e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // write a comment.
1077e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void RecordComment(const char* msg, bool force = false);
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Writes a single byte or word of data in the code stream.  Used for
1080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // inline tables, e.g., jump-tables.
1081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void db(uint8_t data);
1082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void dd(uint32_t data);
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int pc_offset() const { return pc_ - buffer_; }
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if there is less than kGap bytes available in the buffer.
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If this is the case, we need to grow the buffer before emitting
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // an instruction or relocation information.
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; }
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the number of bytes available in the buffer.
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline int available_space() const { return reloc_info_writer.pos() - pc_; }
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static bool IsNop(Address addr);
10957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
10963e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  PositionsRecorder* positions_recorder() { return &positions_recorder_; }
10973e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
1098e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int relocation_writer_size() {
1099e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return (buffer_ + buffer_size_) - reloc_info_writer.pos();
1100e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Avoid overflows for displacements etc.
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kMaximalBufferSize = 512*MB;
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kMinimalBufferSize = 4*KB;
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  byte byte_at(int pos)  { return buffer_[pos]; }
11073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
11083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block protected:
111044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool emit_debug_code() const { return emit_debug_code_; }
111144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movsd(XMMRegister dst, const Operand& src);
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void movsd(const Operand& dst, XMMRegister src);
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_sse_operand(XMMRegister reg, const Operand& adr);
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_sse_operand(XMMRegister dst, XMMRegister src);
11176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void emit_sse_operand(Register dst, XMMRegister src);
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
111944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  byte* addr_at(int pos) { return buffer_ + pos; }
112044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
11213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint32_t long_at(int pos)  {
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return *reinterpret_cast<uint32_t*>(addr_at(pos));
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void long_at_put(int pos, uint32_t x)  {
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // code emission
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void GrowBuffer();
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit(uint32_t x);
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit(Handle<Object> handle);
1134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  inline void emit(uint32_t x,
1135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                   RelocInfo::Mode rmode,
1136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                   unsigned ast_id = kNoASTId);
1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit(const Immediate& x);
1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_w(const Immediate& x);
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit the code-object-relative offset of the label's position
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_code_relative_offset(Label* label);
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // instruction generation
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_arith_b(int op1, int op2, Register dst, int imm8);
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81)
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // with a given destination expression and an immediate operand.  It attempts
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to use the shortest encoding possible.
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sel specifies the /n in the modrm byte (see the Intel PRM).
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_arith(int sel, Operand dst, const Immediate& x);
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_operand(Register reg, const Operand& adr);
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void emit_farith(int b1, int b2, int i);
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // labels
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void print(Label* L);
1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void bind_to(Label* L, int pos);
1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // displacements
1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline Displacement disp_at(Label* L);
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void disp_at_put(Label* L, Displacement disp);
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void emit_disp(Label* L, Displacement::Type type);
1164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  inline void emit_near_disp(Label* L);
1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // record reloc info for current pc_
1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class CodePatcher;
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class EnsureSpace;
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Code buffer:
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The buffer into which code and relocation info are generated.
1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* buffer_;
1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int buffer_size_;
1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // True if the assembler owns the buffer, false if buffer is external.
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool own_buffer_;
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // code generation
1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* pc_;  // the program counter; moves forward
1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RelocInfoWriter reloc_info_writer;
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11833e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  PositionsRecorder positions_recorder_;
11843e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
118544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool emit_debug_code_;
118644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
11873e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  friend class PositionsRecorder;
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper class that ensures that there is enough space for generating
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// instructions and relocation information.  The constructor makes
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// sure that there is enough space and (in debug mode) the destructor
1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// checks that we did not generate too much.
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass EnsureSpace BASE_EMBEDDED {
1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (assembler_->overflow()) assembler_->GrowBuffer();
1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    space_before_ = assembler_->available_space();
1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ~EnsureSpace() {
1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int bytes_generated = space_before_ - assembler_->available_space();
1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(bytes_generated < assembler_->kGap);
1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Assembler* assembler_;
1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int space_before_;
1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_IA32_ASSEMBLER_IA32_H_
1221