19085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Copyright (c) 1994-2006 Sun Microsystems Inc.
29085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// All Rights Reserved.
39085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org//
45ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// Redistribution and use in source and binary forms, with or without
55ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// modification, are permitted provided that the following conditions are
65ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// met:
75ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//
89085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// - Redistributions of source code must retain the above copyright notice,
99085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// this list of conditions and the following disclaimer.
109085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org//
119085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// - Redistribution in binary form must reproduce the above copyright
129085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// notice, this list of conditions and the following disclaimer in the
139085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// documentation and/or other materials provided with the distribution.
149085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org//
159085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// - Neither the name of Sun Microsystems or the names of contributors may
169085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// be used to endorse or promote products derived from this software without
179085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// specific prior written permission.
189085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org//
199085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
209085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
219085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
239085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
249085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
259085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
269085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
279085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
289085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
299085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// The original source code covered by the above license above has been
329085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// modified significantly by Google Inc.
3356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// A lightweight X64 Assembler.
369085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#ifndef V8_X64_ASSEMBLER_X64_H_
389085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#define V8_X64_ASSEMBLER_X64_H_
399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
40c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org#include "serialize.h"
41c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org
4271affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace v8 {
4371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace internal {
449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
45e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org// Utility functions
46e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
47e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org// Test whether a 64-bit value is in a specific range.
481b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orginline bool is_uint32(int64_t x) {
4940b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  static const uint64_t kMaxUInt32 = V8_UINT64_C(0xffffffff);
5040b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  return static_cast<uint64_t>(x) <= kMaxUInt32;
51e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org}
52e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
531b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orginline bool is_int32(int64_t x) {
5440b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  static const int64_t kMinInt32 = -V8_INT64_C(0x80000000);
5540b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  return is_uint32(x - kMinInt32);
56b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org}
57b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org
581b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orginline bool uint_is_int32(uint64_t x) {
5940b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  static const uint64_t kMaxInt32 = V8_UINT64_C(0x7fffffff);
6040b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  return x <= kMaxInt32;
61b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org}
62b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org
631b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.orginline bool is_uint32(uint64_t x) {
6440b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  static const uint64_t kMaxUInt32 = V8_UINT64_C(0xffffffff);
6540b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  return x <= kMaxUInt32;
66e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org}
67e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// CPU Registers.
699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org//
709085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// 1) We would prefer to use an enum, but enum values are assignment-
719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// compatible with int, which has caused code-generation bugs.
729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org//
739085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// 2) We would prefer to use a class instead of a struct but we don't like
749085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// the register initialization to depend on the particular initialization
759085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// order (which appears to be different on OS X, Linux, and Windows for the
769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// installed versions of C++ we tried). Using a struct permits C-style
779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// "initialization". Also, the Register objects cannot be const as this
789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// forces initialization stubs in MSVC, making us dependent on initialization
799085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// order.
809085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org//
819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// 3) By not using an enum, we are possibly preventing the compiler from
829085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// doing certain constant folds, which may significantly reduce the
839085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// code generated for some assembly instructions (because they boil down
849085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// to a few constants). If this is a problem, we could change the code
859085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// such that we use an enum in optimized mode, and the struct in debug
869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// mode. This way we get the compile-time error checking in debug mode
879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// and best performance in optimized code.
889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org//
899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgstruct Register {
91a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // The non-allocatable registers are:
92a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  //  rsp - stack pointer
93a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  //  rbp - frame pointer
94a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  //  rsi - context register
95a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  //  r10 - fixed scratch register
96b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org  //  r12 - smi constant register
97a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  //  r13 - root register
98a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  static const int kMaxNumAllocatableRegisters = 10;
99a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  static int NumAllocatableRegisters() {
100a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    return kMaxNumAllocatableRegisters;
101a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
102a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  static const int kNumRegisters = 16;
103a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
104c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org  static int ToAllocationIndex(Register reg) {
1053a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    return kAllocationIndexByRegisterCode[reg.code()];
106c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org  }
107c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org
108c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org  static Register FromAllocationIndex(int index) {
109a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
1103a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    Register result = { kRegisterCodeByAllocationIndex[index] };
111c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    return result;
112c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org  }
113c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org
114a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  static const char* AllocationIndexToString(int index) {
115a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
116a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    const char* const names[] = {
117a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "rax",
118a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "rbx",
119c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      "rdx",
120c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      "rcx",
121a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "rdi",
122a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "r8",
123a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "r9",
124a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "r11",
125c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      "r14",
126b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org      "r15"
127a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    };
128a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    return names[index];
129a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
130a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
13184bcc559ac20fb04f806e97d28a314b20b58fd60svenpanne@chromium.org  static Register from_code(int code) {
132eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    Register r = { code };
133755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    return r;
134755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
135a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
1364a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  bool is(Register reg) const { return code_ == reg.code_; }
13756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org  // rax, rbx, rcx and rdx are byte registers, the rest are not.
13856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org  bool is_byte_register() const { return code_ <= 3; }
1394a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  int code() const {
1409085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    ASSERT(is_valid());
1419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    return code_;
1429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
1434a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  int bit() const {
144eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    return 1 << code_;
1459085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
1469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1475aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  // Return the high bit of the register code as a 0 or 1.  Used often
1485aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  // when constructing the REX prefix byte.
1495aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  int high_bit() const {
1505aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org    return code_ >> 3;
1515aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  }
1525aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  // Return the 3 low bits of the register code.  Used when encoding registers
1535aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  // in modR/M, SIB, and opcode bytes.
1545aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  int low_bits() const {
1555aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org    return code_ & 0x7;
1565aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  }
1575aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
1585c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Unfortunately we can't make this private in a struct when initializing
1595c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // by assignment.
1609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  int code_;
1610ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
162c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org private:
163a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  static const int kRegisterCodeByAllocationIndex[kMaxNumAllocatableRegisters];
1643a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  static const int kAllocationIndexByRegisterCode[kNumRegisters];
1659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
1669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1671456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_rax_Code = 0;
1681456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_rcx_Code = 1;
1691456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_rdx_Code = 2;
1701456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_rbx_Code = 3;
1711456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_rsp_Code = 4;
1721456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_rbp_Code = 5;
1731456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_rsi_Code = 6;
1741456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_rdi_Code = 7;
1751456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_r8_Code = 8;
1761456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_r9_Code = 9;
1771456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_r10_Code = 10;
1781456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_r11_Code = 11;
1791456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_r12_Code = 12;
1801456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_r13_Code = 13;
1811456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_r14_Code = 14;
1821456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_r15_Code = 15;
1831456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_no_reg_Code = -1;
1841456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
1851456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register rax = { kRegister_rax_Code };
1861456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register rcx = { kRegister_rcx_Code };
1871456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register rdx = { kRegister_rdx_Code };
1881456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register rbx = { kRegister_rbx_Code };
1891456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register rsp = { kRegister_rsp_Code };
1901456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register rbp = { kRegister_rbp_Code };
1911456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register rsi = { kRegister_rsi_Code };
1921456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register rdi = { kRegister_rdi_Code };
1931456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register r8 = { kRegister_r8_Code };
1941456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register r9 = { kRegister_r9_Code };
1951456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register r10 = { kRegister_r10_Code };
1961456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register r11 = { kRegister_r11_Code };
1971456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register r12 = { kRegister_r12_Code };
1981456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register r13 = { kRegister_r13_Code };
1991456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register r14 = { kRegister_r14_Code };
2001456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register r15 = { kRegister_r15_Code };
2011456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register no_reg = { kRegister_no_reg_Code };
2025aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
203ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org#ifdef _WIN64
204ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // Windows calling convention
2056b0169a99e75f4821ce4168e5e0d3cc8f6526a83danno@chromium.org  const Register arg_reg_1 = { kRegister_rcx_Code };
2066b0169a99e75f4821ce4168e5e0d3cc8f6526a83danno@chromium.org  const Register arg_reg_2 = { kRegister_rdx_Code };
2076b0169a99e75f4821ce4168e5e0d3cc8f6526a83danno@chromium.org  const Register arg_reg_3 = { kRegister_r8_Code };
2086b0169a99e75f4821ce4168e5e0d3cc8f6526a83danno@chromium.org  const Register arg_reg_4 = { kRegister_r9_Code };
209ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org#else
210ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // AMD64 calling convention
2116b0169a99e75f4821ce4168e5e0d3cc8f6526a83danno@chromium.org  const Register arg_reg_1 = { kRegister_rdi_Code };
2126b0169a99e75f4821ce4168e5e0d3cc8f6526a83danno@chromium.org  const Register arg_reg_2 = { kRegister_rsi_Code };
2136b0169a99e75f4821ce4168e5e0d3cc8f6526a83danno@chromium.org  const Register arg_reg_3 = { kRegister_rdx_Code };
2146b0169a99e75f4821ce4168e5e0d3cc8f6526a83danno@chromium.org  const Register arg_reg_4 = { kRegister_rcx_Code };
215ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org#endif  // _WIN64
2165aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
2179085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgstruct XMMRegister {
21894b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  static const int kMaxNumRegisters = 16;
219a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  static const int kMaxNumAllocatableRegisters = 15;
220a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  static int NumAllocatableRegisters() {
221a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    return kMaxNumAllocatableRegisters;
222a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
223a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
224a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  static int ToAllocationIndex(XMMRegister reg) {
225a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    ASSERT(reg.code() != 0);
226a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    return reg.code() - 1;
227a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
228a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
229c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org  static XMMRegister FromAllocationIndex(int index) {
230a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    ASSERT(0 <= index && index < kMaxNumAllocatableRegisters);
231c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    XMMRegister result = { index + 1 };
232c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    return result;
233c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org  }
234c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org
235a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  static const char* AllocationIndexToString(int index) {
236a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
237a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    const char* const names[] = {
238a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm1",
239a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm2",
240a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm3",
241a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm4",
242a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm5",
243a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm6",
244a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm7",
245a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm8",
246a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm9",
247a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm10",
248a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm11",
249a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm12",
250a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm13",
251a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm14",
252a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm15"
253a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    };
254a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    return names[index];
255a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
256a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
257c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  static XMMRegister from_code(int code) {
258c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ASSERT(code >= 0);
25994b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org    ASSERT(code < kMaxNumRegisters);
260c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    XMMRegister r = { code };
261c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    return r;
262c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
26394b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters; }
264c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org  bool is(XMMRegister reg) const { return code_ == reg.code_; }
2654a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  int code() const {
2669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    ASSERT(is_valid());
2679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    return code_;
2689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
2699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
27086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // Return the high bit of the register code as a 0 or 1.  Used often
27186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // when constructing the REX prefix byte.
27286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  int high_bit() const {
27386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org    return code_ >> 3;
27486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  }
27586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // Return the 3 low bits of the register code.  Used when encoding registers
27686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // in modR/M, SIB, and opcode bytes.
27786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  int low_bits() const {
27886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org    return code_ & 0x7;
27986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  }
28086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
2819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  int code_;
2829085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
2839085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
284b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm0 = { 0 };
285b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm1 = { 1 };
286b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm2 = { 2 };
287b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm3 = { 3 };
288b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm4 = { 4 };
289b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm5 = { 5 };
290b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm6 = { 6 };
291b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm7 = { 7 };
292b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm8 = { 8 };
293b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm9 = { 9 };
294b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm10 = { 10 };
295b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm11 = { 11 };
296b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm12 = { 12 };
297b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm13 = { 13 };
298b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm14 = { 14 };
299b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm15 = { 15 };
3009085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
301a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
302a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgtypedef XMMRegister DoubleRegister;
303a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
304a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
3059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgenum Condition {
3069085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // any value < 0 is considered no_condition
3079085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  no_condition  = -1,
3089085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3099085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  overflow      =  0,
3109085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  no_overflow   =  1,
3119085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  below         =  2,
3129085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  above_equal   =  3,
3139085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  equal         =  4,
3149085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  not_equal     =  5,
3159085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  below_equal   =  6,
3169085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  above         =  7,
3179085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  negative      =  8,
3189085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  positive      =  9,
3199085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  parity_even   = 10,
3209085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  parity_odd    = 11,
3219085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  less          = 12,
3229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  greater_equal = 13,
3239085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  less_equal    = 14,
3249085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  greater       = 15,
3259085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3269d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // Fake conditions that are handled by the
3279d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // opcodes using them.
3289d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  always        = 16,
3299d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  never         = 17,
3309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // aliases
3319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  carry         = below,
3329085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  not_carry     = above_equal,
3339085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  zero          = equal,
3349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  not_zero      = not_equal,
3359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  sign          = negative,
3369d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  not_sign      = positive,
3379d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  last_condition = greater
3389085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
3399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3409085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Returns the equivalent of !cc.
3429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Negation of the default no_condition (-1) results in a non-default
3439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// no_condition value (-2). As long as tests for no_condition check
3449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// for condition < 0, this will work as expected.
3455ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.orginline Condition NegateCondition(Condition cc) {
3465ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  return static_cast<Condition>(cc ^ 1);
3475ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org}
3485ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org
3499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3509085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Corresponds to transposing the operands of a comparison.
3519085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orginline Condition ReverseCondition(Condition cc) {
3529085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  switch (cc) {
3539085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    case below:
3549085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org      return above;
3559085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    case above:
3569085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org      return below;
3579085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    case above_equal:
3589085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org      return below_equal;
3599085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    case below_equal:
3609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org      return above_equal;
3619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    case less:
3629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org      return greater;
3639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    case greater:
3649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org      return less;
3659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    case greater_equal:
3669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org      return less_equal;
3679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    case less_equal:
3689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org      return greater_equal;
3699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    default:
3709085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org      return cc;
3719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  };
3729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org}
3739085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3745ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org
3759085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// -----------------------------------------------------------------------------
3769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Machine instruction Immediates
3779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgclass Immediate BASE_EMBEDDED {
3799085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org public:
380755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  explicit Immediate(int32_t value) : value_(value) {}
3819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3829085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private:
383755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  int32_t value_;
3849085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3859085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  friend class Assembler;
3869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
3879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// -----------------------------------------------------------------------------
3909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Machine instruction Operands
3919085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3929085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgenum ScaleFactor {
3933e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  times_1 = 0,
3943e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  times_2 = 1,
3953e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  times_4 = 2,
3963e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  times_8 = 3,
3973e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  times_int_size = times_4,
3983e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  times_pointer_size = times_8
3999085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
4009085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
4019085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
4029085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgclass Operand BASE_EMBEDDED {
4039085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org public:
4049085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // [base + disp/r]
405eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  Operand(Register base, int32_t disp);
4069085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
4079085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // [base + index*scale + disp/r]
408755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  Operand(Register base,
409755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org          Register index,
410755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org          ScaleFactor scale,
411755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org          int32_t disp);
4129085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
4139085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // [index*scale + disp/r]
414755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  Operand(Register index,
415755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org          ScaleFactor scale,
416755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org          int32_t disp);
4179085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
4189155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org  // Offset from existing memory operand.
4199155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org  // Offset is added to existing displacement as 32-bit signed values and
4209155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org  // this must not overflow.
4219155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org  Operand(const Operand& base, int32_t offset);
4229155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org
4230ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // Checks whether either base or index register is the given register.
4240ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // Does not check the "reg" part of the Operand.
4250ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  bool AddressUsesRegister(Register reg) const;
4260ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
427eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  // Queries related to the size of the generated instruction.
428eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  // Whether the generated instruction will have a REX prefix.
429eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  bool requires_rex() const { return rex_ != 0; }
430eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  // Size of the ModR/M, SIB and displacement parts of the generated
431eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  // instruction.
432eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  int operand_size() const { return len_; }
433eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org
4349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private:
4359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  byte rex_;
43630ce411529579186181838984710b0b0980857aaricow@chromium.org  byte buf_[6];
4370ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // The number of bytes of buf_ in use.
4380ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  byte len_;
4399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
440e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Set the ModR/M byte without an encoded 'reg' register. The
4419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // register is encoded later as part of the emit_operand operation.
442755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // set_modrm can be called before or after set_sib and set_disp*.
4439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  inline void set_modrm(int mod, Register rm);
4449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
445755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Set the SIB byte if one is needed. Sets the length to 2 rather than 1.
4469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  inline void set_sib(ScaleFactor scale, Register index, Register base);
4479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
448755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Adds operand displacement fields (offsets added to the memory address).
449755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Needs to be called after set_sib, not before it.
450755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  inline void set_disp8(int disp);
451755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  inline void set_disp32(int disp);
4529085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
453755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  friend class Assembler;
4549085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
4559085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
4569085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
4579085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// CpuFeatures keeps track of which features are supported by the target CPU.
458750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org// Supported features must be enabled by a CpuFeatureScope before use.
4599085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Example:
460750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org//   if (assembler->IsSupported(SSE3)) {
461750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org//     CpuFeatureScope fscope(assembler, SSE3);
4623e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org//     // Generate SSE3 floating point code.
4639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org//   } else {
464e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org//     // Generate standard SSE2 floating point code.
4659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org//   }
466c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.orgclass CpuFeatures : public AllStatic {
4679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org public:
4689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Detect features of the target CPU. Set safe defaults if the serializer
4699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // is enabled (snapshots must be portable).
470c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  static void Probe();
471ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
4729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Check whether a feature is supported by the target CPU.
473c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  static bool IsSupported(CpuFeature f) {
474c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    ASSERT(initialized_);
4759d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    if (f == SSE3 && !FLAG_enable_sse3) return false;
4767a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org    if (f == SSE4_1 && !FLAG_enable_sse4_1) return false;
4779d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    if (f == CMOV && !FLAG_enable_cmov) return false;
4789d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    if (f == RDTSC && !FLAG_enable_rdtsc) return false;
4799d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    if (f == SAHF && !FLAG_enable_sahf) return false;
480750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    return (supported_ & (static_cast<uint64_t>(1) << f)) != 0;
4819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
482c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org
483750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
484c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    ASSERT(initialized_);
485750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    return (found_by_runtime_probing_only_ &
486750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org            (static_cast<uint64_t>(1) << f)) != 0;
4879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
48883e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org
489750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  static bool IsSafeForSnapshot(CpuFeature f) {
490750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    return (IsSupported(f) &&
491750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org            (!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f)));
492750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  }
493ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
494c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org private:
495e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Safe defaults include CMOV for X64. It is always available, if
4963e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // anyone checks, but they shouldn't need to check.
497ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // The required user mode extensions in X64 are (from AMD64 ABI Table A.1):
498ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  //   fpu, tsc, cx8, cmov, mmx, sse, sse2, fxsr, syscall
499e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  static const uint64_t kDefaultCpuFeatures = (1 << CMOV);
500ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
501c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org#ifdef DEBUG
502c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  static bool initialized_;
503c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org#endif
504c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  static uint64_t supported_;
505750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  static uint64_t found_by_runtime_probing_only_;
506ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
507003650ee766f5e92756d470a37973fd371757485yangguo@chromium.org  friend class ExternalReference;
508ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
5099085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
5109085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
5119085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
512ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgclass Assembler : public AssemblerBase {
5139085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private:
5143e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // We check before assembling an instruction that there is sufficient
5153e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // space to write an instruction and its relocation information.
5163e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // The relocation writer's position must be kGap bytes above the end of
5179085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // the generated instructions. This leaves enough space for the
5183e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // longest possible x64 instruction, 15 bytes, and the longest possible
5193e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
5203e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // (There is a 15 byte limit on x64 instruction length that rules out some
5213e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // otherwise valid instructions.)
5223e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // This allows for a single, fast space check per instruction.
5239085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  static const int kGap = 32;
5249085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
5259085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org public:
5269085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Create an assembler. Instructions and relocation information are emitted
5279085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // into a buffer, with the instructions starting from the beginning and the
5289085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // relocation information starting from the end of the buffer. See CodeDesc
5299085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // for a detailed comment on the layout (globals.h).
5309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  //
5319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // If the provided buffer is NULL, the assembler allocates and grows its own
5329085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // buffer, and buffer_size determines the initial buffer size. The buffer is
5339085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // owned by the assembler and deallocated upon destruction of the assembler.
5349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  //
5359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // If the provided buffer is not NULL, the assembler uses the provided buffer
5369085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // for code generation and assumes its size to be buffer_size. If the buffer
5379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // is too small, a fatal error occurs. No deallocation of the buffer is done
5389085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // upon destruction of the assembler.
539c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  Assembler(Isolate* isolate, void* buffer, int buffer_size);
5408e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  virtual ~Assembler() { }
5419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
5429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // GetCode emits any pending (non-emitted) code and fills the descriptor
5439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // desc. GetCode() is idempotent; it returns the same result if no other
5449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Assembler functions are invoked in between GetCode() calls.
5459085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void GetCode(CodeDesc* desc);
5469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
547c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // Read/Modify the code target in the relative branch/call instruction at pc.
548c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // On the x64 architecture, we use relative jumps with a 32-bit displacement
549c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // to jump to other Code objects in the Code space in the heap.
550c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // Jumps to C functions are done indirectly through a 64-bit register holding
551c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // the absolute address of the target.
552c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // These functions convert between absolute Addresses of Code objects and
553c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // the relative displacements stored in the code.
554e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  static inline Address target_address_at(Address pc);
555e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  static inline void set_target_address_at(Address pc, Address target);
556c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org
55789e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  // Return the code target address at a call site from the return address
55889e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  // of that call in the instruction stream.
55989e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  static inline Address target_address_from_return_address(Address pc);
56089e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org
5613811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // This sets the branch destination (which is in the instruction on x64).
562c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  // This is for calls and branches within generated code.
56388aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org  inline static void deserialization_set_special_target_at(
56488aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org      Address instruction_payload, Address target) {
5653811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    set_target_address_at(instruction_payload, target);
5663811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  }
567c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org
568c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  // This sets the branch destination (which is a load instruction on x64).
569c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  // This is for calls and branches to runtime code.
570c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  inline static void set_external_target_at(Address instruction_payload,
571c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org                                            Address target) {
572c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    *reinterpret_cast<Address*>(instruction_payload) = target;
573c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  }
574c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org
575c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  inline Handle<Object> code_target_object_handle_at(Address pc);
5766e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  inline Address runtime_entry_at(Address pc);
5773811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // Number of bytes taken up by the branch target in the code.
57888aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org  static const int kSpecialTargetSize = 4;  // Use 32-bit displacement.
5799085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Distance between the address of the code target in the call instruction
580c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // and the return address pushed on the stack.
581c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  static const int kCallTargetAddressOffset = 4;  // Use 32-bit displacement.
582594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // The length of call(kScratchRegister).
583594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kCallScratchRegisterInstructionLength = 3;
584594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // The length of call(Immediate32).
585abafe3dbcc62abc040625a8356be42bbd0cf7608danno@chromium.org  static const int kShortCallInstructionLength = 5;
586594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // The length of movq(kScratchRegister, address).
587594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kMoveAddressIntoScratchRegisterInstructionLength =
588594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      2 + kPointerSize;
589594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // The length of movq(kScratchRegister, address) and call(kScratchRegister).
590594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kCallSequenceLength =
591594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      kMoveAddressIntoScratchRegisterInstructionLength +
592594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      kCallScratchRegisterInstructionLength;
593594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org
594594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // The js return and debug break slot must be able to contain an indirect
595594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // call sequence, some x64 JS code is padded with int3 to make it large
596594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // enough to hold an instruction when the debugger patches it.
597594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kJSReturnSequenceLength = kCallSequenceLength;
598594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kDebugBreakSlotLength = kCallSequenceLength;
599594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kPatchDebugBreakSlotReturnOffset = kCallTargetAddressOffset;
600594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // Distance between the start of the JS return sequence and where the
601594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // 32-bit displacement of a short call would be. The short call is from
602594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // SetDebugBreakAtIC from debug-x64.cc.
603594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kPatchReturnSequenceAddressOffset =
604594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      kJSReturnSequenceLength - kPatchDebugBreakSlotReturnOffset;
605594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // Distance between the start of the JS return sequence and where the
606594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // 32-bit displacement of a short call would be. The short call is from
607594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // SetDebugBreakAtIC from debug-x64.cc.
608594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kPatchDebugBreakSlotAddressOffset =
609594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      kDebugBreakSlotLength - kPatchDebugBreakSlotReturnOffset;
610594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kRealPatchReturnSequenceAddressOffset =
611594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      kMoveAddressIntoScratchRegisterInstructionLength - kPointerSize;
6122356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org
6135d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // One byte opcode for test eax,0xXXXXXXXX.
6145d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  static const byte kTestEaxByte = 0xA9;
615d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  // One byte opcode for test al, 0xXX.
616d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  static const byte kTestAlByte = 0xA8;
617496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  // One byte opcode for nop.
618496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  static const byte kNopByte = 0x90;
619496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
620496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  // One byte prefix for a short conditional jump.
621496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  static const byte kJccShortPrefix = 0x70;
622496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  static const byte kJncShortOpcode = kJccShortPrefix | not_carry;
623496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  static const byte kJcShortOpcode = kJccShortPrefix | carry;
624212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org  static const byte kJnzShortOpcode = kJccShortPrefix | not_zero;
625212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org  static const byte kJzShortOpcode = kJccShortPrefix | zero;
626496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
6272356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org
6289085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
6299085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Code generation
6309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  //
63171affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // Function names correspond one-to-one to x64 instruction mnemonics.
63271affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // Unless specified otherwise, instructions operate on 64-bit operands.
63371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  //
63471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // If we need versions of an assembly instruction that operate on different
63571affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // width arguments, we add a single-letter suffix specifying the width.
636eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // This is done for the following instructions: mov, cmp, inc, dec,
637eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // add, sub, and test.
63871affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // There are no versions of these instructions without the suffix.
63971affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'.
64071affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // - Instructions on 16-bit (word) operands/registers have a trailing 'w'.
64171affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // - Instructions on 32-bit (doubleword) operands/registers use 'l'.
64271affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // - Instructions on 64-bit (quadword) operands/registers use 'q'.
64371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  //
64471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // Some mnemonics, such as "and", are the same as C++ keywords.
64571affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // Naming conflicts with C++ keywords are resolved by adding a trailing '_'.
6469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
6479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Insert the smallest number of nop instructions
6489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // possible to align the pc offset to a multiple
64983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // of m, where m must be a power of 2.
6509085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void Align(int m);
65164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  void Nop(int bytes = 1);
6525ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  // Aligns code to something that's optimal for a jump target for the platform.
6535ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  void CodeTargetAlign();
6549085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
6559085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Stack
656e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void pushfq();
657e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void popfq();
6589085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
659e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void push(Immediate value);
6600ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // Push a 32 bit integer, and guarantee that it is actually pushed as a
6610ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // 32 bit value, the normal push will optimize the 8 bit case.
6620ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void push_imm32(int32_t imm32);
6639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void push(Register src);
6649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void push(const Operand& src);
6659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
6669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void pop(Register dst);
6679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void pop(const Operand& dst);
6689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
669e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void enter(Immediate size);
6709085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void leave();
6719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
6729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Moves
673755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void movb(Register dst, const Operand& src);
674e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void movb(Register dst, Immediate imm);
675755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void movb(const Operand& dst, Register src);
676755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
6773811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // Move the low 16 bits of a 64-bit register value to a 16-bit
6783811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // memory location.
6793811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void movw(const Operand& dst, Register src);
6803811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
681e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void movl(Register dst, Register src);
682e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void movl(Register dst, const Operand& src);
683e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void movl(const Operand& dst, Register src);
684eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void movl(const Operand& dst, Immediate imm);
685e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Load a 32-bit immediate value, zero-extended to 64 bits.
686e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void movl(Register dst, Immediate imm32);
687e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
688911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  // Move 64 bit register value to 64-bit memory location.
689911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void movq(const Operand& dst, Register src);
690911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  // Move 64 bit memory location to 64-bit register value.
691755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void movq(Register dst, const Operand& src);
692911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void movq(Register dst, Register src);
693e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Sign extends immediate 32-bit value to 64 bits.
694e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void movq(Register dst, Immediate x);
695911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  // Move the offset of the label location relative to the current
696911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  // position (after the move) to the destination.
697911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void movl(const Operand& dst, Label* src);
698e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
699eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // Move sign extended immediate to memory location.
700eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void movq(const Operand& dst, Immediate value);
701badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  // Instructions to load a 64-bit immediate into a register.
702755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // All 64-bit immediates must have a relocation mode.
703755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void movq(Register dst, void* ptr, RelocInfo::Mode rmode);
704755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void movq(Register dst, int64_t value, RelocInfo::Mode rmode);
705755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void movq(Register dst, const char* s, RelocInfo::Mode rmode);
706e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Moves the address of the external reference into the register.
707e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void movq(Register dst, ExternalReference ext);
708755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void movq(Register dst, Handle<Object> handle, RelocInfo::Mode rmode);
709755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
7103811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void movsxbq(Register dst, const Operand& src);
7113811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void movsxwq(Register dst, const Operand& src);
7125aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void movsxlq(Register dst, Register src);
7133e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void movsxlq(Register dst, const Operand& src);
7145aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void movzxbq(Register dst, const Operand& src);
7155a6af92a1549c81fb61855518f43b712e4c0e469christian.plesner.hansen@gmail.com  void movzxbl(Register dst, const Operand& src);
7163811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void movzxwq(Register dst, const Operand& src);
7175a6af92a1549c81fb61855518f43b712e4c0e469christian.plesner.hansen@gmail.com  void movzxwl(Register dst, const Operand& src);
71846a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  void movzxwl(Register dst, Register src);
7195aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
720b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Repeated moves.
721b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
722b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void repmovsb();
723b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void repmovsw();
724b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void repmovsl();
725b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void repmovsq();
726b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
727badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  // Instruction to load from an immediate 64-bit pointer into RAX.
728755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void load_rax(void* ptr, RelocInfo::Mode rmode);
729e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void load_rax(ExternalReference ext);
7309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
7313e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // Conditional moves.
7323e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cmovq(Condition cc, Register dst, Register src);
7333e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cmovq(Condition cc, Register dst, const Operand& src);
7343e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cmovl(Condition cc, Register dst, Register src);
7353e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cmovl(Condition cc, Register dst, const Operand& src);
7369085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
7379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Exchange two registers
7389085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void xchg(Register dst, Register src);
7399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
7409085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Arithmetics
7415aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void addl(Register dst, Register src) {
7429dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    arithmetic_op_32(0x03, dst, src);
7435aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  }
7445aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
7453e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void addl(Register dst, Immediate src) {
7463e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org    immediate_arithmetic_op_32(0x0, dst, src);
7473e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  }
7483e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
749e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  void addl(Register dst, const Operand& src) {
750e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    arithmetic_op_32(0x03, dst, src);
751e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  }
752e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
75386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  void addl(const Operand& dst, Immediate src) {
75486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org    immediate_arithmetic_op_32(0x0, dst, src);
75586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  }
75686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
757c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void addl(const Operand& dst, Register src) {
758c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    arithmetic_op_32(0x01, src, dst);
759c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
760c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
761e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  void addq(Register dst, Register src) {
762755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    arithmetic_op(0x03, dst, src);
763755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
764755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
765e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  void addq(Register dst, const Operand& src) {
766e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    arithmetic_op(0x03, dst, src);
767e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  }
768755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
769eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void addq(const Operand& dst, Register src) {
770755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    arithmetic_op(0x01, src, dst);
771755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
772755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
773eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void addq(Register dst, Immediate src) {
774755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    immediate_arithmetic_op(0x0, dst, src);
775755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
7769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
777eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void addq(const Operand& dst, Immediate src) {
778755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    immediate_arithmetic_op(0x0, dst, src);
779755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
780755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
781dff694e8cc18aa9640e92962de2699b9d07a7690vegorov@chromium.org  void sbbl(Register dst, Register src) {
7829dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    arithmetic_op_32(0x1b, dst, src);
783dff694e8cc18aa9640e92962de2699b9d07a7690vegorov@chromium.org  }
784dff694e8cc18aa9640e92962de2699b9d07a7690vegorov@chromium.org
7850a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  void sbbq(Register dst, Register src) {
7860a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    arithmetic_op(0x1b, dst, src);
7870a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  }
7880a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
7893e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cmpb(Register dst, Immediate src) {
7903e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org    immediate_arithmetic_op_8(0x7, dst, src);
7913e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  }
7923e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
793911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpb_al(Immediate src);
794911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
795911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpb(Register dst, Register src) {
796911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org    arithmetic_op(0x3A, dst, src);
797911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
798911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
799911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpb(Register dst, const Operand& src) {
800911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org    arithmetic_op(0x3A, dst, src);
801911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
802911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
803911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpb(const Operand& dst, Register src) {
804911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org    arithmetic_op(0x38, src, dst);
805911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
806911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
807eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void cmpb(const Operand& dst, Immediate src) {
808eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    immediate_arithmetic_op_8(0x7, dst, src);
809eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  }
810eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
811911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpw(const Operand& dst, Immediate src) {
812911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org    immediate_arithmetic_op_16(0x7, dst, src);
813911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
814911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
815911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpw(Register dst, Immediate src) {
816911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org    immediate_arithmetic_op_16(0x7, dst, src);
817911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
818911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
819911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpw(Register dst, const Operand& src) {
820911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org    arithmetic_op_16(0x3B, dst, src);
821911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
822911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
823911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpw(Register dst, Register src) {
824911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org    arithmetic_op_16(0x3B, dst, src);
825911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
826911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
827911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpw(const Operand& dst, Register src) {
828911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org    arithmetic_op_16(0x39, src, dst);
829911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
830911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
83168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  void cmpl(Register dst, Register src) {
83268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    arithmetic_op_32(0x3B, dst, src);
83368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
83468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
83568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  void cmpl(Register dst, const Operand& src) {
836e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    arithmetic_op_32(0x3B, dst, src);
83768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
83868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
83968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  void cmpl(const Operand& dst, Register src) {
840e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    arithmetic_op_32(0x39, src, dst);
84168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
84268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
84368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  void cmpl(Register dst, Immediate src) {
84468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    immediate_arithmetic_op_32(0x7, dst, src);
84568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
84668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
84768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  void cmpl(const Operand& dst, Immediate src) {
84868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    immediate_arithmetic_op_32(0x7, dst, src);
84968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
85068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
851eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void cmpq(Register dst, Register src) {
852755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    arithmetic_op(0x3B, dst, src);
853755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
854755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
855eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void cmpq(Register dst, const Operand& src) {
856755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    arithmetic_op(0x3B, dst, src);
857755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
858755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
859eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void cmpq(const Operand& dst, Register src) {
860755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    arithmetic_op(0x39, src, dst);
861755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
8629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
863eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void cmpq(Register dst, Immediate src) {
864755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    immediate_arithmetic_op(0x7, dst, src);
865755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
866755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
867eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void cmpq(const Operand& dst, Immediate src) {
868755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    immediate_arithmetic_op(0x7, dst, src);
869755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
870755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
871755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void and_(Register dst, Register src) {
872755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    arithmetic_op(0x23, dst, src);
873755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
874755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
875755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void and_(Register dst, const Operand& src) {
876755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    arithmetic_op(0x23, dst, src);
877755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
878755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
879755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void and_(const Operand& dst, Register src) {
880755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    arithmetic_op(0x21, src, dst);
881755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
882755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
883755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void and_(Register dst, Immediate src) {
884755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    immediate_arithmetic_op(0x4, dst, src);
885755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
886755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
887755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void and_(const Operand& dst, Immediate src) {
888755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    immediate_arithmetic_op(0x4, dst, src);
889755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
8909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
891c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  void andl(Register dst, Immediate src) {
892c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    immediate_arithmetic_op_32(0x4, dst, src);
893c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  }
894c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org
8959d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void andl(Register dst, Register src) {
8969d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    arithmetic_op_32(0x23, dst, src);
8979d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  }
8989d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
8990ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void andl(Register dst, const Operand& src) {
9000ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    arithmetic_op_32(0x23, dst, src);
9010ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  }
9020ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
903b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void andb(Register dst, Immediate src) {
904b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    immediate_arithmetic_op_8(0x4, dst, src);
905b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
9069d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
907eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void decq(Register dst);
908eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void decq(const Operand& dst);
909e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  void decl(Register dst);
910eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void decl(const Operand& dst);
9119d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void decb(Register dst);
9129d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void decb(const Operand& dst);
9139085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
914e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Sign-extends rax into rdx:rax.
915e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void cqo();
9160b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Sign-extends eax into edx:eax.
9170b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  void cdq();
9189085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
919e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Divide rdx:rax by src.  Quotient in rax, remainder in rdx.
9200b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  void idivq(Register src);
9210b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Divide edx:eax by lower 32 bits of src.  Quotient in eax, rem. in edx.
9220b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  void idivl(Register src);
9239085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9242abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  // Signed multiply instructions.
9252abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  void imul(Register src);                               // rdx:rax = rax * src.
9262abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  void imul(Register dst, Register src);                 // dst = dst * src.
9272abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  void imul(Register dst, const Operand& src);           // dst = dst * src.
9282abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org  void imul(Register dst, Register src, Immediate imm);  // dst = src * imm.
929cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  // Signed 32-bit multiply instructions.
930cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  void imull(Register dst, Register src);                 // dst = dst * src.
931d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  void imull(Register dst, const Operand& src);           // dst = dst * src.
932cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  void imull(Register dst, Register src, Immediate imm);  // dst = src * imm.
9339085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
934eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void incq(Register dst);
935eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void incq(const Operand& dst);
9365ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  void incl(Register dst);
937eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void incl(const Operand& dst);
9389085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void lea(Register dst, const Operand& src);
940cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  void leal(Register dst, const Operand& src);
9419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
942e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Multiply rax by src, put the result in rdx:rax.
9439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void mul(Register src);
9449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9459085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void neg(Register dst);
946755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void neg(const Operand& dst);
9474af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void negl(Register dst);
9489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void not_(Register dst);
950755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void not_(const Operand& dst);
951cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  void notl(Register dst);
952755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
953755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void or_(Register dst, Register src) {
954755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    arithmetic_op(0x0B, dst, src);
955755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
956755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
9574af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void orl(Register dst, Register src) {
9584af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org    arithmetic_op_32(0x0B, dst, src);
9594af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
9604af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
961755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void or_(Register dst, const Operand& src) {
962755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    arithmetic_op(0x0B, dst, src);
963755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
964755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
96583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  void orl(Register dst, const Operand& src) {
96683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    arithmetic_op_32(0x0B, dst, src);
96783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  }
96883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
969755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void or_(const Operand& dst, Register src) {
970755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    arithmetic_op(0x09, src, dst);
971755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
972755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
973755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void or_(Register dst, Immediate src) {
974755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    immediate_arithmetic_op(0x1, dst, src);
975755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
976755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
9779d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void orl(Register dst, Immediate src) {
9789d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    immediate_arithmetic_op_32(0x1, dst, src);
9799d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  }
9809d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
981755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void or_(const Operand& dst, Immediate src) {
982755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    immediate_arithmetic_op(0x1, dst, src);
983755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
9849085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9859d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void orl(const Operand& dst, Immediate src) {
9869d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    immediate_arithmetic_op_32(0x1, dst, src);
9879d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  }
9889d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
9899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9909d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void rcl(Register dst, Immediate imm8) {
9919d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    shift(dst, imm8, 0x2);
9929d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  }
9939d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
9949d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void rol(Register dst, Immediate imm8) {
9959d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    shift(dst, imm8, 0x0);
9969d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  }
9979d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
9989d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void rcr(Register dst, Immediate imm8) {
9999d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    shift(dst, imm8, 0x3);
10009d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  }
10019d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
10029d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void ror(Register dst, Immediate imm8) {
10039d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    shift(dst, imm8, 0x1);
10049d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  }
10059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1006e4ee6de0de64744d55b63da83156827c989c7099verwaest@chromium.org  void rorl(Register dst, Immediate imm8) {
1007e4ee6de0de64744d55b63da83156827c989c7099verwaest@chromium.org    shift_32(dst, imm8, 0x1);
1008e4ee6de0de64744d55b63da83156827c989c7099verwaest@chromium.org  }
1009e4ee6de0de64744d55b63da83156827c989c7099verwaest@chromium.org
1010e4ee6de0de64744d55b63da83156827c989c7099verwaest@chromium.org  void rorl_cl(Register dst) {
1011e4ee6de0de64744d55b63da83156827c989c7099verwaest@chromium.org    shift_32(dst, 0x1);
1012e4ee6de0de64744d55b63da83156827c989c7099verwaest@chromium.org  }
1013e4ee6de0de64744d55b63da83156827c989c7099verwaest@chromium.org
1014e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Shifts dst:src left by cl bits, affecting only dst.
1015e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void shld(Register dst, Register src);
1016e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1017e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Shifts src:dst right by cl bits, affecting only dst.
1018e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void shrd(Register dst, Register src);
1019e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1020e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Shifts dst right, duplicating sign bit, by shift_amount bits.
1021e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Shifting by 1 is handled efficiently.
1022e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void sar(Register dst, Immediate shift_amount) {
1023e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org    shift(dst, shift_amount, 0x7);
1024e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  }
1025e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1026defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org  // Shifts dst right, duplicating sign bit, by shift_amount bits.
1027defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org  // Shifting by 1 is handled efficiently.
1028defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org  void sarl(Register dst, Immediate shift_amount) {
1029defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org    shift_32(dst, shift_amount, 0x7);
1030defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org  }
1031defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org
1032e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Shifts dst right, duplicating sign bit, by cl % 64 bits.
1033c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  void sar_cl(Register dst) {
1034e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org    shift(dst, 0x7);
1035e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  }
10369085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1037defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org  // Shifts dst right, duplicating sign bit, by cl % 64 bits.
1038c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  void sarl_cl(Register dst) {
1039defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org    shift_32(dst, 0x7);
1040defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org  }
1041defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org
1042e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void shl(Register dst, Immediate shift_amount) {
1043e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org    shift(dst, shift_amount, 0x4);
1044e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  }
10459085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1046c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  void shl_cl(Register dst) {
1047e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org    shift(dst, 0x4);
1048e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  }
10499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1050c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  void shll_cl(Register dst) {
10515aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org    shift_32(dst, 0x4);
10525aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  }
10535aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
1054e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  void shll(Register dst, Immediate shift_amount) {
1055e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    shift_32(dst, shift_amount, 0x4);
1056e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  }
1057e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
1058e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void shr(Register dst, Immediate shift_amount) {
1059e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org    shift(dst, shift_amount, 0x5);
1060e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  }
10619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1062c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  void shr_cl(Register dst) {
1063e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org    shift(dst, 0x5);
1064e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  }
10659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1066c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  void shrl_cl(Register dst) {
10675aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org    shift_32(dst, 0x5);
10685aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  }
10695aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
1070e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  void shrl(Register dst, Immediate shift_amount) {
1071e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    shift_32(dst, shift_amount, 0x5);
1072e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  }
1073e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
1074e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void store_rax(void* dst, RelocInfo::Mode mode);
1075e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void store_rax(ExternalReference ref);
10769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1077eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void subq(Register dst, Register src) {
1078755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    arithmetic_op(0x2B, dst, src);
1079755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
1080755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1081eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void subq(Register dst, const Operand& src) {
1082755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    arithmetic_op(0x2B, dst, src);
1083755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
1084755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1085eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void subq(const Operand& dst, Register src) {
1086755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    arithmetic_op(0x29, src, dst);
1087755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
10889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1089eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void subq(Register dst, Immediate src) {
1090755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    immediate_arithmetic_op(0x5, dst, src);
1091755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
1092755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1093eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void subq(const Operand& dst, Immediate src) {
1094755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    immediate_arithmetic_op(0x5, dst, src);
1095755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
1096755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
10975aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void subl(Register dst, Register src) {
10985aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org    arithmetic_op_32(0x2B, dst, src);
10995aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  }
11005aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
1101b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void subl(Register dst, const Operand& src) {
1102b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    arithmetic_op_32(0x2B, dst, src);
1103b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
1104b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1105eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void subl(const Operand& dst, Immediate src) {
1106eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    immediate_arithmetic_op_32(0x5, dst, src);
1107eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  }
1108eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
110986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  void subl(Register dst, Immediate src) {
111086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org    immediate_arithmetic_op_32(0x5, dst, src);
111186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  }
111286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
1113911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void subb(Register dst, Immediate src) {
1114911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org    immediate_arithmetic_op_8(0x5, dst, src);
1115911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
1116911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
11179d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void testb(Register dst, Register src);
1118755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void testb(Register reg, Immediate mask);
1119755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void testb(const Operand& op, Immediate mask);
1120b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void testb(const Operand& op, Register reg);
112168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  void testl(Register dst, Register src);
1122755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void testl(Register reg, Immediate mask);
1123755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void testl(const Operand& op, Immediate mask);
1124e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void testq(const Operand& op, Register reg);
1125e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void testq(Register dst, Register src);
1126eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void testq(Register dst, Immediate mask);
1127755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1128755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void xor_(Register dst, Register src) {
11293811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    if (dst.code() == src.code()) {
11303811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      arithmetic_op_32(0x33, dst, src);
11313811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    } else {
11323811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      arithmetic_op(0x33, dst, src);
11333811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    }
1134755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
1135755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
11364af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  void xorl(Register dst, Register src) {
11374af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org    arithmetic_op_32(0x33, dst, src);
11384af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
11394af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
114083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  void xorl(Register dst, const Operand& src) {
114183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    arithmetic_op_32(0x33, dst, src);
114283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  }
114383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
114483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  void xorl(Register dst, Immediate src) {
114583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    immediate_arithmetic_op_32(0x6, dst, src);
114683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  }
114783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
114883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  void xorl(const Operand& dst, Immediate src) {
114983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    immediate_arithmetic_op_32(0x6, dst, src);
115083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  }
115183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
1152755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void xor_(Register dst, const Operand& src) {
1153755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    arithmetic_op(0x33, dst, src);
1154755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
1155755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1156755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void xor_(const Operand& dst, Register src) {
1157755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    arithmetic_op(0x31, src, dst);
1158755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
1159755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1160755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void xor_(Register dst, Immediate src) {
1161755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    immediate_arithmetic_op(0x6, dst, src);
1162755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
1163755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1164755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void xor_(const Operand& dst, Immediate src) {
1165755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    immediate_arithmetic_op(0x6, dst, src);
1166755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
11679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Bit operations.
11699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void bt(const Operand& dst, Register src);
11709085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void bts(const Operand& dst, Register src);
11719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Miscellaneous
11739d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void clc();
11747979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  void cld();
1175eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void cpuid();
11769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void hlt();
11779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void int3();
11789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void nop();
11799085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void rdtsc();
11809085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void ret(int imm16);
1181eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void setcc(Condition cc, Register reg);
11829085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11839085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Label operations & relative jumps (PPUM Appendix D)
11849085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  //
11859085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Takes a branch opcode (cc) and a label (L) and generates
11869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // either a backward branch or a forward branch and links it
11879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // to the label fixup chain. Usage:
11889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  //
11899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Label L;    // unbound label
11909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // j(cc, &L);  // forward branch to unbound label
11919085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // bind(&L);   // bind label to the current pc
11929085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // j(cc, &L);  // backward branch to bound label
11939085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // bind(&L);   // illegal: a label may be bound only once
11949085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  //
11959085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Note: The same Label can be used for forward and backward branches
11969085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // but it may be bound only once.
11979085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11989085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void bind(Label* L);  // binds an unbound label L to the current code position
11999085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12009085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Calls
1201e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Call near relative 32-bit displacement, relative to next instruction.
12029085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void call(Label* L);
12036e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  void call(Address entry, RelocInfo::Mode rmode);
12048e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  void call(Handle<Code> target,
12054f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org            RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
1206471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org            TypeFeedbackId ast_id = TypeFeedbackId::None());
1207e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
120883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // Calls directly to the given address using a relative offset.
120983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // Should only ever be used in Code objects for calls within the
121083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // same Code object. Should not be used when generating new code (use labels),
121183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // but only when patching existing code.
121283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  void call(Address target);
121383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
1214e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Call near absolute indirect, address in register
1215e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void call(Register adr);
1216e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1217e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Call near indirect
1218e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void call(const Operand& operand);
12199085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12209085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Jumps
1221e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Jump short or near relative.
1222c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // Use a 32-bit signed displacement.
122383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Unconditional jump to L
122483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void jmp(Label* L, Label::Distance distance = Label::kFar);
12256e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  void jmp(Address entry, RelocInfo::Mode rmode);
1226c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  void jmp(Handle<Code> target, RelocInfo::Mode rmode);
1227e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1228e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Jump near absolute indirect (r64)
1229e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void jmp(Register adr);
12309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1231911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  // Jump near absolute indirect (m64)
1232911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void jmp(const Operand& src);
1233911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
12349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Conditional jumps
123583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void j(Condition cc,
123683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org         Label* L,
123783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org         Label::Distance distance = Label::kFar);
12386e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  void j(Condition cc, Address entry, RelocInfo::Mode rmode);
1239c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode);
12409085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Floating-point operations
12429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fld(int i);
12439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fld1();
12459085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fldz();
1246ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  void fldpi();
1247a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  void fldln2();
12489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fld_s(const Operand& adr);
12509085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fld_d(const Operand& adr);
12519085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12529085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fstp_s(const Operand& adr);
12539085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fstp_d(const Operand& adr);
12543811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void fstp(int index);
12559085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12569085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fild_s(const Operand& adr);
12579085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fild_d(const Operand& adr);
12589085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12599085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fist_s(const Operand& adr);
12609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fistp_s(const Operand& adr);
12629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fistp_d(const Operand& adr);
12639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fisttp_s(const Operand& adr);
1265b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void fisttp_d(const Operand& adr);
12669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fabs();
12689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fchs();
12699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12709085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fadd(int i);
12719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fsub(int i);
12729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fmul(int i);
12739085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fdiv(int i);
12749085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12759085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fisub_s(const Operand& adr);
12769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void faddp(int i = 1);
12789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fsubp(int i = 1);
12799085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fsubrp(int i = 1);
12809085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fmulp(int i = 1);
12819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fdivp(int i = 1);
12829085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fprem();
12839085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fprem1();
12849085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12859085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fxch(int i = 1);
12869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fincstp();
12879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void ffree(int i = 0);
12889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
12899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void ftst();
12909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fucomp(int i);
12919085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fucompp();
12923811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void fucomi(int i);
12933811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void fucomip();
12943811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
12959085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fcompp();
12969085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fnstsw_ax();
12979085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fwait();
12989085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fnclex();
12999085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13005aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void fsin();
13015aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void fcos();
13021b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  void fptan();
1303a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  void fyl2x();
130464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  void f2xm1();
130564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  void fscale();
130664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  void fninit();
13075aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
13089085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void frndint();
13099085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13103e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void sahf();
13113e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
13123e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // SSE2 instructions
1313357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org  void movd(XMMRegister dst, Register src);
1314ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  void movd(Register dst, XMMRegister src);
1315ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  void movq(XMMRegister dst, Register src);
1316ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  void movq(Register dst, XMMRegister src);
1317160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  void movq(XMMRegister dst, XMMRegister src);
1318ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  void extractps(Register dst, XMMRegister src, byte imm8);
1319357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org
1320160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  // Don't use this unless it's important to keep the
1321160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  // top half of the destination register unchanged.
1322160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  // Used movaps when moving double values and movq for integer
1323160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  // values in xmm registers.
1324357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org  void movsd(XMMRegister dst, XMMRegister src);
1325160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
1326160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  void movsd(const Operand& dst, XMMRegister src);
1327357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org  void movsd(XMMRegister dst, const Operand& src);
13283e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
13290ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void movdqa(const Operand& dst, XMMRegister src);
13300ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void movdqa(XMMRegister dst, const Operand& src);
13310ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
1332e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  void movdqu(const Operand& dst, XMMRegister src);
1333e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  void movdqu(XMMRegister dst, const Operand& src);
1334e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
1335160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  void movapd(XMMRegister dst, XMMRegister src);
1336160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  void movaps(XMMRegister dst, XMMRegister src);
1337160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
133840b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  void movss(XMMRegister dst, const Operand& src);
133940b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  void movss(const Operand& dst, XMMRegister src);
134040b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org
13419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void cvttss2si(Register dst, const Operand& src);
13420a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  void cvttss2si(Register dst, XMMRegister src);
13439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void cvttsd2si(Register dst, const Operand& src);
13440a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  void cvttsd2si(Register dst, XMMRegister src);
1345dff694e8cc18aa9640e92962de2699b9d07a7690vegorov@chromium.org  void cvttsd2siq(Register dst, XMMRegister src);
13469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13473e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cvtlsi2sd(XMMRegister dst, const Operand& src);
13483e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cvtlsi2sd(XMMRegister dst, Register src);
13493e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cvtqsi2sd(XMMRegister dst, const Operand& src);
13503e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cvtqsi2sd(XMMRegister dst, Register src);
13519085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
135240b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  void cvtlsi2ss(XMMRegister dst, Register src);
135340b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org
1354357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org  void cvtss2sd(XMMRegister dst, XMMRegister src);
135540b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  void cvtss2sd(XMMRegister dst, const Operand& src);
135640b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  void cvtsd2ss(XMMRegister dst, XMMRegister src);
135740b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org
135840b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  void cvtsd2si(Register dst, XMMRegister src);
135940b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  void cvtsd2siq(Register dst, XMMRegister src);
1360357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org
13619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void addsd(XMMRegister dst, XMMRegister src);
13621f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  void addsd(XMMRegister dst, const Operand& src);
13639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void subsd(XMMRegister dst, XMMRegister src);
13649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void mulsd(XMMRegister dst, XMMRegister src);
13651f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  void mulsd(XMMRegister dst, const Operand& src);
13669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void divsd(XMMRegister dst, XMMRegister src);
13679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13685d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  void andpd(XMMRegister dst, XMMRegister src);
13695d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  void orpd(XMMRegister dst, XMMRegister src);
13705c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void xorpd(XMMRegister dst, XMMRegister src);
1371160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  void xorps(XMMRegister dst, XMMRegister src);
13724111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org  void sqrtsd(XMMRegister dst, XMMRegister src);
13735c838251403b0be9a882540f1922577abba4c872ager@chromium.org
13745c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void ucomisd(XMMRegister dst, XMMRegister src);
137540b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  void ucomisd(XMMRegister dst, const Operand& src);
13763e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
1377160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  enum RoundingMode {
1378160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    kRoundToNearest = 0x0,
1379160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    kRoundDown      = 0x1,
1380160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    kRoundUp        = 0x2,
1381160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    kRoundToZero    = 0x3
1382160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  };
1383160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
1384160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode);
1385160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
138683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  void movmskpd(Register dst, XMMRegister src);
13874121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org  void movmskps(Register dst, XMMRegister src);
138883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
1389357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org  // The first argument is the reg field, the second argument is the r/m field.
13903e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void emit_sse_operand(XMMRegister dst, XMMRegister src);
13913e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void emit_sse_operand(XMMRegister reg, const Operand& adr);
13923e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void emit_sse_operand(XMMRegister dst, Register src);
1393ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  void emit_sse_operand(Register dst, XMMRegister src);
13943e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
13959085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Debugging
13969085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void Print();
13979085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13989085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Check the code size generated from label to here.
13994f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  int SizeOfCodeGeneratedSince(Label* label) {
14004f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    return pc_offset() - label->pos();
14014f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
14029085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
14039085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Mark address of the ExitJSFrame code.
14049085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void RecordJSReturn();
14059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
14062356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org  // Mark address of a debug break slot.
14072356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org  void RecordDebugBreakSlot();
14082356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org
14099085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Record a comment relocation entry that can be used by a disassembler.
1410a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Use --code-comments to enable.
14113a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  void RecordComment(const char* msg, bool force = false);
14129085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1413a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Writes a single word of data in the code stream.
1414a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Used for inline tables, e.g., jump-tables.
14150511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  void db(uint8_t data);
1416a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  void dd(uint32_t data);
1417a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
1418f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org  PositionsRecorder* positions_recorder() { return &positions_recorder_; }
14199085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
14209085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Check if there is less than kGap bytes available in the buffer.
14219085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // If this is the case, we need to grow the buffer before emitting
14229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // an instruction or relocation information.
14234af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  inline bool buffer_overflow() const {
14244af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org    return pc_ >= reloc_info_writer.pos() - kGap;
14254af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
14269085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
14279085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Get the number of bytes available in the buffer.
1428c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  inline int available_space() const {
1429c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    return static_cast<int>(reloc_info_writer.pos() - pc_);
1430c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  }
14319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
143264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  static bool IsNop(Address addr);
14332356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org
14349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Avoid overflows for displacements etc.
14359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  static const int kMaximalBufferSize = 512*MB;
14369085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1437c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  byte byte_at(int pos)  { return buffer_[pos]; }
1438c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
1439c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
14409085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private:
14419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  byte* addr_at(int pos)  { return buffer_ + pos; }
14429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  uint32_t long_at(int pos)  {
14439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    return *reinterpret_cast<uint32_t*>(addr_at(pos));
14449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
14459085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void long_at_put(int pos, uint32_t x)  {
14469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
14479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
14489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
14499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // code emission
14509085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void GrowBuffer();
1451755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1452755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void emit(byte x) { *pc_++ = x; }
1453755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  inline void emitl(uint32_t x);
1454fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  inline void emitp(void* x, RelocInfo::Mode rmode);
1455755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  inline void emitq(uint64_t x, RelocInfo::Mode rmode);
1456e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emitw(uint16_t x);
14578e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  inline void emit_code_target(Handle<Code> target,
14588e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org                               RelocInfo::Mode rmode,
1459471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org                               TypeFeedbackId ast_id = TypeFeedbackId::None());
14606e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  inline void emit_runtime_entry(Address entry, RelocInfo::Mode rmode);
1461755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void emit(Immediate x) { emitl(x.value_); }
14629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
146371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // Emits a REX prefix that encodes a 64-bit operand size and
146471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // the top bit of both register codes.
1465755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1466755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // REX.W is set.
14673e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  inline void emit_rex_64(XMMRegister reg, Register rm_reg);
1468ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  inline void emit_rex_64(Register reg, XMMRegister rm_reg);
1469ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  inline void emit_rex_64(Register reg, Register rm_reg);
147071affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org
147171affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // Emits a REX prefix that encodes a 64-bit operand size and
147271affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // the top bit of the destination, index, and base register codes.
1473755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // The high bit of reg is used for REX.R, the high bit of op's base
1474755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // register is used for REX.B, and the high bit of op's index register
1475755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // is used for REX.X.  REX.W is set.
147671affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  inline void emit_rex_64(Register reg, const Operand& op);
14773e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  inline void emit_rex_64(XMMRegister reg, const Operand& op);
1478e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1479e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emits a REX prefix that encodes a 64-bit operand size and
1480e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // the top bit of the register code.
1481e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // The high bit of register is used for REX.B.
1482e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // REX.W is set and REX.R and REX.X are clear.
1483e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emit_rex_64(Register rm_reg);
1484e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1485e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emits a REX prefix that encodes a 64-bit operand size and
1486e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // the top bit of the index and base register codes.
1487e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // The high bit of op's base register is used for REX.B, and the high
1488e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // bit of op's index register is used for REX.X.
1489e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // REX.W is set and REX.R clear.
1490e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emit_rex_64(const Operand& op);
1491e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1492e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emit a REX prefix that only sets REX.W to choose a 64-bit operand size.
1493e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void emit_rex_64() { emit(0x48); }
1494755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1495755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1496e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // REX.W is clear.
1497755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  inline void emit_rex_32(Register reg, Register rm_reg);
1498755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1499755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // The high bit of reg is used for REX.R, the high bit of op's base
1500755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // register is used for REX.B, and the high bit of op's index register
1501755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // is used for REX.X.  REX.W is cleared.
1502755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  inline void emit_rex_32(Register reg, const Operand& op);
1503755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1504e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // High bit of rm_reg goes to REX.B.
1505e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // REX.W, REX.R and REX.X are clear.
1506e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emit_rex_32(Register rm_reg);
1507e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1508e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // High bit of base goes to REX.B and high bit of index to REX.X.
1509e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // REX.W and REX.R are clear.
1510e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emit_rex_32(const Operand& op);
1511e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1512755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1513755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // REX.W is cleared.  If no REX bits are set, no byte is emitted.
1514755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  inline void emit_optional_rex_32(Register reg, Register rm_reg);
1515755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1516755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // The high bit of reg is used for REX.R, the high bit of op's base
1517755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // register is used for REX.B, and the high bit of op's index register
1518755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // is used for REX.X.  REX.W is cleared.  If no REX bits are set, nothing
1519755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // is emitted.
1520755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  inline void emit_optional_rex_32(Register reg, const Operand& op);
1521755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
15223e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // As for emit_optional_rex_32(Register, Register), except that
15233e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // the registers are XMM registers.
15243e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  inline void emit_optional_rex_32(XMMRegister reg, XMMRegister base);
15253e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
15263e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // As for emit_optional_rex_32(Register, Register), except that
1527ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // one of the registers is an XMM registers.
15283e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  inline void emit_optional_rex_32(XMMRegister reg, Register base);
15293e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
1530ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // As for emit_optional_rex_32(Register, Register), except that
1531ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // one of the registers is an XMM registers.
1532ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  inline void emit_optional_rex_32(Register reg, XMMRegister base);
1533ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
15343e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // As for emit_optional_rex_32(Register, const Operand&), except that
15353e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // the register is an XMM register.
15363e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  inline void emit_optional_rex_32(XMMRegister reg, const Operand& op);
15373e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
1538e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Optionally do as emit_rex_32(Register) if the register number has
1539e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // the high bit set.
1540e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emit_optional_rex_32(Register rm_reg);
1541e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1542e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Optionally do as emit_rex_32(const Operand&) if the operand register
1543e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // numbers have a high bit set.
1544e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emit_optional_rex_32(const Operand& op);
1545e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1546e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1547e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emit the ModR/M byte, and optionally the SIB byte and
1548755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // 1- or 4-byte offset for a memory operand.  Also encodes
1549755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // the second operand of the operation, a register or operation
1550e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // subcode, into the reg field of the ModR/M byte.
1551e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void emit_operand(Register reg, const Operand& adr) {
15525aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org    emit_operand(reg.low_bits(), adr);
1553e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  }
1554e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1555e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emit the ModR/M byte, and optionally the SIB byte and
1556e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // 1- or 4-byte offset for a memory operand.  Also used to encode
1557e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // a three-bit opcode extension into the ModR/M byte.
1558e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void emit_operand(int rm, const Operand& adr);
1559e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1560e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emit a ModR/M byte with registers coded in the reg and rm_reg fields.
1561e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void emit_modrm(Register reg, Register rm_reg) {
15625aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org    emit(0xC0 | reg.low_bits() << 3 | rm_reg.low_bits());
1563e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  }
1564e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1565e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emit a ModR/M byte with an operation subcode in the reg field and
1566e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // a register in the rm_reg field.
1567e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void emit_modrm(int code, Register rm_reg) {
15685aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org    ASSERT(is_uint3(code));
15695aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org    emit(0xC0 | code << 3 | rm_reg.low_bits());
1570755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
157171affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org
15729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Emit the code-object-relative offset of the label's position
15739085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  inline void emit_code_relative_offset(Label* label);
15749085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1575755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Emit machine code for one of the operations ADD, ADC, SUB, SBC,
1576755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // AND, OR, XOR, or CMP.  The encodings of these operations are all
1577755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // similar, differing just in the opcode or in the reg field of the
1578e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // ModR/M byte.
1579911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void arithmetic_op_16(byte opcode, Register reg, Register rm_reg);
1580911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg);
1581911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void arithmetic_op_32(byte opcode, Register reg, Register rm_reg);
1582e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  void arithmetic_op_32(byte opcode, Register reg, const Operand& rm_reg);
1583911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void arithmetic_op(byte opcode, Register reg, Register rm_reg);
1584e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  void arithmetic_op(byte opcode, Register reg, const Operand& rm_reg);
1585755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void immediate_arithmetic_op(byte subcode, Register dst, Immediate src);
1586755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void immediate_arithmetic_op(byte subcode, const Operand& dst, Immediate src);
15873e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // Operate on a byte in memory or register.
1588eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void immediate_arithmetic_op_8(byte subcode,
1589911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                 Register dst,
15903e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org                                 Immediate src);
15913e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void immediate_arithmetic_op_8(byte subcode,
1592911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                 const Operand& dst,
15933e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org                                 Immediate src);
1594911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  // Operate on a word in memory or register.
1595911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void immediate_arithmetic_op_16(byte subcode,
1596911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                  Register dst,
1597911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                  Immediate src);
1598911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void immediate_arithmetic_op_16(byte subcode,
1599911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                  const Operand& dst,
1600911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                  Immediate src);
1601911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  // Operate on a 32-bit word in memory or register.
1602911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void immediate_arithmetic_op_32(byte subcode,
1603911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                  Register dst,
1604911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                  Immediate src);
1605911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void immediate_arithmetic_op_32(byte subcode,
1606911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                  const Operand& dst,
1607911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                  Immediate src);
1608911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
1609e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emit machine code for a shift operation.
1610e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void shift(Register dst, Immediate shift_amount, int subcode);
1611defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org  void shift_32(Register dst, Immediate shift_amount, int subcode);
1612e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Shift dst by cl % 64 bits.
1613e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void shift(Register dst, int subcode);
16145aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void shift_32(Register dst, int subcode);
16159085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
16165aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void emit_farith(int b1, int b2, int i);
16179085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
16189085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // labels
1619eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // void print(Label* L);
16209085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void bind_to(Label* L, int pos);
16219085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
16229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // record reloc info for current pc_
16239085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
16249085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
16259085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  friend class CodePatcher;
16269085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  friend class EnsureSpace;
1627911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  friend class RegExpMacroAssemblerX64;
16289085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
16299085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // code generation
16309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  RelocInfoWriter reloc_info_writer;
16319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1632c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  List< Handle<Code> > code_targets_;
16339085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1634f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org  PositionsRecorder positions_recorder_;
1635f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org  friend class PositionsRecorder;
16369085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
16379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
16389085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
16399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Helper class that ensures that there is enough space for generating
16409085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// instructions and relocation information.  The constructor makes
16419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// sure that there is enough space and (in debug mode) the destructor
16429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// checks that we did not generate too much.
16439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgclass EnsureSpace BASE_EMBEDDED {
16449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org public:
16459085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
16464af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org    if (assembler_->buffer_overflow()) assembler_->GrowBuffer();
16479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#ifdef DEBUG
16489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    space_before_ = assembler_->available_space();
16499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#endif
16509085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
16519085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
16529085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#ifdef DEBUG
16539085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  ~EnsureSpace() {
16549085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    int bytes_generated = space_before_ - assembler_->available_space();
16559085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    ASSERT(bytes_generated < assembler_->kGap);
16569085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
16579085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#endif
16589085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
16599085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private:
16609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  Assembler* assembler_;
16619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#ifdef DEBUG
16629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  int space_before_;
16639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#endif
16649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
16659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
16669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org} }  // namespace v8::internal
16675ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org
16689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#endif  // V8_X64_ASSEMBLER_X64_H_
1669