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) {
87a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    ASSERT(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) {
93a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    ASSERT(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 {
1199085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    ASSERT(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) {
204a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    ASSERT(reg.code() != 0);
205a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    return reg.code() - 1;
206a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
207a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
208c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org  static XMMRegister FromAllocationIndex(int index) {
209a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    ASSERT(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) {
215a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    ASSERT(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) {
237c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ASSERT(code >= 0);
23894b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org    ASSERT(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 {
2459085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    ASSERT(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) {
36104a34e6171ac922cb1a4c5162cf471809c468ad0machenbach@chromium.org    ASSERT(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
440fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org#define ASSEMBLER_INSTRUCTION_LIST(V)   \
441fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  V(add)                                \
442895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  V(and)                                \
4437a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  V(cmp)                                \
4447a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  V(dec)                                \
445fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  V(idiv)                               \
446fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  V(imul)                               \
4477a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  V(inc)                                \
448895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  V(lea)                                \
449fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  V(mov)                                \
450895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  V(movzxb)                             \
451895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  V(movzxw)                             \
4527a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  V(neg)                                \
453895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  V(not)                                \
454895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  V(or)                                 \
455895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  V(repmovs)                            \
4567a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  V(sbb)                                \
4577a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  V(sub)                                \
458895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  V(test)                               \
459895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  V(xchg)                               \
460895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  V(xor)
461ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org
462ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org
4632f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org// Shift instructions on operands/registers with kPointerSize, kInt32Size and
4642f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org// kInt64Size.
4652f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org#define SHIFT_INSTRUCTION_LIST(V)       \
4662f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  V(rol, 0x0)                           \
4672f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  V(ror, 0x1)                           \
4682f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  V(rcl, 0x2)                           \
4692f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  V(rcr, 0x3)                           \
4702f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  V(shl, 0x4)                           \
4712f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  V(shr, 0x5)                           \
4722f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  V(sar, 0x7)                           \
4732f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org
4742f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org
475ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgclass Assembler : public AssemblerBase {
4769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private:
4773e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // We check before assembling an instruction that there is sufficient
4783e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // space to write an instruction and its relocation information.
4793e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // The relocation writer's position must be kGap bytes above the end of
4809085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // the generated instructions. This leaves enough space for the
4813e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // longest possible x64 instruction, 15 bytes, and the longest possible
4823e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
4833e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // (There is a 15 byte limit on x64 instruction length that rules out some
4843e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // otherwise valid instructions.)
4853e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // This allows for a single, fast space check per instruction.
4869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  static const int kGap = 32;
4879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
4889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org public:
4899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Create an assembler. Instructions and relocation information are emitted
4909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // into a buffer, with the instructions starting from the beginning and the
4919085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // relocation information starting from the end of the buffer. See CodeDesc
4929085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // for a detailed comment on the layout (globals.h).
4939085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  //
4949085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // If the provided buffer is NULL, the assembler allocates and grows its own
4959085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // buffer, and buffer_size determines the initial buffer size. The buffer is
4969085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // owned by the assembler and deallocated upon destruction of the assembler.
4979085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  //
4989085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // If the provided buffer is not NULL, the assembler uses the provided buffer
4999085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // for code generation and assumes its size to be buffer_size. If the buffer
5009085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // is too small, a fatal error occurs. No deallocation of the buffer is done
5019085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // upon destruction of the assembler.
502c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  Assembler(Isolate* isolate, void* buffer, int buffer_size);
5038e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  virtual ~Assembler() { }
5049085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
5059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // GetCode emits any pending (non-emitted) code and fills the descriptor
5069085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // desc. GetCode() is idempotent; it returns the same result if no other
5079085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Assembler functions are invoked in between GetCode() calls.
5089085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void GetCode(CodeDesc* desc);
5099085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
510c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // Read/Modify the code target in the relative branch/call instruction at pc.
511c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // On the x64 architecture, we use relative jumps with a 32-bit displacement
512c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // to jump to other Code objects in the Code space in the heap.
513c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // Jumps to C functions are done indirectly through a 64-bit register holding
514c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // the absolute address of the target.
515c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // These functions convert between absolute Addresses of Code objects and
516c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // the relative displacements stored in the code.
51797b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  static inline Address target_address_at(Address pc,
51897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org                                          ConstantPoolArray* constant_pool);
51997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  static inline void set_target_address_at(Address pc,
52097b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org                                           ConstantPoolArray* constant_pool,
5216a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                           Address target,
5226a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                           ICacheFlushMode icache_flush_mode =
5236a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                               FLUSH_ICACHE_IF_NEEDED) ;
52497b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  static inline Address target_address_at(Address pc, Code* code) {
52597b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
52697b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    return target_address_at(pc, constant_pool);
52797b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  }
52897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  static inline void set_target_address_at(Address pc,
52997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org                                           Code* code,
5306a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                           Address target,
5316a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                           ICacheFlushMode icache_flush_mode =
5326a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                               FLUSH_ICACHE_IF_NEEDED) {
53397b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
5346a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org    set_target_address_at(pc, constant_pool, target, icache_flush_mode);
53597b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  }
536c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org
53789e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  // Return the code target address at a call site from the return address
53889e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  // of that call in the instruction stream.
53989e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  static inline Address target_address_from_return_address(Address pc);
54089e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org
5413811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // This sets the branch destination (which is in the instruction on x64).
542c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  // This is for calls and branches within generated code.
54388aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org  inline static void deserialization_set_special_target_at(
54497b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org      Address instruction_payload, Code* code, Address target) {
54597b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    set_target_address_at(instruction_payload, code, target);
5463811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  }
547c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org
548af4fba3c6d2a18866505de3e6798757dd1448c6dmachenbach@chromium.org  static inline RelocInfo::Mode RelocInfoNone() {
549af4fba3c6d2a18866505de3e6798757dd1448c6dmachenbach@chromium.org    if (kPointerSize == kInt64Size) {
550af4fba3c6d2a18866505de3e6798757dd1448c6dmachenbach@chromium.org      return RelocInfo::NONE64;
551af4fba3c6d2a18866505de3e6798757dd1448c6dmachenbach@chromium.org    } else {
552af4fba3c6d2a18866505de3e6798757dd1448c6dmachenbach@chromium.org      ASSERT(kPointerSize == kInt32Size);
553af4fba3c6d2a18866505de3e6798757dd1448c6dmachenbach@chromium.org      return RelocInfo::NONE32;
554af4fba3c6d2a18866505de3e6798757dd1448c6dmachenbach@chromium.org    }
555af4fba3c6d2a18866505de3e6798757dd1448c6dmachenbach@chromium.org  }
556af4fba3c6d2a18866505de3e6798757dd1448c6dmachenbach@chromium.org
557c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  inline Handle<Object> code_target_object_handle_at(Address pc);
5586e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  inline Address runtime_entry_at(Address pc);
5593811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // Number of bytes taken up by the branch target in the code.
56088aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org  static const int kSpecialTargetSize = 4;  // Use 32-bit displacement.
5619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Distance between the address of the code target in the call instruction
562c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // and the return address pushed on the stack.
563c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  static const int kCallTargetAddressOffset = 4;  // Use 32-bit displacement.
564594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // The length of call(kScratchRegister).
565594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kCallScratchRegisterInstructionLength = 3;
566594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // The length of call(Immediate32).
567abafe3dbcc62abc040625a8356be42bbd0cf7608danno@chromium.org  static const int kShortCallInstructionLength = 5;
568594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // The length of movq(kScratchRegister, address).
569594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kMoveAddressIntoScratchRegisterInstructionLength =
570594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      2 + kPointerSize;
571594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // The length of movq(kScratchRegister, address) and call(kScratchRegister).
572594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kCallSequenceLength =
573594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      kMoveAddressIntoScratchRegisterInstructionLength +
574594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      kCallScratchRegisterInstructionLength;
575594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org
576594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // The js return and debug break slot must be able to contain an indirect
577594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // call sequence, some x64 JS code is padded with int3 to make it large
578594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // enough to hold an instruction when the debugger patches it.
579594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kJSReturnSequenceLength = kCallSequenceLength;
580594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kDebugBreakSlotLength = kCallSequenceLength;
581594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kPatchDebugBreakSlotReturnOffset = kCallTargetAddressOffset;
582594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // Distance between the start of the JS return sequence and where the
583594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // 32-bit displacement of a short call would be. The short call is from
584594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // SetDebugBreakAtIC from debug-x64.cc.
585594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kPatchReturnSequenceAddressOffset =
586594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      kJSReturnSequenceLength - kPatchDebugBreakSlotReturnOffset;
587594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // Distance between the start of the JS return sequence and where the
588594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // 32-bit displacement of a short call would be. The short call is from
589594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // SetDebugBreakAtIC from debug-x64.cc.
590594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kPatchDebugBreakSlotAddressOffset =
591594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      kDebugBreakSlotLength - kPatchDebugBreakSlotReturnOffset;
592594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  static const int kRealPatchReturnSequenceAddressOffset =
593594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      kMoveAddressIntoScratchRegisterInstructionLength - kPointerSize;
5942356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org
5955d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // One byte opcode for test eax,0xXXXXXXXX.
5965d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  static const byte kTestEaxByte = 0xA9;
597d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  // One byte opcode for test al, 0xXX.
598d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  static const byte kTestAlByte = 0xA8;
599496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  // One byte opcode for nop.
600496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  static const byte kNopByte = 0x90;
601496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
602496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  // One byte prefix for a short conditional jump.
603496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  static const byte kJccShortPrefix = 0x70;
604496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  static const byte kJncShortOpcode = kJccShortPrefix | not_carry;
605496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  static const byte kJcShortOpcode = kJccShortPrefix | carry;
606212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org  static const byte kJnzShortOpcode = kJccShortPrefix | not_zero;
607212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org  static const byte kJzShortOpcode = kJccShortPrefix | zero;
608496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
6092356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org
6109085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // ---------------------------------------------------------------------------
6119085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Code generation
6129085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  //
61371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // Function names correspond one-to-one to x64 instruction mnemonics.
61471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // Unless specified otherwise, instructions operate on 64-bit operands.
61571affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  //
61671affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // If we need versions of an assembly instruction that operate on different
61771affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // width arguments, we add a single-letter suffix specifying the width.
618eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // This is done for the following instructions: mov, cmp, inc, dec,
619eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // add, sub, and test.
62071affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // There are no versions of these instructions without the suffix.
62171affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'.
62271affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // - Instructions on 16-bit (word) operands/registers have a trailing 'w'.
62371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // - Instructions on 32-bit (doubleword) operands/registers use 'l'.
62471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // - Instructions on 64-bit (quadword) operands/registers use 'q'.
625895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  // - Instructions on operands/registers with pointer size use 'p'.
6269085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
6272f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  STATIC_ASSERT(kPointerSize == kInt64Size || kPointerSize == kInt32Size);
6282f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org
629ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org#define DECLARE_INSTRUCTION(instruction)                \
630fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  template<class P1>                                    \
631fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void instruction##p(P1 p1) {                          \
632fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org    emit_##instruction(p1, kPointerSize);               \
633fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }                                                     \
634fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                                        \
635fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  template<class P1>                                    \
636fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void instruction##l(P1 p1) {                          \
637fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org    emit_##instruction(p1, kInt32Size);                 \
638fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }                                                     \
639fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                                        \
640fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  template<class P1>                                    \
641fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void instruction##q(P1 p1) {                          \
642fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org    emit_##instruction(p1, kInt64Size);                 \
643fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }                                                     \
644fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                                        \
645ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  template<class P1, class P2>                          \
646ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  void instruction##p(P1 p1, P2 p2) {                   \
647ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org    emit_##instruction(p1, p2, kPointerSize);           \
648ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  }                                                     \
649ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org                                                        \
650ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  template<class P1, class P2>                          \
651ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  void instruction##l(P1 p1, P2 p2) {                   \
652ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org    emit_##instruction(p1, p2, kInt32Size);             \
653ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  }                                                     \
654ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org                                                        \
655ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  template<class P1, class P2>                          \
656ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  void instruction##q(P1 p1, P2 p2) {                   \
657ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org    emit_##instruction(p1, p2, kInt64Size);             \
658fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }                                                     \
659fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                                        \
660fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  template<class P1, class P2, class P3>                \
661fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void instruction##p(P1 p1, P2 p2, P3 p3) {            \
662fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org    emit_##instruction(p1, p2, p3, kPointerSize);       \
663fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }                                                     \
664fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                                        \
665fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  template<class P1, class P2, class P3>                \
666fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void instruction##l(P1 p1, P2 p2, P3 p3) {            \
667fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org    emit_##instruction(p1, p2, p3, kInt32Size);         \
668fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }                                                     \
669fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                                        \
670fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  template<class P1, class P2, class P3>                \
671fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void instruction##q(P1 p1, P2 p2, P3 p3) {            \
672fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org    emit_##instruction(p1, p2, p3, kInt64Size);         \
673ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  }
674ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  ASSEMBLER_INSTRUCTION_LIST(DECLARE_INSTRUCTION)
675ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org#undef DECLARE_INSTRUCTION
676ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org
6779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Insert the smallest number of nop instructions
6789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // possible to align the pc offset to a multiple
67983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // of m, where m must be a power of 2.
6809085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void Align(int m);
68164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  void Nop(int bytes = 1);
6825ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  // Aligns code to something that's optimal for a jump target for the platform.
6835ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org  void CodeTargetAlign();
6849085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
6859085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Stack
686e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void pushfq();
687e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void popfq();
6889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
689763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void pushq(Immediate value);
6900ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // Push a 32 bit integer, and guarantee that it is actually pushed as a
6910ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // 32 bit value, the normal push will optimize the 8 bit case.
692763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void pushq_imm32(int32_t imm32);
693763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void pushq(Register src);
694763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void pushq(const Operand& src);
6959085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
696763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void popq(Register dst);
697763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void popq(const Operand& dst);
6989085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
699e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void enter(Immediate size);
7009085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void leave();
7019085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
7029085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Moves
703755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void movb(Register dst, const Operand& src);
704e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void movb(Register dst, Immediate imm);
705755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void movb(const Operand& dst, Register src);
706e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  void movb(const Operand& dst, Immediate imm);
707755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
7083811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // Move the low 16 bits of a 64-bit register value to a 16-bit
7093811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // memory location.
710e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  void movw(Register dst, const Operand& src);
7113811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void movw(const Operand& dst, Register src);
712e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  void movw(const Operand& dst, Immediate imm);
7133811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
714911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  // Move the offset of the label location relative to the current
715911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  // position (after the move) to the destination.
716911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void movl(const Operand& dst, Label* src);
717e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
718e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  // Loads a pointer into a register with a relocation mode.
7199cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org  void movp(Register dst, void* ptr, RelocInfo::Mode rmode);
7209cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org
721e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  // Loads a 64-bit immediate into a register.
722e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  void movq(Register dst, int64_t value);
723ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  void movq(Register dst, uint64_t value);
724755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
7252ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org  void movsxbl(Register dst, const Operand& src);
7263811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void movsxbq(Register dst, const Operand& src);
7272ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org  void movsxwl(Register dst, const Operand& src);
7283811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void movsxwq(Register dst, const Operand& src);
7295aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void movsxlq(Register dst, Register src);
7303e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void movsxlq(Register dst, const Operand& src);
7315aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
732b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Repeated moves.
733b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
734b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void repmovsb();
735b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void repmovsw();
736895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void repmovsp() { emit_repmovs(kPointerSize); }
737895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void repmovsl() { emit_repmovs(kInt32Size); }
738895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void repmovsq() { emit_repmovs(kInt64Size); }
739b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
740badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  // Instruction to load from an immediate 64-bit pointer into RAX.
741755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void load_rax(void* ptr, RelocInfo::Mode rmode);
742e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void load_rax(ExternalReference ext);
7439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
7443e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // Conditional moves.
7453e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cmovq(Condition cc, Register dst, Register src);
7463e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cmovq(Condition cc, Register dst, const Operand& src);
7473e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cmovl(Condition cc, Register dst, Register src);
7483e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cmovl(Condition cc, Register dst, const Operand& src);
7499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
7503e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cmpb(Register dst, Immediate src) {
7513e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org    immediate_arithmetic_op_8(0x7, dst, src);
7523e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  }
7533e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
754911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpb_al(Immediate src);
755911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
756911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpb(Register dst, Register src) {
7572f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op_8(0x3A, dst, src);
758911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
759911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
760911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpb(Register dst, const Operand& src) {
7612f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op_8(0x3A, dst, src);
762911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
763911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
764911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpb(const Operand& dst, Register src) {
7652f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op_8(0x38, src, dst);
766911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
767911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
768eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void cmpb(const Operand& dst, Immediate src) {
769eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org    immediate_arithmetic_op_8(0x7, dst, src);
770eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  }
771eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org
772911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpw(const Operand& dst, Immediate src) {
773911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org    immediate_arithmetic_op_16(0x7, dst, src);
774911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
775911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
776911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpw(Register 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, const Operand& src) {
781911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org    arithmetic_op_16(0x3B, dst, src);
782911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
783911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
784911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpw(Register dst, Register src) {
785911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org    arithmetic_op_16(0x3B, dst, src);
786911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
787911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
788911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void cmpw(const Operand& dst, Register src) {
789911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org    arithmetic_op_16(0x39, src, dst);
790911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
791911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
792b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void andb(Register dst, Immediate src) {
793b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    immediate_arithmetic_op_8(0x4, dst, src);
794b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
7959d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
7969d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void decb(Register dst);
7979d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void decb(const Operand& dst);
7989085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
799e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Sign-extends rax into rdx:rax.
800e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void cqo();
8010b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Sign-extends eax into edx:eax.
8020b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  void cdq();
8039085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
804e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Multiply rax by src, put the result in rdx:rax.
8059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void mul(Register src);
8069085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
8072f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org#define DECLARE_SHIFT_INSTRUCTION(instruction, subcode)     \
8082f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void instruction##p(Register dst, Immediate imm8) {       \
8092f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    shift(dst, imm8, subcode, kPointerSize);                \
8102f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  }                                                         \
8112f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                                                            \
8122f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void instruction##l(Register dst, Immediate imm8) {       \
8132f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    shift(dst, imm8, subcode, kInt32Size);                  \
8142f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  }                                                         \
8152f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                                                            \
8162f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void instruction##q(Register dst, Immediate imm8) {       \
8172f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    shift(dst, imm8, subcode, kInt64Size);                  \
8182f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  }                                                         \
8192f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                                                            \
8202f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void instruction##p_cl(Register dst) {                    \
8212f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    shift(dst, subcode, kPointerSize);                      \
8222f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  }                                                         \
8232f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                                                            \
8242f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void instruction##l_cl(Register dst) {                    \
8252f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    shift(dst, subcode, kInt32Size);                        \
8262f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  }                                                         \
8272f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                                                            \
8282f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void instruction##q_cl(Register dst) {                    \
8292f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    shift(dst, subcode, kInt64Size);                        \
8302f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  }
8312f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  SHIFT_INSTRUCTION_LIST(DECLARE_SHIFT_INSTRUCTION)
8322f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org#undef DECLARE_SHIFT_INSTRUCTION
833e4ee6de0de64744d55b63da83156827c989c7099verwaest@chromium.org
834e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Shifts dst:src left by cl bits, affecting only dst.
835e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void shld(Register dst, Register src);
836e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
837e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Shifts src:dst right by cl bits, affecting only dst.
838e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void shrd(Register dst, Register src);
839e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
840e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void store_rax(void* dst, RelocInfo::Mode mode);
841e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void store_rax(ExternalReference ref);
8429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
843911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void subb(Register dst, Immediate src) {
844911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org    immediate_arithmetic_op_8(0x5, dst, src);
845911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  }
846911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
8479d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void testb(Register dst, Register src);
848755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void testb(Register reg, Immediate mask);
849755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void testb(const Operand& op, Immediate mask);
850b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void testb(const Operand& op, Register reg);
851755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
8529085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Bit operations.
8539085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void bt(const Operand& dst, Register src);
8549085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void bts(const Operand& dst, Register src);
855f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void bsrl(Register dst, Register src);
8569085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
8579085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Miscellaneous
8589d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  void clc();
8597979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  void cld();
860eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void cpuid();
8619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void hlt();
8629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void int3();
8639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void nop();
8649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void ret(int imm16);
865eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void setcc(Condition cc, Register reg);
8669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
8679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Label operations & relative jumps (PPUM Appendix D)
8689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  //
8699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Takes a branch opcode (cc) and a label (L) and generates
8709085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // either a backward branch or a forward branch and links it
8719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // to the label fixup chain. Usage:
8729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  //
8739085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Label L;    // unbound label
8749085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // j(cc, &L);  // forward branch to unbound label
8759085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // bind(&L);   // bind label to the current pc
8769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // j(cc, &L);  // backward branch to bound label
8779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // bind(&L);   // illegal: a label may be bound only once
8789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  //
8799085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Note: The same Label can be used for forward and backward branches
8809085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // but it may be bound only once.
8819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
8829085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void bind(Label* L);  // binds an unbound label L to the current code position
8839085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
8849085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Calls
885e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Call near relative 32-bit displacement, relative to next instruction.
8869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void call(Label* L);
8876e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  void call(Address entry, RelocInfo::Mode rmode);
8888e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  void call(Handle<Code> target,
8894f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org            RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
890471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org            TypeFeedbackId ast_id = TypeFeedbackId::None());
891e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
89283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // Calls directly to the given address using a relative offset.
89383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // Should only ever be used in Code objects for calls within the
89483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // same Code object. Should not be used when generating new code (use labels),
89583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // but only when patching existing code.
89683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  void call(Address target);
89783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
898e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Call near absolute indirect, address in register
899e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void call(Register adr);
900e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
9019085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Jumps
902e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Jump short or near relative.
903c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // Use a 32-bit signed displacement.
90483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Unconditional jump to L
90583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void jmp(Label* L, Label::Distance distance = Label::kFar);
9066e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  void jmp(Address entry, RelocInfo::Mode rmode);
907c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  void jmp(Handle<Code> target, RelocInfo::Mode rmode);
908e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
909e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Jump near absolute indirect (r64)
910e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void jmp(Register adr);
9119085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9129085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Conditional jumps
91383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void j(Condition cc,
91483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org         Label* L,
91583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org         Label::Distance distance = Label::kFar);
9166e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  void j(Condition cc, Address entry, RelocInfo::Mode rmode);
917c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode);
9189085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9199085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Floating-point operations
9209085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fld(int i);
9219085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fld1();
9239085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fldz();
924ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  void fldpi();
925a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  void fldln2();
9269085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9279085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fld_s(const Operand& adr);
9289085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fld_d(const Operand& adr);
9299085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fstp_s(const Operand& adr);
9319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fstp_d(const Operand& adr);
9323811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void fstp(int index);
9339085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fild_s(const Operand& adr);
9359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fild_d(const Operand& adr);
9369085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fist_s(const Operand& adr);
9389085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fistp_s(const Operand& adr);
9409085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fistp_d(const Operand& adr);
9419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fisttp_s(const Operand& adr);
943b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void fisttp_d(const Operand& adr);
9449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9459085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fabs();
9469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fchs();
9479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fadd(int i);
9499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fsub(int i);
9509085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fmul(int i);
9519085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fdiv(int i);
9529085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9539085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fisub_s(const Operand& adr);
9549085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9559085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void faddp(int i = 1);
9569085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fsubp(int i = 1);
9579085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fsubrp(int i = 1);
9589085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fmulp(int i = 1);
9599085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fdivp(int i = 1);
9609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fprem();
9619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fprem1();
9629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fxch(int i = 1);
9649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fincstp();
9659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void ffree(int i = 0);
9669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void ftst();
9689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fucomp(int i);
9699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fucompp();
9703811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void fucomi(int i);
9713811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void fucomip();
9723811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
9739085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fcompp();
9749085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fnstsw_ax();
9759085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fwait();
9769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void fnclex();
9779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9785aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void fsin();
9795aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void fcos();
9801b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  void fptan();
981a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  void fyl2x();
98264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  void f2xm1();
98364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  void fscale();
98464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  void fninit();
9855aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
9869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void frndint();
9879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
9883e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void sahf();
9893e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
990ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  // SSE instructions
991ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void movaps(XMMRegister dst, XMMRegister src);
992ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void movss(XMMRegister dst, const Operand& src);
993ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void movss(const Operand& dst, XMMRegister src);
994af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void shufps(XMMRegister dst, XMMRegister src, byte imm8);
995ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org
996ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void cvttss2si(Register dst, const Operand& src);
997ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void cvttss2si(Register dst, XMMRegister src);
998ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void cvtlsi2ss(XMMRegister dst, Register src);
999ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org
1000ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void andps(XMMRegister dst, XMMRegister src);
1001af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void andps(XMMRegister dst, const Operand& src);
1002057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  void orps(XMMRegister dst, XMMRegister src);
1003af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void orps(XMMRegister dst, const Operand& src);
1004057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  void xorps(XMMRegister dst, XMMRegister src);
1005af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void xorps(XMMRegister dst, const Operand& src);
1006af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org
1007af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void addps(XMMRegister dst, XMMRegister src);
1008af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void addps(XMMRegister dst, const Operand& src);
1009af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void subps(XMMRegister dst, XMMRegister src);
1010af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void subps(XMMRegister dst, const Operand& src);
1011af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void mulps(XMMRegister dst, XMMRegister src);
1012af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void mulps(XMMRegister dst, const Operand& src);
1013af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void divps(XMMRegister dst, XMMRegister src);
1014af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  void divps(XMMRegister dst, const Operand& src);
1015ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org
1016ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void movmskps(Register dst, XMMRegister src);
1017ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org
10183e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // SSE2 instructions
1019357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org  void movd(XMMRegister dst, Register src);
1020ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  void movd(Register dst, XMMRegister src);
1021ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  void movq(XMMRegister dst, Register src);
1022ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  void movq(Register dst, XMMRegister src);
1023160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  void movq(XMMRegister dst, XMMRegister src);
1024357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org
1025160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  // Don't use this unless it's important to keep the
1026160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  // top half of the destination register unchanged.
1027160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  // Used movaps when moving double values and movq for integer
1028160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  // values in xmm registers.
1029357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org  void movsd(XMMRegister dst, XMMRegister src);
1030160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
1031160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  void movsd(const Operand& dst, XMMRegister src);
1032357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org  void movsd(XMMRegister dst, const Operand& src);
10333e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
10340ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void movdqa(const Operand& dst, XMMRegister src);
10350ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  void movdqa(XMMRegister dst, const Operand& src);
10360ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org
1037e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  void movdqu(const Operand& dst, XMMRegister src);
1038e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  void movdqu(XMMRegister dst, const Operand& src);
1039e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
1040160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  void movapd(XMMRegister dst, XMMRegister src);
104140b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org
1042ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org  void psllq(XMMRegister reg, byte imm8);
1043ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org
10449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void cvttsd2si(Register dst, const Operand& src);
10450a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  void cvttsd2si(Register dst, XMMRegister src);
1046dff694e8cc18aa9640e92962de2699b9d07a7690vegorov@chromium.org  void cvttsd2siq(Register dst, XMMRegister src);
10479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
10483e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cvtlsi2sd(XMMRegister dst, const Operand& src);
10493e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cvtlsi2sd(XMMRegister dst, Register src);
10503e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cvtqsi2sd(XMMRegister dst, const Operand& src);
10513e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void cvtqsi2sd(XMMRegister dst, Register src);
10529085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
105340b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org
1054357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org  void cvtss2sd(XMMRegister dst, XMMRegister src);
105540b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  void cvtss2sd(XMMRegister dst, const Operand& src);
105640b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  void cvtsd2ss(XMMRegister dst, XMMRegister src);
105740b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org
105840b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  void cvtsd2si(Register dst, XMMRegister src);
105940b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  void cvtsd2siq(Register dst, XMMRegister src);
1060357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org
10619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void addsd(XMMRegister dst, XMMRegister src);
10621f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  void addsd(XMMRegister dst, const Operand& src);
10639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void subsd(XMMRegister dst, XMMRegister src);
10649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void mulsd(XMMRegister dst, XMMRegister src);
10651f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org  void mulsd(XMMRegister dst, const Operand& src);
10669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void divsd(XMMRegister dst, XMMRegister src);
10679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
10685d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  void andpd(XMMRegister dst, XMMRegister src);
10695d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  void orpd(XMMRegister dst, XMMRegister src);
10705c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void xorpd(XMMRegister dst, XMMRegister src);
10714111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org  void sqrtsd(XMMRegister dst, XMMRegister src);
10727e6132b924829c353864933f29124419916db550machenbach@chromium.org  void sqrtsd(XMMRegister dst, const Operand& src);
10735c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10745c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void ucomisd(XMMRegister dst, XMMRegister src);
107540b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  void ucomisd(XMMRegister dst, const Operand& src);
1076ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void cmpltsd(XMMRegister dst, XMMRegister src);
1077ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org
1078ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void movmskpd(Register dst, XMMRegister src);
1079ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org
1080ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  // SSE 4.1 instruction
1081ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void extractps(Register dst, XMMRegister src, byte imm8);
10823e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
1083160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  enum RoundingMode {
1084160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    kRoundToNearest = 0x0,
1085160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    kRoundDown      = 0x1,
1086160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    kRoundUp        = 0x2,
1087160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    kRoundToZero    = 0x3
1088160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  };
1089160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
1090160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode);
1091160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
10929085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Debugging
10939085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void Print();
10949085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
10959085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Check the code size generated from label to here.
10964f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  int SizeOfCodeGeneratedSince(Label* label) {
10974f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    return pc_offset() - label->pos();
10984f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
10999085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11009085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Mark address of the ExitJSFrame code.
11019085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void RecordJSReturn();
11029085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11032356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org  // Mark address of a debug break slot.
11042356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org  void RecordDebugBreakSlot();
11052356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org
11069085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Record a comment relocation entry that can be used by a disassembler.
1107a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Use --code-comments to enable.
11083a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  void RecordComment(const char* msg, bool force = false);
11099085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1110763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  // Allocate a constant pool of the correct size for the generated code.
11119fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org  Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate);
1112763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org
1113763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  // Generate the constant pool for the generated code.
1114763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void PopulateConstantPool(ConstantPoolArray* constant_pool);
1115763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org
1116a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Writes a single word of data in the code stream.
1117a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Used for inline tables, e.g., jump-tables.
11180511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  void db(uint8_t data);
1119a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  void dd(uint32_t data);
1120a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
1121f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org  PositionsRecorder* positions_recorder() { return &positions_recorder_; }
11229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11239085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Check if there is less than kGap bytes available in the buffer.
11249085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // If this is the case, we need to grow the buffer before emitting
11259085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // an instruction or relocation information.
11264af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  inline bool buffer_overflow() const {
11274af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org    return pc_ >= reloc_info_writer.pos() - kGap;
11284af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  }
11299085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Get the number of bytes available in the buffer.
1131c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  inline int available_space() const {
1132c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    return static_cast<int>(reloc_info_writer.pos() - pc_);
1133c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  }
11349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
113564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  static bool IsNop(Address addr);
11362356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org
11379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Avoid overflows for displacements etc.
11389085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  static const int kMaximalBufferSize = 512*MB;
11399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1140c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  byte byte_at(int pos)  { return buffer_[pos]; }
1141c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
1142c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1143f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org protected:
1144f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Call near indirect
1145f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void call(const Operand& operand);
1146f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1147f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Jump near absolute indirect (m64)
1148f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void jmp(const Operand& src);
1149f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
11509085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private:
11519085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  byte* addr_at(int pos)  { return buffer_ + pos; }
11529085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  uint32_t long_at(int pos)  {
11539085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    return *reinterpret_cast<uint32_t*>(addr_at(pos));
11549085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
11559085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void long_at_put(int pos, uint32_t x)  {
11569085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
11579085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
11589085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
11599085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // code emission
11609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void GrowBuffer();
1161755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1162755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void emit(byte x) { *pc_++ = x; }
1163755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  inline void emitl(uint32_t x);
1164fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  inline void emitp(void* x, RelocInfo::Mode rmode);
1165c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  inline void emitq(uint64_t x);
1166e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emitw(uint16_t x);
11678e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  inline void emit_code_target(Handle<Code> target,
11688e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org                               RelocInfo::Mode rmode,
1169471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org                               TypeFeedbackId ast_id = TypeFeedbackId::None());
11706e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  inline void emit_runtime_entry(Address entry, RelocInfo::Mode rmode);
1171755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  void emit(Immediate x) { emitl(x.value_); }
11729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
117371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // Emits a REX prefix that encodes a 64-bit operand size and
117471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // the top bit of both register codes.
1175755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1176755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // REX.W is set.
11773e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  inline void emit_rex_64(XMMRegister reg, Register rm_reg);
1178ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  inline void emit_rex_64(Register reg, XMMRegister rm_reg);
1179ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  inline void emit_rex_64(Register reg, Register rm_reg);
118071affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org
118171affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // Emits a REX prefix that encodes a 64-bit operand size and
118271affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // the top bit of the destination, index, and base register codes.
1183755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // The high bit of reg is used for REX.R, the high bit of op's base
1184755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // register is used for REX.B, and the high bit of op's index register
1185755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // is used for REX.X.  REX.W is set.
118671affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  inline void emit_rex_64(Register reg, const Operand& op);
11873e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  inline void emit_rex_64(XMMRegister reg, const Operand& op);
1188e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1189e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emits a REX prefix that encodes a 64-bit operand size and
1190e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // the top bit of the register code.
1191e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // The high bit of register is used for REX.B.
1192e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // REX.W is set and REX.R and REX.X are clear.
1193e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emit_rex_64(Register rm_reg);
1194e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1195e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emits a REX prefix that encodes a 64-bit operand size and
1196e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // the top bit of the index and base register codes.
1197e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // The high bit of op's base register is used for REX.B, and the high
1198e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // bit of op's index register is used for REX.X.
1199e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // REX.W is set and REX.R clear.
1200e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emit_rex_64(const Operand& op);
1201e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1202e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emit a REX prefix that only sets REX.W to choose a 64-bit operand size.
1203e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void emit_rex_64() { emit(0x48); }
1204755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1205755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1206e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // REX.W is clear.
1207755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  inline void emit_rex_32(Register reg, Register rm_reg);
1208755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1209755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // The high bit of reg is used for REX.R, the high bit of op's base
1210755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // register is used for REX.B, and the high bit of op's index register
1211755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // is used for REX.X.  REX.W is cleared.
1212755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  inline void emit_rex_32(Register reg, const Operand& op);
1213755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1214e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // High bit of rm_reg goes to REX.B.
1215e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // REX.W, REX.R and REX.X are clear.
1216e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emit_rex_32(Register rm_reg);
1217e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1218e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // High bit of base goes to REX.B and high bit of index to REX.X.
1219e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // REX.W and REX.R are clear.
1220e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emit_rex_32(const Operand& op);
1221e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1222755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1223755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // REX.W is cleared.  If no REX bits are set, no byte is emitted.
1224755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  inline void emit_optional_rex_32(Register reg, Register rm_reg);
1225755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
1226755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // The high bit of reg is used for REX.R, the high bit of op's base
1227755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // register is used for REX.B, and the high bit of op's index register
1228755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // is used for REX.X.  REX.W is cleared.  If no REX bits are set, nothing
1229755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // is emitted.
1230755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  inline void emit_optional_rex_32(Register reg, const Operand& op);
1231755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org
12323e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // As for emit_optional_rex_32(Register, Register), except that
12333e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // the registers are XMM registers.
12343e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  inline void emit_optional_rex_32(XMMRegister reg, XMMRegister base);
12353e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
12363e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // As for emit_optional_rex_32(Register, Register), except that
1237ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // one of the registers is an XMM registers.
12383e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  inline void emit_optional_rex_32(XMMRegister reg, Register base);
12393e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
1240ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // As for emit_optional_rex_32(Register, Register), except that
1241ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  // one of the registers is an XMM registers.
1242ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  inline void emit_optional_rex_32(Register reg, XMMRegister base);
1243ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
12443e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // As for emit_optional_rex_32(Register, const Operand&), except that
12453e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // the register is an XMM register.
12463e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  inline void emit_optional_rex_32(XMMRegister reg, const Operand& op);
12473e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org
1248e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Optionally do as emit_rex_32(Register) if the register number has
1249e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // the high bit set.
1250e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emit_optional_rex_32(Register rm_reg);
1251e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1252e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Optionally do as emit_rex_32(const Operand&) if the operand register
1253e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // numbers have a high bit set.
1254e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  inline void emit_optional_rex_32(const Operand& op);
1255e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1256895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_rex(int size) {
1257895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    if (size == kInt64Size) {
1258895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org      emit_rex_64();
1259895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    } else {
1260895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org      ASSERT(size == kInt32Size);
1261895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    }
1262895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1263895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1264ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  template<class P1>
1265ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  void emit_rex(P1 p1, int size) {
1266ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org    if (size == kInt64Size) {
1267ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org      emit_rex_64(p1);
1268ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org    } else {
1269ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org      ASSERT(size == kInt32Size);
1270ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org      emit_optional_rex_32(p1);
1271ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org    }
1272ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  }
1273ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org
1274ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  template<class P1, class P2>
1275ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  void emit_rex(P1 p1, P2 p2, int size) {
1276ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org    if (size == kInt64Size) {
1277ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org      emit_rex_64(p1, p2);
1278ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org    } else {
1279ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org      ASSERT(size == kInt32Size);
1280ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org      emit_optional_rex_32(p1, p2);
1281ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org    }
1282ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  }
1283e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1284e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emit the ModR/M byte, and optionally the SIB byte and
1285755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // 1- or 4-byte offset for a memory operand.  Also encodes
1286755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // the second operand of the operation, a register or operation
1287e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // subcode, into the reg field of the ModR/M byte.
1288e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void emit_operand(Register reg, const Operand& adr) {
12895aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org    emit_operand(reg.low_bits(), adr);
1290e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  }
1291e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1292e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emit the ModR/M byte, and optionally the SIB byte and
1293e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // 1- or 4-byte offset for a memory operand.  Also used to encode
1294e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // a three-bit opcode extension into the ModR/M byte.
1295e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void emit_operand(int rm, const Operand& adr);
1296e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1297e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emit a ModR/M byte with registers coded in the reg and rm_reg fields.
1298e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void emit_modrm(Register reg, Register rm_reg) {
12995aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org    emit(0xC0 | reg.low_bits() << 3 | rm_reg.low_bits());
1300e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  }
1301e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org
1302e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emit a ModR/M byte with an operation subcode in the reg field and
1303e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // a register in the rm_reg field.
1304e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  void emit_modrm(int code, Register rm_reg) {
13055aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org    ASSERT(is_uint3(code));
13065aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org    emit(0xC0 | code << 3 | rm_reg.low_bits());
1307755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  }
130871affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org
13099085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // Emit the code-object-relative offset of the label's position
13109085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  inline void emit_code_relative_offset(Label* label);
13119085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1312ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  // The first argument is the reg field, the second argument is the r/m field.
1313ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void emit_sse_operand(XMMRegister dst, XMMRegister src);
1314ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void emit_sse_operand(XMMRegister reg, const Operand& adr);
1315ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void emit_sse_operand(XMMRegister dst, Register src);
1316ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  void emit_sse_operand(Register dst, XMMRegister src);
1317ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org
1318755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // Emit machine code for one of the operations ADD, ADC, SUB, SBC,
1319755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // AND, OR, XOR, or CMP.  The encodings of these operations are all
1320755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org  // similar, differing just in the opcode or in the reg field of the
1321e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // ModR/M byte.
13222f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void arithmetic_op_8(byte opcode, Register reg, Register rm_reg);
13232f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void arithmetic_op_8(byte opcode, Register reg, const Operand& rm_reg);
1324911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void arithmetic_op_16(byte opcode, Register reg, Register rm_reg);
1325911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg);
13262f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  // Operate on operands/registers with pointer size, 32-bit or 64-bit size.
13272f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void arithmetic_op(byte opcode, Register reg, Register rm_reg, int size);
13282f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void arithmetic_op(byte opcode,
13292f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                     Register reg,
13302f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                     const Operand& rm_reg,
13312f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                     int size);
13323e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  // Operate on a byte in memory or register.
1333eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  void immediate_arithmetic_op_8(byte subcode,
1334911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                 Register dst,
13353e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org                                 Immediate src);
13363e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org  void immediate_arithmetic_op_8(byte subcode,
1337911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                 const Operand& dst,
13383e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org                                 Immediate src);
1339911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  // Operate on a word in memory or register.
1340911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void immediate_arithmetic_op_16(byte subcode,
1341911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                  Register dst,
1342911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                  Immediate src);
1343911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  void immediate_arithmetic_op_16(byte subcode,
1344911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                  const Operand& dst,
1345911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org                                  Immediate src);
13462f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  // Operate on operands/registers with pointer size, 32-bit or 64-bit size.
13472f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void immediate_arithmetic_op(byte subcode,
13482f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                               Register dst,
13492f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                               Immediate src,
13502f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                               int size);
13512f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void immediate_arithmetic_op(byte subcode,
13522f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                               const Operand& dst,
13532f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                               Immediate src,
13542f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org                               int size);
1355911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
1356e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Emit machine code for a shift operation.
13572f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void shift(Register dst, Immediate shift_amount, int subcode, int size);
1358e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org  // Shift dst by cl % 64 bits.
13592f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org  void shift(Register dst, int subcode, int size);
13609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13615aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org  void emit_farith(int b1, int b2, int i);
13629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // labels
1364eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org  // void print(Label* L);
13659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void bind_to(Label* L, int pos);
13669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
13679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // record reloc info for current pc_
13689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
13699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1370fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  // Arithmetics
1371fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_add(Register dst, Register src, int size) {
13722f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x03, dst, src, size);
1373fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
1374fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
1375fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_add(Register dst, Immediate src, int size) {
13762f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x0, dst, src, size);
1377fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
1378fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
1379fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_add(Register dst, const Operand& src, int size) {
13802f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x03, dst, src, size);
1381fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
1382fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
1383fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_add(const Operand& dst, Register src, int size) {
13842f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x1, src, dst, size);
1385fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
1386fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
1387fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_add(const Operand& dst, Immediate src, int size) {
13882f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x0, dst, src, size);
1389fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
1390fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
1391895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_and(Register dst, Register src, int size) {
13922f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x23, dst, src, size);
1393895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1394895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1395895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_and(Register dst, const Operand& src, int size) {
13962f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x23, dst, src, size);
1397895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1398895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1399895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_and(const Operand& dst, Register src, int size) {
14002f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x21, src, dst, size);
1401895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1402895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1403895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_and(Register dst, Immediate src, int size) {
14042f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x4, dst, src, size);
1405895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1406895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1407895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_and(const Operand& dst, Immediate src, int size) {
14082f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x4, dst, src, size);
1409895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1410895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
14117a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_cmp(Register dst, Register src, int size) {
14122f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x3B, dst, src, size);
14137a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  }
14147a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org
14157a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_cmp(Register dst, const Operand& src, int size) {
14162f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x3B, dst, src, size);
14177a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  }
14187a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org
14197a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_cmp(const Operand& dst, Register src, int size) {
14202f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x39, src, dst, size);
14217a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  }
14227a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org
14237a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_cmp(Register dst, Immediate src, int size) {
14242f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x7, dst, src, size);
14257a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  }
14267a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org
14277a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_cmp(const Operand& dst, Immediate src, int size) {
14282f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x7, dst, src, size);
14297a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  }
14307a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org
14317a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_dec(Register dst, int size);
14327a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_dec(const Operand& dst, int size);
14337a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org
1434fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  // Divide rdx:rax by src.  Quotient in rax, remainder in rdx when size is 64.
1435fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  // Divide edx:eax by lower 32 bits of src.  Quotient in eax, remainder in edx
1436fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  // when size is 32.
1437fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_idiv(Register src, int size);
1438fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
1439fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  // Signed multiply instructions.
1440fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  // rdx:rax = rax * src when size is 64 or edx:eax = eax * src when size is 32.
1441fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_imul(Register src, int size);
1442fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_imul(Register dst, Register src, int size);
1443fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_imul(Register dst, const Operand& src, int size);
1444fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_imul(Register dst, Register src, Immediate imm, int size);
1445fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
14467a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_inc(Register dst, int size);
14477a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_inc(const Operand& dst, int size);
14487a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org
1449895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_lea(Register dst, const Operand& src, int size);
1450895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
14517a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_mov(Register dst, const Operand& src, int size);
14527a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_mov(Register dst, Register src, int size);
14537a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_mov(const Operand& dst, Register src, int size);
14547a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_mov(Register dst, Immediate value, int size);
14557a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_mov(const Operand& dst, Immediate value, int size);
14567a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org
1457895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_movzxb(Register dst, const Operand& src, int size);
1458895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_movzxw(Register dst, const Operand& src, int size);
1459895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_movzxw(Register dst, Register src, int size);
1460895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
14617a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_neg(Register dst, int size);
14627a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_neg(const Operand& dst, int size);
14637a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org
1464895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_not(Register dst, int size);
1465895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_not(const Operand& dst, int size);
1466895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1467895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_or(Register dst, Register src, int size) {
14682f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x0B, dst, src, size);
1469895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1470895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1471895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_or(Register dst, const Operand& src, int size) {
14722f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x0B, dst, src, size);
1473895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1474895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1475895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_or(const Operand& dst, Register src, int size) {
14762f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x9, src, dst, size);
1477895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1478895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1479895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_or(Register dst, Immediate src, int size) {
14802f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x1, dst, src, size);
1481895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1482895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1483895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_or(const Operand& dst, Immediate src, int size) {
14842f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x1, dst, src, size);
1485895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1486895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1487895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_repmovs(int size);
1488895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
14897a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_sbb(Register dst, Register src, int size) {
14902f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x1b, dst, src, size);
14917a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  }
14927a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org
1493fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_sub(Register dst, Register src, int size) {
14942f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x2B, dst, src, size);
1495fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
1496fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
1497fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_sub(Register dst, Immediate src, int size) {
14982f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x5, dst, src, size);
1499fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
1500fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
1501fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_sub(Register dst, const Operand& src, int size) {
15022f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x2B, dst, src, size);
1503fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
1504fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
1505fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_sub(const Operand& dst, Register src, int size) {
15062f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x29, src, dst, size);
1507fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
1508fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
1509fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  void emit_sub(const Operand& dst, Immediate src, int size) {
15102f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x5, dst, src, size);
1511fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
1512fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
15137a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_test(Register dst, Register src, int size);
15147a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_test(Register reg, Immediate mask, int size);
15157a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_test(const Operand& op, Register reg, int size);
15167a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  void emit_test(const Operand& op, Immediate mask, int size);
1517ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org
1518895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  // Exchange two registers
1519895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_xchg(Register dst, Register src, int size);
1520895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1521895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_xor(Register dst, Register src, int size) {
15222f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    if (size == kInt64Size && dst.code() == src.code()) {
15232f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
15242f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    // there is no need to make this a 64 bit operation.
15252f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org      arithmetic_op(0x33, dst, src, kInt32Size);
1526895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    } else {
15272f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org      arithmetic_op(0x33, dst, src, size);
1528895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    }
1529895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1530895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1531895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_xor(Register dst, const Operand& src, int size) {
15322f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x33, dst, src, size);
1533895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1534895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1535895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_xor(Register dst, Immediate src, int size) {
15362f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x6, dst, src, size);
1537895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1538895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1539895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_xor(const Operand& dst, Immediate src, int size) {
15402f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    immediate_arithmetic_op(0x6, dst, src, size);
1541895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1542895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
1543895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  void emit_xor(const Operand& dst, Register src, int size) {
15442f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org    arithmetic_op(0x31, src, dst, size);
1545895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  }
1546895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org
15479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  friend class CodePatcher;
15489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  friend class EnsureSpace;
1549911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  friend class RegExpMacroAssemblerX64;
15509085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15519085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  // code generation
15529085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  RelocInfoWriter reloc_info_writer;
15539085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1554c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  List< Handle<Code> > code_targets_;
15559085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
1556f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org  PositionsRecorder positions_recorder_;
1557f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org  friend class PositionsRecorder;
15589085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
15599085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// Helper class that ensures that there is enough space for generating
15629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// instructions and relocation information.  The constructor makes
15639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// sure that there is enough space and (in debug mode) the destructor
15649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org// checks that we did not generate too much.
15659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgclass EnsureSpace BASE_EMBEDDED {
15669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org public:
15679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
15684af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org    if (assembler_->buffer_overflow()) assembler_->GrowBuffer();
15699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#ifdef DEBUG
15709085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    space_before_ = assembler_->available_space();
15719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#endif
15729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
15739085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15749085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#ifdef DEBUG
15759085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  ~EnsureSpace() {
15769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    int bytes_generated = space_before_ - assembler_->available_space();
15779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    ASSERT(bytes_generated < assembler_->kGap);
15789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
15799085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#endif
15809085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org private:
15829085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  Assembler* assembler_;
15839085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#ifdef DEBUG
15849085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  int space_before_;
15859085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#endif
15869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org};
15879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org
15889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org} }  // namespace v8::internal
15895ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org
15909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#endif  // V8_X64_ASSEMBLER_X64_H_
1591