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
40196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/serialize.h"
41c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org
4271affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace v8 {
4371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace internal {
449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
45e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org// Utility functions
46e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// CPU Registers.
489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org//
499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// 1) We would prefer to use an enum, but enum values are assignment-
509085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// compatible with int, which has caused code-generation bugs.
519085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org//
529085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// 2) We would prefer to use a class instead of a struct but we don't like
539085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// the register initialization to depend on the particular initialization
549085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// order (which appears to be different on OS X, Linux, and Windows for the
559085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// installed versions of C++ we tried). Using a struct permits C-style
569085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// "initialization". Also, the Register objects cannot be const as this
579085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// forces initialization stubs in MSVC, making us dependent on initialization
589085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// order.
599085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org//
609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// 3) By not using an enum, we are possibly preventing the compiler from
619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// doing certain constant folds, which may significantly reduce the
629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// code generated for some assembly instructions (because they boil down
639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// to a few constants). If this is a problem, we could change the code
649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// such that we use an enum in optimized mode, and the struct in debug
659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// mode. This way we get the compile-time error checking in debug mode
669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// and best performance in optimized code.
679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org//
689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgstruct Register {
70a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // The non-allocatable registers are:
71a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  //  rsp - stack pointer
72a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  //  rbp - frame pointer
73a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  //  r10 - fixed scratch register
74b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org  //  r12 - smi constant register
75a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  //  r13 - root register
76935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org  static const int kMaxNumAllocatableRegisters = 11;
77a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  static int NumAllocatableRegisters() {
78a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    return kMaxNumAllocatableRegisters;
79a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
80a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  static const int kNumRegisters = 16;
81a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
82c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org  static int ToAllocationIndex(Register reg) {
833a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    return kAllocationIndexByRegisterCode[reg.code()];
84c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org  }
85c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org
86c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org  static Register FromAllocationIndex(int index) {
87e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
883a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    Register result = { kRegisterCodeByAllocationIndex[index] };
89c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    return result;
90c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org  }
91c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org
92a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  static const char* AllocationIndexToString(int index) {
93e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
94a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    const char* const names[] = {
95a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "rax",
96a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "rbx",
97c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      "rdx",
98c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      "rcx",
99935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org      "rsi",
100a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "rdi",
101a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "r8",
102a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "r9",
103a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "r11",
104c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      "r14",
105b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org      "r15"
106a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    };
107a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    return names[index];
108a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
109a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
11084bcc559ac20fb04f806e97d28a314b20b58fd60svenpanne@chromium.org  static Register from_code(int code) {
111eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    Register r = { code };
112755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    return r;
113755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
114a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
1154a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  bool is(Register reg) const { return code_ == reg.code_; }
11656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org  // rax, rbx, rcx and rdx are byte registers, the rest are not.
11756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org  bool is_byte_register() const { return code_ <= 3; }
1184a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  int code() const {
119e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(is_valid());
1209085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    return code_;
1219085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
1224a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  int bit() const {
123eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    return 1 << code_;
1249085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
1259085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1265aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  // Return the high bit of the register code as a 0 or 1.  Used often
1275aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  // when constructing the REX prefix byte.
1285aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  int high_bit() const {
1295aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org    return code_ >> 3;
1305aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  }
1315aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  // Return the 3 low bits of the register code.  Used when encoding registers
1325aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  // in modR/M, SIB, and opcode bytes.
1335aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  int low_bits() const {
1345aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org    return code_ & 0x7;
1355aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  }
1365aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
1375c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Unfortunately we can't make this private in a struct when initializing
1385c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // by assignment.
1399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  int code_;
1400ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
141c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org private:
142a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  static const int kRegisterCodeByAllocationIndex[kMaxNumAllocatableRegisters];
1433a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  static const int kAllocationIndexByRegisterCode[kNumRegisters];
1449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
1459085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1461456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_rax_Code = 0;
1471456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_rcx_Code = 1;
1481456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_rdx_Code = 2;
1491456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_rbx_Code = 3;
1501456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_rsp_Code = 4;
1511456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_rbp_Code = 5;
1521456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_rsi_Code = 6;
1531456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_rdi_Code = 7;
1541456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_r8_Code = 8;
1551456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_r9_Code = 9;
1561456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_r10_Code = 10;
1571456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_r11_Code = 11;
1581456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_r12_Code = 12;
1591456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_r13_Code = 13;
1601456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_r14_Code = 14;
1611456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_r15_Code = 15;
1621456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst int kRegister_no_reg_Code = -1;
1631456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
1641456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register rax = { kRegister_rax_Code };
1651456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register rcx = { kRegister_rcx_Code };
1661456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register rdx = { kRegister_rdx_Code };
1671456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register rbx = { kRegister_rbx_Code };
1681456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register rsp = { kRegister_rsp_Code };
1691456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register rbp = { kRegister_rbp_Code };
1701456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register rsi = { kRegister_rsi_Code };
1711456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register rdi = { kRegister_rdi_Code };
1721456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register r8 = { kRegister_r8_Code };
1731456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register r9 = { kRegister_r9_Code };
1741456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register r10 = { kRegister_r10_Code };
1751456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register r11 = { kRegister_r11_Code };
1761456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register r12 = { kRegister_r12_Code };
1771456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register r13 = { kRegister_r13_Code };
1781456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register r14 = { kRegister_r14_Code };
1791456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register r15 = { kRegister_r15_Code };
1801456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgconst Register no_reg = { kRegister_no_reg_Code };
1815aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
182ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org#ifdef _WIN64
183ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // Windows calling convention
1846b0169a99e75f4821ce4168e5e0d3cc8f6526a83danno@chromium.org  const Register arg_reg_1 = { kRegister_rcx_Code };
1856b0169a99e75f4821ce4168e5e0d3cc8f6526a83danno@chromium.org  const Register arg_reg_2 = { kRegister_rdx_Code };
1866b0169a99e75f4821ce4168e5e0d3cc8f6526a83danno@chromium.org  const Register arg_reg_3 = { kRegister_r8_Code };
1876b0169a99e75f4821ce4168e5e0d3cc8f6526a83danno@chromium.org  const Register arg_reg_4 = { kRegister_r9_Code };
188ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org#else
189ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // AMD64 calling convention
1906b0169a99e75f4821ce4168e5e0d3cc8f6526a83danno@chromium.org  const Register arg_reg_1 = { kRegister_rdi_Code };
1916b0169a99e75f4821ce4168e5e0d3cc8f6526a83danno@chromium.org  const Register arg_reg_2 = { kRegister_rsi_Code };
1926b0169a99e75f4821ce4168e5e0d3cc8f6526a83danno@chromium.org  const Register arg_reg_3 = { kRegister_rdx_Code };
1936b0169a99e75f4821ce4168e5e0d3cc8f6526a83danno@chromium.org  const Register arg_reg_4 = { kRegister_rcx_Code };
194ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org#endif  // _WIN64
1955aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
1969085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgstruct XMMRegister {
19794b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  static const int kMaxNumRegisters = 16;
198a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  static const int kMaxNumAllocatableRegisters = 15;
199a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  static int NumAllocatableRegisters() {
200a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    return kMaxNumAllocatableRegisters;
201a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
202a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
203a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  static int ToAllocationIndex(XMMRegister reg) {
204e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(reg.code() != 0);
205a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    return reg.code() - 1;
206a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
207a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
208c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org  static XMMRegister FromAllocationIndex(int index) {
209e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(0 <= index && index < kMaxNumAllocatableRegisters);
210c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    XMMRegister result = { index + 1 };
211c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    return result;
212c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org  }
213c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org
214a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  static const char* AllocationIndexToString(int index) {
215e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
216a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    const char* const names[] = {
217a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm1",
218a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm2",
219a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm3",
220a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm4",
221a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm5",
222a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm6",
223a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm7",
224a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm8",
225a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm9",
226a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm10",
227a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm11",
228a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm12",
229a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm13",
230a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm14",
231a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      "xmm15"
232a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    };
233a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    return names[index];
234a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
235a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
236c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  static XMMRegister from_code(int code) {
237e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(code >= 0);
238e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(code < kMaxNumRegisters);
239c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    XMMRegister r = { code };
240c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    return r;
241c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
24294b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters; }
243c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org  bool is(XMMRegister reg) const { return code_ == reg.code_; }
2444a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  int code() const {
245e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(is_valid());
2469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    return code_;
2479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
2489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
24986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // Return the high bit of the register code as a 0 or 1.  Used often
25086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // when constructing the REX prefix byte.
25186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  int high_bit() const {
25286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org    return code_ >> 3;
25386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  }
25486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // Return the 3 low bits of the register code.  Used when encoding registers
25586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // in modR/M, SIB, and opcode bytes.
25686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  int low_bits() const {
25786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org    return code_ & 0x7;
25886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  }
25986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
2609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  int code_;
2619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
2629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
263b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm0 = { 0 };
264b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm1 = { 1 };
265b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm2 = { 2 };
266b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm3 = { 3 };
267b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm4 = { 4 };
268b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm5 = { 5 };
269b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm6 = { 6 };
270b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm7 = { 7 };
271b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm8 = { 8 };
272b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm9 = { 9 };
273b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm10 = { 10 };
274b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm11 = { 11 };
275b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm12 = { 12 };
276b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm13 = { 13 };
277b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm14 = { 14 };
278b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.orgconst XMMRegister xmm15 = { 15 };
2799085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
280a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
281a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgtypedef XMMRegister DoubleRegister;
282a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
283a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
2849085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgenum Condition {
2859085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // any value < 0 is considered no_condition
2869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  no_condition  = -1,
2879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
2889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  overflow      =  0,
2899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  no_overflow   =  1,
2909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  below         =  2,
2919085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  above_equal   =  3,
2929085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  equal         =  4,
2939085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  not_equal     =  5,
2949085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  below_equal   =  6,
2959085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  above         =  7,
2969085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  negative      =  8,
2979085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  positive      =  9,
2989085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  parity_even   = 10,
2999085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  parity_odd    = 11,
3009085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  less          = 12,
3019085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  greater_equal = 13,
3029085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  less_equal    = 14,
3039085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  greater       = 15,
3049085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3059d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // Fake conditions that are handled by the
3069d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // opcodes using them.
3079d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  always        = 16,
3089d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  never         = 17,
3099085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // aliases
3109085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  carry         = below,
3119085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  not_carry     = above_equal,
3129085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  zero          = equal,
3139085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  not_zero      = not_equal,
3149085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  sign          = negative,
3159d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  not_sign      = positive,
3169d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  last_condition = greater
3179085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
3189085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3199085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3209085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Returns the equivalent of !cc.
3219085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Negation of the default no_condition (-1) results in a non-default
3229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// no_condition value (-2). As long as tests for no_condition check
3239085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// for condition < 0, this will work as expected.
3245ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.orginline Condition NegateCondition(Condition cc) {
3255ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  return static_cast<Condition>(cc ^ 1);
3265ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org}
3275ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org
3289085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3291e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org// Commute a condition such that {a cond b == b cond' a}.
33038de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.orginline Condition CommuteCondition(Condition cc) {
3319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  switch (cc) {
3329085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    case below:
3339085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org      return above;
3349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    case above:
3359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org      return below;
3369085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    case above_equal:
3379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org      return below_equal;
3389085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    case below_equal:
3399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org      return above_equal;
3409085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    case less:
3419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org      return greater;
3429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    case greater:
3439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org      return less;
3449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    case greater_equal:
3459085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org      return less_equal;
3469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    case less_equal:
3479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org      return greater_equal;
3489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    default:
3499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org      return cc;
3503c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  }
3519085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org}
3529085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3535ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org
3549085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// -----------------------------------------------------------------------------
3559085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Machine instruction Immediates
3569085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3579085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgclass Immediate BASE_EMBEDDED {
3589085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org public:
359755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  explicit Immediate(int32_t value) : value_(value) {}
36004a34e6171ac922cb1a4c5162cf471809c468ad0machenbach@chromium.org  explicit Immediate(Smi* value) {
361e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(SmiValuesAre31Bits());  // Only available for 31-bit SMI.
36204a34e6171ac922cb1a4c5162cf471809c468ad0machenbach@chromium.org    value_ = static_cast<int32_t>(reinterpret_cast<intptr_t>(value));
36304a34e6171ac922cb1a4c5162cf471809c468ad0machenbach@chromium.org  }
3649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private:
366755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  int32_t value_;
3679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  friend class Assembler;
3699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
3709085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// -----------------------------------------------------------------------------
3739085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Machine instruction Operands
3749085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3759085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgenum ScaleFactor {
3763e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  times_1 = 0,
3773e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  times_2 = 1,
3783e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  times_4 = 2,
3793e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  times_8 = 3,
3803e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  times_int_size = times_4,
38125530ce9cb50f9e8386663ca40fd3f6e023ec9f6bmeurer@chromium.org  times_pointer_size = (kPointerSize == 8) ? times_8 : times_4
3829085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
3839085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3849085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3859085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgclass Operand BASE_EMBEDDED {
3869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org public:
3879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // [base + disp/r]
388eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  Operand(Register base, int32_t disp);
3899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // [base + index*scale + disp/r]
391755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  Operand(Register base,
392755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org          Register index,
393755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org          ScaleFactor scale,
394755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org          int32_t disp);
3959085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
3969085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // [index*scale + disp/r]
397755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  Operand(Register index,
398755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org          ScaleFactor scale,
399755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org          int32_t disp);
4009085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
4019155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org  // Offset from existing memory operand.
4029155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org  // Offset is added to existing displacement as 32-bit signed values and
4039155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org  // this must not overflow.
4049155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org  Operand(const Operand& base, int32_t offset);
4059155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org
4060ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // Checks whether either base or index register is the given register.
4070ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // Does not check the "reg" part of the Operand.
4080ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  bool AddressUsesRegister(Register reg) const;
4090ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
410eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  // Queries related to the size of the generated instruction.
411eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  // Whether the generated instruction will have a REX prefix.
412eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  bool requires_rex() const { return rex_ != 0; }
413eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  // Size of the ModR/M, SIB and displacement parts of the generated
414eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  // instruction.
415eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org  int operand_size() const { return len_; }
416eb96f4fd17b379ad2247264f82af1100f448779bricow@chromium.org
4179085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private:
4189085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  byte rex_;
41930ce411529579186181838984710b0b0980857aaricow@chromium.org  byte buf_[6];
4200ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // The number of bytes of buf_ in use.
4210ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  byte len_;
4229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
423e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Set the ModR/M byte without an encoded 'reg' register. The
4249085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // register is encoded later as part of the emit_operand operation.
425755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // set_modrm can be called before or after set_sib and set_disp*.
4269085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  inline void set_modrm(int mod, Register rm);
4279085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
428755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Set the SIB byte if one is needed. Sets the length to 2 rather than 1.
4299085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  inline void set_sib(ScaleFactor scale, Register index, Register base);
4309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
431755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Adds operand displacement fields (offsets added to the memory address).
432755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Needs to be called after set_sib, not before it.
433755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  inline void set_disp8(int disp);
434755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  inline void set_disp32(int disp);
4359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
436755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  friend class Assembler;
4379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
4389085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
4399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
4407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#define ASSEMBLER_INSTRUCTION_LIST(V) \
4417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(add)                              \
4427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(and)                              \
4437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(cmp)                              \
4447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(dec)                              \
4457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(idiv)                             \
4467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(div)                              \
4477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(imul)                             \
4487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(inc)                              \
4497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(lea)                              \
4507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(mov)                              \
4517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(movzxb)                           \
4527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(movzxw)                           \
4537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(neg)                              \
4547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(not)                              \
4557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(or)                               \
4567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(repmovs)                          \
4577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(sbb)                              \
4587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(sub)                              \
4597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(test)                             \
4607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(xchg)                             \
461895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  V(xor)
462ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org
463ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org
4642f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org// Shift instructions on operands/registers with kPointerSize, kInt32Size and
4652f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org// kInt64Size.
4662f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org#define SHIFT_INSTRUCTION_LIST(V)       \
4672f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  V(rol, 0x0)                           \
4682f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  V(ror, 0x1)                           \
4692f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  V(rcl, 0x2)                           \
4702f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  V(rcr, 0x3)                           \
4712f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  V(shl, 0x4)                           \
4722f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  V(shr, 0x5)                           \
4732f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  V(sar, 0x7)                           \
4742f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org
4752f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org
476ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgclass Assembler : public AssemblerBase {
4779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private:
4783e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // We check before assembling an instruction that there is sufficient
4793e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // space to write an instruction and its relocation information.
4803e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // The relocation writer's position must be kGap bytes above the end of
4819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // the generated instructions. This leaves enough space for the
4823e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // longest possible x64 instruction, 15 bytes, and the longest possible
4833e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
4843e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // (There is a 15 byte limit on x64 instruction length that rules out some
4853e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // otherwise valid instructions.)
4863e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // This allows for a single, fast space check per instruction.
4879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  static const int kGap = 32;
4889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
4899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org public:
4909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Create an assembler. Instructions and relocation information are emitted
4919085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // into a buffer, with the instructions starting from the beginning and the
4929085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // relocation information starting from the end of the buffer. See CodeDesc
4939085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // for a detailed comment on the layout (globals.h).
4949085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  //
4959085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // If the provided buffer is NULL, the assembler allocates and grows its own
4969085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // buffer, and buffer_size determines the initial buffer size. The buffer is
4979085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // owned by the assembler and deallocated upon destruction of the assembler.
4989085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  //
4999085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // If the provided buffer is not NULL, the assembler uses the provided buffer
5009085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // for code generation and assumes its size to be buffer_size. If the buffer
5019085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // is too small, a fatal error occurs. No deallocation of the buffer is done
5029085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // upon destruction of the assembler.
503c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  Assembler(Isolate* isolate, void* buffer, int buffer_size);
5048e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  virtual ~Assembler() { }
5059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
5069085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // GetCode emits any pending (non-emitted) code and fills the descriptor
5079085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // desc. GetCode() is idempotent; it returns the same result if no other
5089085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Assembler functions are invoked in between GetCode() calls.
5099085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void GetCode(CodeDesc* desc);
5109085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
511c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // Read/Modify the code target in the relative branch/call instruction at pc.
512c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // On the x64 architecture, we use relative jumps with a 32-bit displacement
513c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // to jump to other Code objects in the Code space in the heap.
514c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // Jumps to C functions are done indirectly through a 64-bit register holding
515c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // the absolute address of the target.
516c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // These functions convert between absolute Addresses of Code objects and
517c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // the relative displacements stored in the code.
51897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  static inline Address target_address_at(Address pc,
51997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org                                          ConstantPoolArray* constant_pool);
52097b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  static inline void set_target_address_at(Address pc,
52197b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org                                           ConstantPoolArray* constant_pool,
5226a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                           Address target,
5236a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                           ICacheFlushMode icache_flush_mode =
5246a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                               FLUSH_ICACHE_IF_NEEDED) ;
52597b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  static inline Address target_address_at(Address pc, Code* code) {
52697b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
52797b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    return target_address_at(pc, constant_pool);
52897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  }
52997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  static inline void set_target_address_at(Address pc,
53097b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org                                           Code* code,
5316a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                           Address target,
5326a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                           ICacheFlushMode icache_flush_mode =
5336a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                               FLUSH_ICACHE_IF_NEEDED) {
53497b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
5356a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org    set_target_address_at(pc, constant_pool, target, icache_flush_mode);
53697b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  }
537c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org
53889e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  // Return the code target address at a call site from the return address
53989e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  // of that call in the instruction stream.
54089e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  static inline Address target_address_from_return_address(Address pc);
54189e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org
5429d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  // Return the code target address of the patch debug break slot
5439d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  inline static Address break_address_from_return_address(Address pc);
5449d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org
5453811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // This sets the branch destination (which is in the instruction on x64).
546c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  // This is for calls and branches within generated code.
54788aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org  inline static void deserialization_set_special_target_at(
54897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org      Address instruction_payload, Code* code, Address target) {
54997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    set_target_address_at(instruction_payload, code, target);
5503811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  }
551c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org
552af4fba3c6d2a18866505de3e6798757dd1448c6dmachenbach@chromium.org  static inline RelocInfo::Mode RelocInfoNone() {
553af4fba3c6d2a18866505de3e6798757dd1448c6dmachenbach@chromium.org    if (kPointerSize == kInt64Size) {
554af4fba3c6d2a18866505de3e6798757dd1448c6dmachenbach@chromium.org      return RelocInfo::NONE64;
555af4fba3c6d2a18866505de3e6798757dd1448c6dmachenbach@chromium.org    } else {
556e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(kPointerSize == kInt32Size);
557af4fba3c6d2a18866505de3e6798757dd1448c6dmachenbach@chromium.org      return RelocInfo::NONE32;
558af4fba3c6d2a18866505de3e6798757dd1448c6dmachenbach@chromium.org    }
559af4fba3c6d2a18866505de3e6798757dd1448c6dmachenbach@chromium.org  }
560af4fba3c6d2a18866505de3e6798757dd1448c6dmachenbach@chromium.org
561c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  inline Handle<Object> code_target_object_handle_at(Address pc);
5626e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  inline Address runtime_entry_at(Address pc);
5633811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // Number of bytes taken up by the branch target in the code.
56488aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org  static const int kSpecialTargetSize = 4;  // Use 32-bit displacement.
5659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Distance between the address of the code target in the call instruction
566c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // and the return address pushed on the stack.
567c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  static const int kCallTargetAddressOffset = 4;  // Use 32-bit displacement.
568594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // The length of call(kScratchRegister).
569594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kCallScratchRegisterInstructionLength = 3;
570594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // The length of call(Immediate32).
571abafe3dbcc62abc040625a8356be42bbd0cf7608danno@chromium.org  static const int kShortCallInstructionLength = 5;
572594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // The length of movq(kScratchRegister, address).
573594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kMoveAddressIntoScratchRegisterInstructionLength =
574594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      2 + kPointerSize;
575594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // The length of movq(kScratchRegister, address) and call(kScratchRegister).
576594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kCallSequenceLength =
577594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      kMoveAddressIntoScratchRegisterInstructionLength +
578594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      kCallScratchRegisterInstructionLength;
579594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org
580594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // The js return and debug break slot must be able to contain an indirect
581594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // call sequence, some x64 JS code is padded with int3 to make it large
582594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // enough to hold an instruction when the debugger patches it.
583594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kJSReturnSequenceLength = kCallSequenceLength;
584594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kDebugBreakSlotLength = kCallSequenceLength;
585594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kPatchDebugBreakSlotReturnOffset = kCallTargetAddressOffset;
586594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // Distance between the start of the JS return sequence and where the
587594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // 32-bit displacement of a short call would be. The short call is from
588594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // SetDebugBreakAtIC from debug-x64.cc.
589594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kPatchReturnSequenceAddressOffset =
590594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      kJSReturnSequenceLength - kPatchDebugBreakSlotReturnOffset;
591594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // Distance between the start of the JS return sequence and where the
592594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // 32-bit displacement of a short call would be. The short call is from
593594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // SetDebugBreakAtIC from debug-x64.cc.
594594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kPatchDebugBreakSlotAddressOffset =
595594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      kDebugBreakSlotLength - kPatchDebugBreakSlotReturnOffset;
596594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kRealPatchReturnSequenceAddressOffset =
597594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      kMoveAddressIntoScratchRegisterInstructionLength - kPointerSize;
5982356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org
5995d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // One byte opcode for test eax,0xXXXXXXXX.
6005d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  static const byte kTestEaxByte = 0xA9;
601d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  // One byte opcode for test al, 0xXX.
602d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  static const byte kTestAlByte = 0xA8;
603496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  // One byte opcode for nop.
604496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  static const byte kNopByte = 0x90;
605496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
606496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  // One byte prefix for a short conditional jump.
607496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  static const byte kJccShortPrefix = 0x70;
608496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  static const byte kJncShortOpcode = kJccShortPrefix | not_carry;
609496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  static const byte kJcShortOpcode = kJccShortPrefix | carry;
610212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org  static const byte kJnzShortOpcode = kJccShortPrefix | not_zero;
611212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org  static const byte kJzShortOpcode = kJccShortPrefix | zero;
612496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
6132356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org
6149085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
6159085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Code generation
6169085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  //
61771affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // Function names correspond one-to-one to x64 instruction mnemonics.
61871affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // Unless specified otherwise, instructions operate on 64-bit operands.
61971affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  //
62071affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // If we need versions of an assembly instruction that operate on different
62171affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // width arguments, we add a single-letter suffix specifying the width.
622eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // This is done for the following instructions: mov, cmp, inc, dec,
623eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // add, sub, and test.
62471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // There are no versions of these instructions without the suffix.
62571affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'.
62671affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // - Instructions on 16-bit (word) operands/registers have a trailing 'w'.
62771affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // - Instructions on 32-bit (doubleword) operands/registers use 'l'.
62871affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // - Instructions on 64-bit (quadword) operands/registers use 'q'.
629895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  // - Instructions on operands/registers with pointer size use 'p'.
6309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
6312f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  STATIC_ASSERT(kPointerSize == kInt64Size || kPointerSize == kInt32Size);
6322f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org
633ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org#define DECLARE_INSTRUCTION(instruction)                \
634fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  template<class P1>                                    \
635fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void instruction##p(P1 p1) {                          \
636fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org    emit_##instruction(p1, kPointerSize);               \
637fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }                                                     \
638fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                                        \
639fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  template<class P1>                                    \
640fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void instruction##l(P1 p1) {                          \
641fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org    emit_##instruction(p1, kInt32Size);                 \
642fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }                                                     \
643fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                                        \
644fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  template<class P1>                                    \
645fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void instruction##q(P1 p1) {                          \
646fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org    emit_##instruction(p1, kInt64Size);                 \
647fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }                                                     \
648fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                                        \
649ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  template<class P1, class P2>                          \
650ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  void instruction##p(P1 p1, P2 p2) {                   \
651ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org    emit_##instruction(p1, p2, kPointerSize);           \
652ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  }                                                     \
653ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org                                                        \
654ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  template<class P1, class P2>                          \
655ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  void instruction##l(P1 p1, P2 p2) {                   \
656ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org    emit_##instruction(p1, p2, kInt32Size);             \
657ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  }                                                     \
658ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org                                                        \
659ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  template<class P1, class P2>                          \
660ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  void instruction##q(P1 p1, P2 p2) {                   \
661ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org    emit_##instruction(p1, p2, kInt64Size);             \
662fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }                                                     \
663fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                                        \
664fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  template<class P1, class P2, class P3>                \
665fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void instruction##p(P1 p1, P2 p2, P3 p3) {            \
666fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org    emit_##instruction(p1, p2, p3, kPointerSize);       \
667fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }                                                     \
668fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                                        \
669fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  template<class P1, class P2, class P3>                \
670fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void instruction##l(P1 p1, P2 p2, P3 p3) {            \
671fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org    emit_##instruction(p1, p2, p3, kInt32Size);         \
672fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }                                                     \
673fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                                        \
674fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  template<class P1, class P2, class P3>                \
675fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void instruction##q(P1 p1, P2 p2, P3 p3) {            \
676fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org    emit_##instruction(p1, p2, p3, kInt64Size);         \
677ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  }
678ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  ASSEMBLER_INSTRUCTION_LIST(DECLARE_INSTRUCTION)
679ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org#undef DECLARE_INSTRUCTION
680ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org
6819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Insert the smallest number of nop instructions
6829085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // possible to align the pc offset to a multiple
68383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // of m, where m must be a power of 2.
6849085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void Align(int m);
68564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  void Nop(int bytes = 1);
6865ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  // Aligns code to something that's optimal for a jump target for the platform.
6875ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  void CodeTargetAlign();
6889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
6899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Stack
690e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void pushfq();
691e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void popfq();
6929085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
693763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void pushq(Immediate value);
6940ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // Push a 32 bit integer, and guarantee that it is actually pushed as a
6950ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // 32 bit value, the normal push will optimize the 8 bit case.
696763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void pushq_imm32(int32_t imm32);
697763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void pushq(Register src);
698763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void pushq(const Operand& src);
6999085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
700763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void popq(Register dst);
701763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void popq(const Operand& dst);
7029085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
703e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void enter(Immediate size);
7049085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void leave();
7059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
7069085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Moves
707755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void movb(Register dst, const Operand& src);
708e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void movb(Register dst, Immediate imm);
709755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void movb(const Operand& dst, Register src);
710e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  void movb(const Operand& dst, Immediate imm);
711755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
7123811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // Move the low 16 bits of a 64-bit register value to a 16-bit
7133811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // memory location.
714e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  void movw(Register dst, const Operand& src);
7153811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void movw(const Operand& dst, Register src);
716e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  void movw(const Operand& dst, Immediate imm);
7173811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
718911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  // Move the offset of the label location relative to the current
719911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  // position (after the move) to the destination.
720911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void movl(const Operand& dst, Label* src);
721e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
722e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  // Loads a pointer into a register with a relocation mode.
7239cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org  void movp(Register dst, void* ptr, RelocInfo::Mode rmode);
7249cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org
725e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  // Loads a 64-bit immediate into a register.
726e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  void movq(Register dst, int64_t value);
727ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  void movq(Register dst, uint64_t value);
728755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
7292ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org  void movsxbl(Register dst, const Operand& src);
7303811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void movsxbq(Register dst, const Operand& src);
7312ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org  void movsxwl(Register dst, const Operand& src);
7323811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void movsxwq(Register dst, const Operand& src);
7335aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void movsxlq(Register dst, Register src);
7343e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void movsxlq(Register dst, const Operand& src);
7355aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
736b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Repeated moves.
737b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
738b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void repmovsb();
739b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void repmovsw();
740895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void repmovsp() { emit_repmovs(kPointerSize); }
741895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void repmovsl() { emit_repmovs(kInt32Size); }
742895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void repmovsq() { emit_repmovs(kInt64Size); }
743b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
744badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  // Instruction to load from an immediate 64-bit pointer into RAX.
745755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void load_rax(void* ptr, RelocInfo::Mode rmode);
746e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void load_rax(ExternalReference ext);
7479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
7483e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // Conditional moves.
7493e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cmovq(Condition cc, Register dst, Register src);
7503e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cmovq(Condition cc, Register dst, const Operand& src);
7513e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cmovl(Condition cc, Register dst, Register src);
7523e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cmovl(Condition cc, Register dst, const Operand& src);
7539085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
7543e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cmpb(Register dst, Immediate src) {
7553e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org    immediate_arithmetic_op_8(0x7, dst, src);
7563e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  }
7573e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
758911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpb_al(Immediate src);
759911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
760911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpb(Register dst, Register src) {
7612f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op_8(0x3A, dst, src);
762911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
763911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
764911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpb(Register dst, const Operand& src) {
7652f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op_8(0x3A, dst, src);
766911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
767911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
768911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpb(const Operand& dst, Register src) {
7692f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op_8(0x38, src, dst);
770911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
771911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
772eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void cmpb(const Operand& dst, Immediate src) {
773eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    immediate_arithmetic_op_8(0x7, dst, src);
774eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  }
775eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
776911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpw(const Operand& dst, Immediate src) {
777911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org    immediate_arithmetic_op_16(0x7, dst, src);
778911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
779911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
780911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpw(Register dst, Immediate src) {
781911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org    immediate_arithmetic_op_16(0x7, dst, src);
782911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
783911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
784911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpw(Register dst, const Operand& src) {
785911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org    arithmetic_op_16(0x3B, dst, src);
786911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
787911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
788911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpw(Register dst, Register src) {
789911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org    arithmetic_op_16(0x3B, dst, src);
790911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
791911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
792911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpw(const Operand& dst, Register src) {
793911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org    arithmetic_op_16(0x39, src, dst);
794911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
795911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
796b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void andb(Register dst, Immediate src) {
797b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    immediate_arithmetic_op_8(0x4, dst, src);
798b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
7999d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
8009d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void decb(Register dst);
8019d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void decb(const Operand& dst);
8029085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
803e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Sign-extends rax into rdx:rax.
804e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void cqo();
8050b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Sign-extends eax into edx:eax.
8060b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  void cdq();
8079085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
808e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Multiply rax by src, put the result in rdx:rax.
8099085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void mul(Register src);
8109085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
8112f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org#define DECLARE_SHIFT_INSTRUCTION(instruction, subcode)     \
8122f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void instruction##p(Register dst, Immediate imm8) {       \
8132f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    shift(dst, imm8, subcode, kPointerSize);                \
8142f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  }                                                         \
8152f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                                                            \
8162f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void instruction##l(Register dst, Immediate imm8) {       \
8172f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    shift(dst, imm8, subcode, kInt32Size);                  \
8182f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  }                                                         \
8192f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                                                            \
8202f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void instruction##q(Register dst, Immediate imm8) {       \
8212f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    shift(dst, imm8, subcode, kInt64Size);                  \
8222f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  }                                                         \
8232f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                                                            \
8242f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void instruction##p_cl(Register dst) {                    \
8252f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    shift(dst, subcode, kPointerSize);                      \
8262f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  }                                                         \
8272f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                                                            \
8282f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void instruction##l_cl(Register dst) {                    \
8292f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    shift(dst, subcode, kInt32Size);                        \
8302f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  }                                                         \
8312f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                                                            \
8322f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void instruction##q_cl(Register dst) {                    \
8332f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    shift(dst, subcode, kInt64Size);                        \
8342f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  }
8352f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  SHIFT_INSTRUCTION_LIST(DECLARE_SHIFT_INSTRUCTION)
8362f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org#undef DECLARE_SHIFT_INSTRUCTION
837e4ee6de0de64744d55b63da83156827c989c7099verwaest@chromium.org
838e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Shifts dst:src left by cl bits, affecting only dst.
839e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void shld(Register dst, Register src);
840e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
841e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Shifts src:dst right by cl bits, affecting only dst.
842e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void shrd(Register dst, Register src);
843e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
844e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void store_rax(void* dst, RelocInfo::Mode mode);
845e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void store_rax(ExternalReference ref);
8469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
847911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void subb(Register dst, Immediate src) {
848911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org    immediate_arithmetic_op_8(0x5, dst, src);
849911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
850911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
8519d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void testb(Register dst, Register src);
852755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void testb(Register reg, Immediate mask);
853755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void testb(const Operand& op, Immediate mask);
854b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void testb(const Operand& op, Register reg);
855755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
8569085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Bit operations.
8579085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void bt(const Operand& dst, Register src);
8589085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void bts(const Operand& dst, Register src);
859f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void bsrl(Register dst, Register src);
8609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
8619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Miscellaneous
8629d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void clc();
8637979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  void cld();
864eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void cpuid();
8659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void hlt();
8669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void int3();
8679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void nop();
8689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void ret(int imm16);
869eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void setcc(Condition cc, Register reg);
8709085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
8719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Label operations & relative jumps (PPUM Appendix D)
8729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  //
8739085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Takes a branch opcode (cc) and a label (L) and generates
8749085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // either a backward branch or a forward branch and links it
8759085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // to the label fixup chain. Usage:
8769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  //
8779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Label L;    // unbound label
8789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // j(cc, &L);  // forward branch to unbound label
8799085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // bind(&L);   // bind label to the current pc
8809085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // j(cc, &L);  // backward branch to bound label
8819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // bind(&L);   // illegal: a label may be bound only once
8829085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  //
8839085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Note: The same Label can be used for forward and backward branches
8849085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // but it may be bound only once.
8859085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
8869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void bind(Label* L);  // binds an unbound label L to the current code position
8879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
8889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Calls
889e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Call near relative 32-bit displacement, relative to next instruction.
8909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void call(Label* L);
8916e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  void call(Address entry, RelocInfo::Mode rmode);
8928e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  void call(Handle<Code> target,
8934f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org            RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
894471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org            TypeFeedbackId ast_id = TypeFeedbackId::None());
895e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
89683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // Calls directly to the given address using a relative offset.
89783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // Should only ever be used in Code objects for calls within the
89883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // same Code object. Should not be used when generating new code (use labels),
89983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // but only when patching existing code.
90083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  void call(Address target);
90183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
902e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Call near absolute indirect, address in register
903e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void call(Register adr);
904e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
9059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Jumps
906e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Jump short or near relative.
907c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // Use a 32-bit signed displacement.
90883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Unconditional jump to L
90983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void jmp(Label* L, Label::Distance distance = Label::kFar);
9106e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  void jmp(Address entry, RelocInfo::Mode rmode);
911c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  void jmp(Handle<Code> target, RelocInfo::Mode rmode);
912e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
913e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Jump near absolute indirect (r64)
914e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void jmp(Register adr);
9159085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9169085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Conditional jumps
91783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void j(Condition cc,
91883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org         Label* L,
91983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org         Label::Distance distance = Label::kFar);
9206e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  void j(Condition cc, Address entry, RelocInfo::Mode rmode);
921c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode);
9229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9239085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Floating-point operations
9249085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fld(int i);
9259085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9269085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fld1();
9279085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fldz();
928ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  void fldpi();
929a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  void fldln2();
9309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fld_s(const Operand& adr);
9329085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fld_d(const Operand& adr);
9339085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fstp_s(const Operand& adr);
9359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fstp_d(const Operand& adr);
9363811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void fstp(int index);
9379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9389085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fild_s(const Operand& adr);
9399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fild_d(const Operand& adr);
9409085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fist_s(const Operand& adr);
9429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fistp_s(const Operand& adr);
9449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fistp_d(const Operand& adr);
9459085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fisttp_s(const Operand& adr);
947b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void fisttp_d(const Operand& adr);
9489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fabs();
9509085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fchs();
9519085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9529085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fadd(int i);
9539085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fsub(int i);
9549085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fmul(int i);
9559085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fdiv(int i);
9569085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9579085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fisub_s(const Operand& adr);
9589085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9599085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void faddp(int i = 1);
9609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fsubp(int i = 1);
9619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fsubrp(int i = 1);
9629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fmulp(int i = 1);
9639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fdivp(int i = 1);
9649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fprem();
9659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fprem1();
9669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fxch(int i = 1);
9689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fincstp();
9699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void ffree(int i = 0);
9709085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void ftst();
9729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fucomp(int i);
9739085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fucompp();
9743811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void fucomi(int i);
9753811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void fucomip();
9763811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
9779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fcompp();
9789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fnstsw_ax();
9799085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fwait();
9809085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fnclex();
9819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9825aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void fsin();
9835aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void fcos();
9841b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  void fptan();
985a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  void fyl2x();
98664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  void f2xm1();
98764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  void fscale();
98864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  void fninit();
9895aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
9909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void frndint();
9919085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9923e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void sahf();
9933e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
994ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  // SSE instructions
995ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void movaps(XMMRegister dst, XMMRegister src);
996ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void movss(XMMRegister dst, const Operand& src);
997ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void movss(const Operand& dst, XMMRegister src);
998af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void shufps(XMMRegister dst, XMMRegister src, byte imm8);
999ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org
1000ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void cvttss2si(Register dst, const Operand& src);
1001ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void cvttss2si(Register dst, XMMRegister src);
1002ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void cvtlsi2ss(XMMRegister dst, Register src);
1003ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org
1004ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void andps(XMMRegister dst, XMMRegister src);
1005af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void andps(XMMRegister dst, const Operand& src);
1006057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  void orps(XMMRegister dst, XMMRegister src);
1007af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void orps(XMMRegister dst, const Operand& src);
1008057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  void xorps(XMMRegister dst, XMMRegister src);
1009af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void xorps(XMMRegister dst, const Operand& src);
1010af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org
1011af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void addps(XMMRegister dst, XMMRegister src);
1012af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void addps(XMMRegister dst, const Operand& src);
1013af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void subps(XMMRegister dst, XMMRegister src);
1014af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void subps(XMMRegister dst, const Operand& src);
1015af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void mulps(XMMRegister dst, XMMRegister src);
1016af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void mulps(XMMRegister dst, const Operand& src);
1017af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void divps(XMMRegister dst, XMMRegister src);
1018af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void divps(XMMRegister dst, const Operand& src);
1019ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org
1020ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void movmskps(Register dst, XMMRegister src);
1021ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org
10223e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // SSE2 instructions
1023357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org  void movd(XMMRegister dst, Register src);
1024ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  void movd(Register dst, XMMRegister src);
1025ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  void movq(XMMRegister dst, Register src);
1026ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  void movq(Register dst, XMMRegister src);
1027160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  void movq(XMMRegister dst, XMMRegister src);
1028357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org
1029160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  // Don't use this unless it's important to keep the
1030160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  // top half of the destination register unchanged.
1031160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  // Used movaps when moving double values and movq for integer
1032160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  // values in xmm registers.
1033357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org  void movsd(XMMRegister dst, XMMRegister src);
1034160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
1035160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  void movsd(const Operand& dst, XMMRegister src);
1036357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org  void movsd(XMMRegister dst, const Operand& src);
10373e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
10380ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void movdqa(const Operand& dst, XMMRegister src);
10390ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void movdqa(XMMRegister dst, const Operand& src);
10400ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
1041e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  void movdqu(const Operand& dst, XMMRegister src);
1042e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  void movdqu(XMMRegister dst, const Operand& src);
1043e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
1044160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  void movapd(XMMRegister dst, XMMRegister src);
104540b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org
1046ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org  void psllq(XMMRegister reg, byte imm8);
1047ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org
10489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void cvttsd2si(Register dst, const Operand& src);
10490a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  void cvttsd2si(Register dst, XMMRegister src);
1050dff694e8cc18aa9640e92962de2699b9d07a7690vegorov@chromium.org  void cvttsd2siq(Register dst, XMMRegister src);
1051a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  void cvttsd2siq(Register dst, const Operand& src);
10529085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
10533e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cvtlsi2sd(XMMRegister dst, const Operand& src);
10543e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cvtlsi2sd(XMMRegister dst, Register src);
10553e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cvtqsi2sd(XMMRegister dst, const Operand& src);
10563e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cvtqsi2sd(XMMRegister dst, Register src);
10579085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
105840b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org
1059357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org  void cvtss2sd(XMMRegister dst, XMMRegister src);
106040b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  void cvtss2sd(XMMRegister dst, const Operand& src);
106140b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  void cvtsd2ss(XMMRegister dst, XMMRegister src);
106240b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org
106340b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  void cvtsd2si(Register dst, XMMRegister src);
106440b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  void cvtsd2siq(Register dst, XMMRegister src);
1065357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org
10669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void addsd(XMMRegister dst, XMMRegister src);
10671f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  void addsd(XMMRegister dst, const Operand& src);
10689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void subsd(XMMRegister dst, XMMRegister src);
10699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void mulsd(XMMRegister dst, XMMRegister src);
10701f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  void mulsd(XMMRegister dst, const Operand& src);
10719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void divsd(XMMRegister dst, XMMRegister src);
10729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
10735d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  void andpd(XMMRegister dst, XMMRegister src);
10745d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  void orpd(XMMRegister dst, XMMRegister src);
10755c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void xorpd(XMMRegister dst, XMMRegister src);
10764111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org  void sqrtsd(XMMRegister dst, XMMRegister src);
10777e6132b924829c353864933f29124419916db550machenbach@chromium.org  void sqrtsd(XMMRegister dst, const Operand& src);
10785c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10795c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void ucomisd(XMMRegister dst, XMMRegister src);
108040b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  void ucomisd(XMMRegister dst, const Operand& src);
1081ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void cmpltsd(XMMRegister dst, XMMRegister src);
1082ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org
1083ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void movmskpd(Register dst, XMMRegister src);
1084ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org
1085ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  // SSE 4.1 instruction
1086ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void extractps(Register dst, XMMRegister src, byte imm8);
10873e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
1088160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  enum RoundingMode {
1089160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    kRoundToNearest = 0x0,
1090160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    kRoundDown      = 0x1,
1091160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    kRoundUp        = 0x2,
1092160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    kRoundToZero    = 0x3
1093160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  };
1094160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
1095160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode);
1096160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
10979085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Debugging
10989085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void Print();
10999085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11009085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Check the code size generated from label to here.
11014f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  int SizeOfCodeGeneratedSince(Label* label) {
11024f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    return pc_offset() - label->pos();
11034f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
11049085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Mark address of the ExitJSFrame code.
11069085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void RecordJSReturn();
11079085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11082356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org  // Mark address of a debug break slot.
11092356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org  void RecordDebugBreakSlot();
11102356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org
11119085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Record a comment relocation entry that can be used by a disassembler.
1112a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Use --code-comments to enable.
11133a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  void RecordComment(const char* msg, bool force = false);
11149085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1115763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  // Allocate a constant pool of the correct size for the generated code.
11169fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org  Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate);
1117763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org
1118763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  // Generate the constant pool for the generated code.
1119763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void PopulateConstantPool(ConstantPoolArray* constant_pool);
1120763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org
1121a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Writes a single word of data in the code stream.
1122a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Used for inline tables, e.g., jump-tables.
11230511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  void db(uint8_t data);
1124a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  void dd(uint32_t data);
1125a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
1126f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org  PositionsRecorder* positions_recorder() { return &positions_recorder_; }
11279085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11289085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Check if there is less than kGap bytes available in the buffer.
11299085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // If this is the case, we need to grow the buffer before emitting
11309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // an instruction or relocation information.
11314af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  inline bool buffer_overflow() const {
11324af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org    return pc_ >= reloc_info_writer.pos() - kGap;
11334af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
11349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Get the number of bytes available in the buffer.
1136c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  inline int available_space() const {
1137c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    return static_cast<int>(reloc_info_writer.pos() - pc_);
1138c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  }
11399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
114064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  static bool IsNop(Address addr);
11412356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org
11429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Avoid overflows for displacements etc.
11439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  static const int kMaximalBufferSize = 512*MB;
11449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1145c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  byte byte_at(int pos)  { return buffer_[pos]; }
1146c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
1147c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1148f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org protected:
1149f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Call near indirect
1150f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void call(const Operand& operand);
1151f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1152f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Jump near absolute indirect (m64)
1153f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void jmp(const Operand& src);
1154f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
11559085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private:
11569085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  byte* addr_at(int pos)  { return buffer_ + pos; }
11579085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  uint32_t long_at(int pos)  {
11589085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    return *reinterpret_cast<uint32_t*>(addr_at(pos));
11599085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
11609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void long_at_put(int pos, uint32_t x)  {
11619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
11629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
11639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // code emission
11659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void GrowBuffer();
1166755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1167755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void emit(byte x) { *pc_++ = x; }
1168755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  inline void emitl(uint32_t x);
1169fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  inline void emitp(void* x, RelocInfo::Mode rmode);
1170c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  inline void emitq(uint64_t x);
1171e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emitw(uint16_t x);
11728e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  inline void emit_code_target(Handle<Code> target,
11738e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org                               RelocInfo::Mode rmode,
1174471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org                               TypeFeedbackId ast_id = TypeFeedbackId::None());
11756e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  inline void emit_runtime_entry(Address entry, RelocInfo::Mode rmode);
1176755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void emit(Immediate x) { emitl(x.value_); }
11779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
117871affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // Emits a REX prefix that encodes a 64-bit operand size and
117971affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // the top bit of both register codes.
1180755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1181755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // REX.W is set.
11823e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  inline void emit_rex_64(XMMRegister reg, Register rm_reg);
1183ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  inline void emit_rex_64(Register reg, XMMRegister rm_reg);
1184ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  inline void emit_rex_64(Register reg, Register rm_reg);
118571affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org
118671affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // Emits a REX prefix that encodes a 64-bit operand size and
118771affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // the top bit of the destination, index, and base register codes.
1188755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // The high bit of reg is used for REX.R, the high bit of op's base
1189755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // register is used for REX.B, and the high bit of op's index register
1190755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // is used for REX.X.  REX.W is set.
119171affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  inline void emit_rex_64(Register reg, const Operand& op);
11923e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  inline void emit_rex_64(XMMRegister reg, const Operand& op);
1193e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1194e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emits a REX prefix that encodes a 64-bit operand size and
1195e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // the top bit of the register code.
1196e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // The high bit of register is used for REX.B.
1197e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // REX.W is set and REX.R and REX.X are clear.
1198e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emit_rex_64(Register rm_reg);
1199e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1200e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emits a REX prefix that encodes a 64-bit operand size and
1201e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // the top bit of the index and base register codes.
1202e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // The high bit of op's base register is used for REX.B, and the high
1203e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // bit of op's index register is used for REX.X.
1204e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // REX.W is set and REX.R clear.
1205e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emit_rex_64(const Operand& op);
1206e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1207e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emit a REX prefix that only sets REX.W to choose a 64-bit operand size.
1208e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void emit_rex_64() { emit(0x48); }
1209755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1210755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1211e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // REX.W is clear.
1212755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  inline void emit_rex_32(Register reg, Register rm_reg);
1213755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1214755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // The high bit of reg is used for REX.R, the high bit of op's base
1215755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // register is used for REX.B, and the high bit of op's index register
1216755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // is used for REX.X.  REX.W is cleared.
1217755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  inline void emit_rex_32(Register reg, const Operand& op);
1218755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1219e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // High bit of rm_reg goes to REX.B.
1220e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // REX.W, REX.R and REX.X are clear.
1221e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emit_rex_32(Register rm_reg);
1222e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1223e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // High bit of base goes to REX.B and high bit of index to REX.X.
1224e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // REX.W and REX.R are clear.
1225e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emit_rex_32(const Operand& op);
1226e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1227755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1228755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // REX.W is cleared.  If no REX bits are set, no byte is emitted.
1229755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  inline void emit_optional_rex_32(Register reg, Register rm_reg);
1230755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1231755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // The high bit of reg is used for REX.R, the high bit of op's base
1232755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // register is used for REX.B, and the high bit of op's index register
1233755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // is used for REX.X.  REX.W is cleared.  If no REX bits are set, nothing
1234755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // is emitted.
1235755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  inline void emit_optional_rex_32(Register reg, const Operand& op);
1236755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
12373e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // As for emit_optional_rex_32(Register, Register), except that
12383e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // the registers are XMM registers.
12393e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  inline void emit_optional_rex_32(XMMRegister reg, XMMRegister base);
12403e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
12413e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // As for emit_optional_rex_32(Register, Register), except that
1242ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // one of the registers is an XMM registers.
12433e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  inline void emit_optional_rex_32(XMMRegister reg, Register base);
12443e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
1245ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // As for emit_optional_rex_32(Register, Register), except that
1246ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // one of the registers is an XMM registers.
1247ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  inline void emit_optional_rex_32(Register reg, XMMRegister base);
1248ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
12493e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // As for emit_optional_rex_32(Register, const Operand&), except that
12503e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // the register is an XMM register.
12513e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  inline void emit_optional_rex_32(XMMRegister reg, const Operand& op);
12523e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
1253e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Optionally do as emit_rex_32(Register) if the register number has
1254e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // the high bit set.
1255e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emit_optional_rex_32(Register rm_reg);
1256e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1257e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Optionally do as emit_rex_32(const Operand&) if the operand register
1258e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // numbers have a high bit set.
1259e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emit_optional_rex_32(const Operand& op);
1260e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1261895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_rex(int size) {
1262895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    if (size == kInt64Size) {
1263895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org      emit_rex_64();
1264895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    } else {
1265e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(size == kInt32Size);
1266895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    }
1267895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1268895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1269ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  template<class P1>
1270ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  void emit_rex(P1 p1, int size) {
1271ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org    if (size == kInt64Size) {
1272ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org      emit_rex_64(p1);
1273ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org    } else {
1274e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(size == kInt32Size);
1275ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org      emit_optional_rex_32(p1);
1276ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org    }
1277ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  }
1278ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org
1279ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  template<class P1, class P2>
1280ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  void emit_rex(P1 p1, P2 p2, int size) {
1281ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org    if (size == kInt64Size) {
1282ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org      emit_rex_64(p1, p2);
1283ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org    } else {
1284e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(size == kInt32Size);
1285ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org      emit_optional_rex_32(p1, p2);
1286ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org    }
1287ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  }
1288e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1289e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emit the ModR/M byte, and optionally the SIB byte and
1290755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // 1- or 4-byte offset for a memory operand.  Also encodes
1291755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // the second operand of the operation, a register or operation
1292e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // subcode, into the reg field of the ModR/M byte.
1293e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void emit_operand(Register reg, const Operand& adr) {
12945aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org    emit_operand(reg.low_bits(), adr);
1295e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  }
1296e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1297e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emit the ModR/M byte, and optionally the SIB byte and
1298e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // 1- or 4-byte offset for a memory operand.  Also used to encode
1299e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // a three-bit opcode extension into the ModR/M byte.
1300e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void emit_operand(int rm, const Operand& adr);
1301e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1302e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emit a ModR/M byte with registers coded in the reg and rm_reg fields.
1303e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void emit_modrm(Register reg, Register rm_reg) {
13045aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org    emit(0xC0 | reg.low_bits() << 3 | rm_reg.low_bits());
1305e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  }
1306e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1307e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emit a ModR/M byte with an operation subcode in the reg field and
1308e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // a register in the rm_reg field.
1309e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void emit_modrm(int code, Register rm_reg) {
1310e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(is_uint3(code));
13115aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org    emit(0xC0 | code << 3 | rm_reg.low_bits());
1312755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
131371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org
13149085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Emit the code-object-relative offset of the label's position
13159085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  inline void emit_code_relative_offset(Label* label);
13169085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1317ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  // The first argument is the reg field, the second argument is the r/m field.
1318ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void emit_sse_operand(XMMRegister dst, XMMRegister src);
1319ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void emit_sse_operand(XMMRegister reg, const Operand& adr);
1320a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  void emit_sse_operand(Register reg, const Operand& adr);
1321ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void emit_sse_operand(XMMRegister dst, Register src);
1322ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void emit_sse_operand(Register dst, XMMRegister src);
1323ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org
1324755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Emit machine code for one of the operations ADD, ADC, SUB, SBC,
1325755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // AND, OR, XOR, or CMP.  The encodings of these operations are all
1326755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // similar, differing just in the opcode or in the reg field of the
1327e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // ModR/M byte.
13282f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void arithmetic_op_8(byte opcode, Register reg, Register rm_reg);
13292f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void arithmetic_op_8(byte opcode, Register reg, const Operand& rm_reg);
1330911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void arithmetic_op_16(byte opcode, Register reg, Register rm_reg);
1331911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg);
13322f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  // Operate on operands/registers with pointer size, 32-bit or 64-bit size.
13332f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void arithmetic_op(byte opcode, Register reg, Register rm_reg, int size);
13342f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void arithmetic_op(byte opcode,
13352f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                     Register reg,
13362f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                     const Operand& rm_reg,
13372f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                     int size);
13383e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // Operate on a byte in memory or register.
1339eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void immediate_arithmetic_op_8(byte subcode,
1340911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                 Register dst,
13413e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org                                 Immediate src);
13423e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void immediate_arithmetic_op_8(byte subcode,
1343911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                 const Operand& dst,
13443e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org                                 Immediate src);
1345911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  // Operate on a word in memory or register.
1346911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void immediate_arithmetic_op_16(byte subcode,
1347911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                  Register dst,
1348911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                  Immediate src);
1349911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void immediate_arithmetic_op_16(byte subcode,
1350911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                  const Operand& dst,
1351911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                  Immediate src);
13522f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  // Operate on operands/registers with pointer size, 32-bit or 64-bit size.
13532f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void immediate_arithmetic_op(byte subcode,
13542f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                               Register dst,
13552f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                               Immediate src,
13562f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                               int size);
13572f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void immediate_arithmetic_op(byte subcode,
13582f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                               const Operand& dst,
13592f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                               Immediate src,
13602f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                               int size);
1361911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
1362e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emit machine code for a shift operation.
13632f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void shift(Register dst, Immediate shift_amount, int subcode, int size);
1364e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Shift dst by cl % 64 bits.
13652f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void shift(Register dst, int subcode, int size);
13669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13675aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void emit_farith(int b1, int b2, int i);
13689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // labels
1370eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // void print(Label* L);
13719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void bind_to(Label* L, int pos);
13729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13739085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // record reloc info for current pc_
13749085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
13759085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1376fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  // Arithmetics
1377fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_add(Register dst, Register src, int size) {
13782f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x03, dst, src, size);
1379fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
1380fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
1381fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_add(Register dst, Immediate src, int size) {
13822f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x0, dst, src, size);
1383fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
1384fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
1385fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_add(Register dst, const Operand& src, int size) {
13862f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x03, dst, src, size);
1387fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
1388fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
1389fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_add(const Operand& dst, Register src, int size) {
13902f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x1, src, dst, size);
1391fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
1392fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
1393fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_add(const Operand& dst, Immediate src, int size) {
13942f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x0, dst, src, size);
1395fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
1396fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
1397895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_and(Register dst, Register src, int size) {
13982f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x23, dst, src, size);
1399895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1400895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1401895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_and(Register dst, const Operand& src, int size) {
14022f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x23, dst, src, size);
1403895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1404895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1405895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_and(const Operand& dst, Register src, int size) {
14062f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x21, src, dst, size);
1407895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1408895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1409895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_and(Register dst, Immediate src, int size) {
14102f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x4, dst, src, size);
1411895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1412895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1413895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_and(const Operand& dst, Immediate src, int size) {
14142f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x4, dst, src, size);
1415895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1416895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
14177a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_cmp(Register dst, Register src, int size) {
14182f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x3B, dst, src, size);
14197a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  }
14207a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org
14217a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_cmp(Register dst, const Operand& src, int size) {
14222f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x3B, dst, src, size);
14237a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  }
14247a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org
14257a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_cmp(const Operand& dst, Register src, int size) {
14262f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x39, src, dst, size);
14277a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  }
14287a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org
14297a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_cmp(Register dst, Immediate src, int size) {
14302f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x7, dst, src, size);
14317a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  }
14327a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org
14337a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_cmp(const Operand& dst, Immediate src, int size) {
14342f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x7, dst, src, size);
14357a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  }
14367a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org
14377a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_dec(Register dst, int size);
14387a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_dec(const Operand& dst, int size);
14397a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org
1440fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  // Divide rdx:rax by src.  Quotient in rax, remainder in rdx when size is 64.
1441fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  // Divide edx:eax by lower 32 bits of src.  Quotient in eax, remainder in edx
1442fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  // when size is 32.
1443fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_idiv(Register src, int size);
14447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void emit_div(Register src, int size);
1445fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
1446fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  // Signed multiply instructions.
1447fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  // rdx:rax = rax * src when size is 64 or edx:eax = eax * src when size is 32.
1448fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_imul(Register src, int size);
1449fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_imul(Register dst, Register src, int size);
1450fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_imul(Register dst, const Operand& src, int size);
1451fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_imul(Register dst, Register src, Immediate imm, int size);
1452fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
14537a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_inc(Register dst, int size);
14547a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_inc(const Operand& dst, int size);
14557a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org
1456895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_lea(Register dst, const Operand& src, int size);
1457895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
14587a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_mov(Register dst, const Operand& src, int size);
14597a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_mov(Register dst, Register src, int size);
14607a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_mov(const Operand& dst, Register src, int size);
14617a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_mov(Register dst, Immediate value, int size);
14627a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_mov(const Operand& dst, Immediate value, int size);
14637a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org
1464895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_movzxb(Register dst, const Operand& src, int size);
14657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void emit_movzxb(Register dst, Register src, int size);
1466895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_movzxw(Register dst, const Operand& src, int size);
1467895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_movzxw(Register dst, Register src, int size);
1468895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
14697a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_neg(Register dst, int size);
14707a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_neg(const Operand& dst, int size);
14717a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org
1472895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_not(Register dst, int size);
1473895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_not(const Operand& dst, int size);
1474895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1475895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_or(Register dst, Register src, int size) {
14762f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x0B, dst, src, size);
1477895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1478895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1479895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_or(Register dst, const Operand& src, int size) {
14802f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x0B, dst, src, size);
1481895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1482895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1483895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_or(const Operand& dst, Register src, int size) {
14842f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x9, src, dst, size);
1485895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1486895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1487895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_or(Register dst, Immediate src, int size) {
14882f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x1, dst, src, size);
1489895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1490895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1491895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_or(const Operand& dst, Immediate src, int size) {
14922f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x1, dst, src, size);
1493895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1494895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1495895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_repmovs(int size);
1496895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
14977a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_sbb(Register dst, Register src, int size) {
14982f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x1b, dst, src, size);
14997a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  }
15007a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org
1501fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_sub(Register dst, Register src, int size) {
15022f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x2B, dst, src, size);
1503fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
1504fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
1505fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_sub(Register dst, Immediate src, int size) {
15062f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x5, dst, src, size);
1507fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
1508fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
1509fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_sub(Register dst, const Operand& src, int size) {
15102f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x2B, dst, src, size);
1511fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
1512fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
1513fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_sub(const Operand& dst, Register src, int size) {
15142f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x29, src, dst, size);
1515fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
1516fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
1517fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_sub(const Operand& dst, Immediate src, int size) {
15182f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x5, dst, src, size);
1519fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
1520fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
15217a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_test(Register dst, Register src, int size);
15227a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_test(Register reg, Immediate mask, int size);
15237a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_test(const Operand& op, Register reg, int size);
15247a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_test(const Operand& op, Immediate mask, int size);
15257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void emit_test(Register reg, const Operand& op, int size) {
15267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return emit_test(op, reg, size);
15277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1528ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org
1529895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_xchg(Register dst, Register src, int size);
15307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void emit_xchg(Register dst, const Operand& src, int size);
1531895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1532895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_xor(Register dst, Register src, int size) {
15332f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    if (size == kInt64Size && dst.code() == src.code()) {
15342f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
15352f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    // there is no need to make this a 64 bit operation.
15362f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org      arithmetic_op(0x33, dst, src, kInt32Size);
1537895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    } else {
15382f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org      arithmetic_op(0x33, dst, src, size);
1539895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    }
1540895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1541895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1542895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_xor(Register dst, const Operand& src, int size) {
15432f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x33, dst, src, size);
1544895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1545895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1546895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_xor(Register dst, Immediate src, int size) {
15472f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x6, dst, src, size);
1548895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1549895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1550895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_xor(const Operand& dst, Immediate src, int size) {
15512f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x6, dst, src, size);
1552895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1553895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1554895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_xor(const Operand& dst, Register src, int size) {
15552f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x31, src, dst, size);
1556895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1557895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
15589085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  friend class CodePatcher;
15599085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  friend class EnsureSpace;
1560911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  friend class RegExpMacroAssemblerX64;
15619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // code generation
15639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  RelocInfoWriter reloc_info_writer;
15649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1565c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  List< Handle<Code> > code_targets_;
15669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1567f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org  PositionsRecorder positions_recorder_;
1568f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org  friend class PositionsRecorder;
15699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
15709085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Helper class that ensures that there is enough space for generating
15739085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// instructions and relocation information.  The constructor makes
15749085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// sure that there is enough space and (in debug mode) the destructor
15759085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// checks that we did not generate too much.
15769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgclass EnsureSpace BASE_EMBEDDED {
15779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org public:
15789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
15794af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org    if (assembler_->buffer_overflow()) assembler_->GrowBuffer();
15809085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#ifdef DEBUG
15819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    space_before_ = assembler_->available_space();
15829085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#endif
15839085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
15849085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15859085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#ifdef DEBUG
15869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  ~EnsureSpace() {
15879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    int bytes_generated = space_before_ - assembler_->available_space();
1588e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(bytes_generated < assembler_->kGap);
15899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
15909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#endif
15919085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15929085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private:
15939085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  Assembler* assembler_;
15949085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#ifdef DEBUG
15959085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  int space_before_;
15969085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#endif
15979085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
15989085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15999085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org} }  // namespace v8::internal
16005ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org
16019085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#endif  // V8_X64_ASSEMBLER_X64_H_
1602