assembler-x64.h revision 8defd9ff6930b4e24729971a61cf7469daf119be
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright (c) 1994-2006 Sun Microsystems Inc. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// All Rights Reserved. 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// - Redistributions of source code must retain the above copyright notice, 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// this list of conditions and the following disclaimer. 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// - Redistribution in binary form must reproduce the above copyright 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer in the 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// documentation and/or other materials provided with the distribution. 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// - Neither the name of Sun Microsystems or the names of contributors may 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// be used to endorse or promote products derived from this software without 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// specific prior written permission. 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The original source code covered by the above license above has been 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modified significantly by Google Inc. 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2009 the V8 project authors. All rights reserved. 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A lightweight X64 Assembler. 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_X64_ASSEMBLER_X64_H_ 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_X64_ASSEMBLER_X64_H_ 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 40d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "serialize.h" 41d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Utility functions 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test whether a 64-bit value is in a specific range. 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline bool is_uint32(int64_t x) { 498defd9ff6930b4e24729971a61cf7469daf119beSteve Block static const uint64_t kMaxUInt32 = V8_UINT64_C(0xffffffff); 508defd9ff6930b4e24729971a61cf7469daf119beSteve Block return static_cast<uint64_t>(x) <= kMaxUInt32; 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline bool is_int32(int64_t x) { 548defd9ff6930b4e24729971a61cf7469daf119beSteve Block static const int64_t kMinInt32 = -V8_INT64_C(0x80000000); 558defd9ff6930b4e24729971a61cf7469daf119beSteve Block return is_uint32(x - kMinInt32); 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline bool uint_is_int32(uint64_t x) { 598defd9ff6930b4e24729971a61cf7469daf119beSteve Block static const uint64_t kMaxInt32 = V8_UINT64_C(0x7fffffff); 608defd9ff6930b4e24729971a61cf7469daf119beSteve Block return x <= kMaxInt32; 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline bool is_uint32(uint64_t x) { 648defd9ff6930b4e24729971a61cf7469daf119beSteve Block static const uint64_t kMaxUInt32 = V8_UINT64_C(0xffffffff); 658defd9ff6930b4e24729971a61cf7469daf119beSteve Block return x <= kMaxUInt32; 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CPU Registers. 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 1) We would prefer to use an enum, but enum values are assignment- 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// compatible with int, which has caused code-generation bugs. 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 2) We would prefer to use a class instead of a struct but we don't like 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the register initialization to depend on the particular initialization 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// order (which appears to be different on OS X, Linux, and Windows for the 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// installed versions of C++ we tried). Using a struct permits C-style 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "initialization". Also, the Register objects cannot be const as this 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// forces initialization stubs in MSVC, making us dependent on initialization 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// order. 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 3) By not using an enum, we are possibly preventing the compiler from 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// doing certain constant folds, which may significantly reduce the 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// code generated for some assembly instructions (because they boil down 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to a few constants). If this is a problem, we could change the code 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// such that we use an enum in optimized mode, and the struct in debug 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// mode. This way we get the compile-time error checking in debug mode 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and best performance in optimized code. 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct Register { 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static Register toRegister(int code) { 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register r = { code }; 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return r; 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_valid() const { return 0 <= code_ && code_ < 16; } 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is(Register reg) const { return code_ == reg.code_; } 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int code() const { 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_valid()); 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return code_; 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int bit() const { 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1 << code_; 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the high bit of the register code as a 0 or 1. Used often 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // when constructing the REX prefix byte. 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int high_bit() const { 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return code_ >> 3; 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the 3 low bits of the register code. Used when encoding registers 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // in modR/M, SIB, and opcode bytes. 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int low_bits() const { 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return code_ & 0x7; 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Unfortunately we can't make this private in a struct when initializing 1173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // by assignment. 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int code_; 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 121402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register rax = { 0 }; 122402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register rcx = { 1 }; 123402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register rdx = { 2 }; 124402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register rbx = { 3 }; 125402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register rsp = { 4 }; 126402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register rbp = { 5 }; 127402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register rsi = { 6 }; 128402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register rdi = { 7 }; 129402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register r8 = { 8 }; 130402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register r9 = { 9 }; 131402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register r10 = { 10 }; 132402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register r11 = { 11 }; 133402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register r12 = { 12 }; 134402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register r13 = { 13 }; 135402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register r14 = { 14 }; 136402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register r15 = { 15 }; 137402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst Register no_reg = { -1 }; 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct XMMRegister { 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_valid() const { return 0 <= code_ && code_ < 16; } 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int code() const { 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_valid()); 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return code_; 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the high bit of the register code as a 0 or 1. Used often 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // when constructing the REX prefix byte. 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int high_bit() const { 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return code_ >> 3; 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the 3 low bits of the register code. Used when encoding registers 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // in modR/M, SIB, and opcode bytes. 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int low_bits() const { 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return code_ & 0x7; 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int code_; 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 161402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm0 = { 0 }; 162402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm1 = { 1 }; 163402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm2 = { 2 }; 164402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm3 = { 3 }; 165402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm4 = { 4 }; 166402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm5 = { 5 }; 167402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm6 = { 6 }; 168402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm7 = { 7 }; 169402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm8 = { 8 }; 170402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm9 = { 9 }; 171402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm10 = { 10 }; 172402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm11 = { 11 }; 173402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm12 = { 12 }; 174402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm13 = { 13 }; 175402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm14 = { 14 }; 176402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuconst XMMRegister xmm15 = { 15 }; 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum Condition { 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // any value < 0 is considered no_condition 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block no_condition = -1, 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block overflow = 0, 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block no_overflow = 1, 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block below = 2, 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block above_equal = 3, 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block equal = 4, 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block not_equal = 5, 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block below_equal = 6, 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block above = 7, 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block negative = 8, 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block positive = 9, 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block parity_even = 10, 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block parity_odd = 11, 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block less = 12, 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block greater_equal = 13, 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block less_equal = 14, 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block greater = 15, 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Fake conditions that are handled by the 2003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // opcodes using them. 2013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block always = 16, 2023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block never = 17, 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // aliases 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block carry = below, 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block not_carry = above_equal, 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block zero = equal, 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block not_zero = not_equal, 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sign = negative, 2093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block not_sign = positive, 2103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block last_condition = greater 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns the equivalent of !cc. 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Negation of the default no_condition (-1) results in a non-default 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// no_condition value (-2). As long as tests for no_condition check 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// for condition < 0, this will work as expected. 2189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monseninline Condition NegateCondition(Condition cc) { 2199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen return static_cast<Condition>(cc ^ 1); 2209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 2219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Corresponds to transposing the operands of a comparison. 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline Condition ReverseCondition(Condition cc) { 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (cc) { 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case below: 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return above; 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case above: 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return below; 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case above_equal: 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return below_equal; 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case below_equal: 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return above_equal; 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case less: 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return greater; 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case greater: 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return less; 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case greater_equal: 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return less_equal; 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case less_equal: 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return greater_equal; 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return cc; 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum Hint { 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block no_hint = 0, 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block not_taken = 0x2e, 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block taken = 0x3e 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The result of negating a hint is as if the corresponding condition 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// were negated by NegateCondition. That is, no_hint is mapped to 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// itself and not_taken and taken are mapped to each other. 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline Hint NegateHint(Hint hint) { 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return (hint == no_hint) 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ? no_hint 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : ((hint == not_taken) ? taken : not_taken); 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------- 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Machine instruction Immediates 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Immediate BASE_EMBEDDED { 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit Immediate(int32_t value) : value_(value) {} 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t value_; 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block friend class Assembler; 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------- 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Machine instruction Operands 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum ScaleFactor { 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block times_1 = 0, 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block times_2 = 1, 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block times_4 = 2, 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block times_8 = 3, 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block times_int_size = times_4, 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block times_pointer_size = times_8 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Operand BASE_EMBEDDED { 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [base + disp/r] 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(Register base, int32_t disp); 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [base + index*scale + disp/r] 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(Register base, 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register index, 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScaleFactor scale, 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t disp); 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [index*scale + disp/r] 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(Register index, 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScaleFactor scale, 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t disp); 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 307f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Offset from existing memory operand. 308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Offset is added to existing displacement as 32-bit signed values and 309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // this must not overflow. 310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Operand(const Operand& base, int32_t offset); 311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte rex_; 3147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch byte buf_[6]; 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The number of bytes in buf_. 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned int len_; 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the ModR/M byte without an encoded 'reg' register. The 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register is encoded later as part of the emit_operand operation. 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // set_modrm can be called before or after set_sib and set_disp*. 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void set_modrm(int mod, Register rm); 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the SIB byte if one is needed. Sets the length to 2 rather than 1. 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void set_sib(ScaleFactor scale, Register index, Register base); 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adds operand displacement fields (offsets added to the memory address). 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Needs to be called after set_sib, not before it. 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void set_disp8(int disp); 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void set_disp32(int disp); 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block friend class Assembler; 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CpuFeatures keeps track of which features are supported by the target CPU. 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Supported features must be enabled by a Scope before use. 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Example: 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// if (CpuFeatures::IsSupported(SSE3)) { 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CpuFeatures::Scope fscope(SSE3); 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// // Generate SSE3 floating point code. 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// } else { 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// // Generate standard x87 or SSE2 floating point code. 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// } 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CpuFeatures : public AllStatic { 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Detect features of the target CPU. Set safe defaults if the serializer 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is enabled (snapshots must be portable). 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static void Probe(); 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check whether a feature is supported by the target CPU. 350d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static bool IsSupported(CpuFeature f) { 3513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (f == SSE2 && !FLAG_enable_sse2) return false; 3523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (f == SSE3 && !FLAG_enable_sse3) return false; 3533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (f == CMOV && !FLAG_enable_cmov) return false; 3543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (f == RDTSC && !FLAG_enable_rdtsc) return false; 3553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (f == SAHF && !FLAG_enable_sahf) return false; 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return (supported_ & (V8_UINT64_C(1) << f)) != 0; 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check whether a feature is currently enabled. 359d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static bool IsEnabled(CpuFeature f) { 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return (enabled_ & (V8_UINT64_C(1) << f)) != 0; 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Enable a specified feature within a scope. 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block class Scope BASE_EMBEDDED { 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 366d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block explicit Scope(CpuFeature f) { 367d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block uint64_t mask = (V8_UINT64_C(1) << f); 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(CpuFeatures::IsSupported(f)); 369d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(!Serializer::enabled() || (found_by_runtime_probing_ & mask) == 0); 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block old_enabled_ = CpuFeatures::enabled_; 371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CpuFeatures::enabled_ |= mask; 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ~Scope() { CpuFeatures::enabled_ = old_enabled_; } 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint64_t old_enabled_; 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 378d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block explicit Scope(CpuFeature f) {} 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Safe defaults include SSE2 and CMOV for X64. It is always available, if 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // anyone checks, but they shouldn't need to check. 384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static const uint64_t kDefaultCpuFeatures = (1 << SSE2 | 1 << CMOV); 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static uint64_t supported_; 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static uint64_t enabled_; 387d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static uint64_t found_by_runtime_probing_; 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Assembler : public Malloced { 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We check before assembling an instruction that there is sufficient 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // space to write an instruction and its relocation information. 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The relocation writer's position must be kGap bytes above the end of 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the generated instructions. This leaves enough space for the 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // longest possible x64 instruction, 15 bytes, and the longest possible 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // relocation information encoding, RelocInfoWriter::kMaxLength == 16. 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // (There is a 15 byte limit on x64 instruction length that rules out some 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // otherwise valid instructions.) 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This allows for a single, fast space check per instruction. 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kGap = 32; 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Create an assembler. Instructions and relocation information are emitted 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // into a buffer, with the instructions starting from the beginning and the 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // relocation information starting from the end of the buffer. See CodeDesc 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for a detailed comment on the layout (globals.h). 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the provided buffer is NULL, the assembler allocates and grows its own 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // buffer, and buffer_size determines the initial buffer size. The buffer is 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // owned by the assembler and deallocated upon destruction of the assembler. 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the provided buffer is not NULL, the assembler uses the provided buffer 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for code generation and assumes its size to be buffer_size. If the buffer 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is too small, a fatal error occurs. No deallocation of the buffer is done 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // upon destruction of the assembler. 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Assembler(void* buffer, int buffer_size); 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ~Assembler(); 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // GetCode emits any pending (non-emitted) code and fills the descriptor 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // desc. GetCode() is idempotent; it returns the same result if no other 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Assembler functions are invoked in between GetCode() calls. 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void GetCode(CodeDesc* desc); 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Read/Modify the code target in the relative branch/call instruction at pc. 4273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // On the x64 architecture, we use relative jumps with a 32-bit displacement 4283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // to jump to other Code objects in the Code space in the heap. 4293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Jumps to C functions are done indirectly through a 64-bit register holding 4303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // the absolute address of the target. 4313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // These functions convert between absolute Addresses of Code objects and 4323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // the relative displacements stored in the code. 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static inline Address target_address_at(Address pc); 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static inline void set_target_address_at(Address pc, Address target); 435d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 436d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This sets the branch destination (which is in the instruction on x64). 437d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This is for calls and branches within generated code. 438d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block inline static void set_target_at(Address instruction_payload, 439d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Address target) { 440d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block set_target_address_at(instruction_payload, target); 441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This sets the branch destination (which is a load instruction on x64). 444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This is for calls and branches to runtime code. 445d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block inline static void set_external_target_at(Address instruction_payload, 446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Address target) { 447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *reinterpret_cast<Address*>(instruction_payload) = target; 448d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 449d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block inline Handle<Object> code_target_object_handle_at(Address pc); 451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Number of bytes taken up by the branch target in the code. 452d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static const int kCallTargetSize = 4; // Use 32-bit displacement. 453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static const int kExternalTargetSize = 8; // Use 64-bit absolute. 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Distance between the address of the code target in the call instruction 4553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // and the return address pushed on the stack. 4563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block static const int kCallTargetAddressOffset = 4; // Use 32-bit displacement. 4573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Distance between the start of the JS return sequence and where the 4583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // 32-bit displacement of a near call would be, relative to the pushed 4593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // return address. TODO: Use return sequence length instead. 4603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset; 4613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block static const int kPatchReturnSequenceAddressOffset = 13 - 4; 4627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Distance between start of patched debug break slot and where the 4637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // 32-bit displacement of a near call would be, relative to the pushed 4647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // return address. TODO: Use return sequence length instead. 4657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset; 4667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch static const int kPatchDebugBreakSlotAddressOffset = 13 - 4; 4673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // TODO(X64): Rename this, removing the "Real", after changing the above. 4683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block static const int kRealPatchReturnSequenceAddressOffset = 2; 469d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 470d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // The x64 JS return sequence is padded with int3 to make it large 471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // enough to hold a call instruction when the debugger patches it. 472d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static const int kCallInstructionLength = 13; 473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static const int kJSReturnSequenceLength = 13; 474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // The debug break slot must be able to contain a call instruction. 4767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch static const int kDebugBreakSlotLength = kCallInstructionLength; 4777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Code generation 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Function names correspond one-to-one to x64 instruction mnemonics. 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Unless specified otherwise, instructions operate on 64-bit operands. 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we need versions of an assembly instruction that operate on different 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // width arguments, we add a single-letter suffix specifying the width. 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This is done for the following instructions: mov, cmp, inc, dec, 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // add, sub, and test. 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // There are no versions of these instructions without the suffix. 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'. 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // - Instructions on 16-bit (word) operands/registers have a trailing 'w'. 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // - Instructions on 32-bit (doubleword) operands/registers use 'l'. 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // - Instructions on 64-bit (quadword) operands/registers use 'q'. 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Some mnemonics, such as "and", are the same as C++ keywords. 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Naming conflicts with C++ keywords are resolved by adding a trailing '_'. 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Insert the smallest number of nop instructions 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // possible to align the pc offset to a multiple 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of m. m must be a power of 2. 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Align(int m); 5029dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Aligns code to something that's optimal for a jump target for the platform. 5039dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen void CodeTargetAlign(); 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stack 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void pushfq(); 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void popfq(); 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void push(Immediate value); 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void push(Register src); 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void push(const Operand& src); 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void push(Label* label, RelocInfo::Mode relocation_mode); 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void pop(Register dst); 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void pop(const Operand& dst); 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void enter(Immediate size); 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void leave(); 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Moves 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movb(Register dst, const Operand& src); 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movb(Register dst, Immediate imm); 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movb(const Operand& dst, Register src); 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Move the low 16 bits of a 64-bit register value to a 16-bit 5263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // memory location. 5273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void movw(const Operand& dst, Register src); 5283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movl(Register dst, Register src); 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movl(Register dst, const Operand& src); 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movl(const Operand& dst, Register src); 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movl(const Operand& dst, Immediate imm); 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load a 32-bit immediate value, zero-extended to 64 bits. 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movl(Register dst, Immediate imm32); 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move 64 bit register value to 64-bit memory location. 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movq(const Operand& dst, Register src); 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move 64 bit memory location to 64-bit register value. 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movq(Register dst, const Operand& src); 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movq(Register dst, Register src); 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Sign extends immediate 32-bit value to 64 bits. 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movq(Register dst, Immediate x); 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move the offset of the label location relative to the current 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // position (after the move) to the destination. 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movl(const Operand& dst, Label* src); 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move sign extended immediate to memory location. 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movq(const Operand& dst, Immediate value); 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // New x64 instructions to load a 64-bit immediate into a register. 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // All 64-bit immediates must have a relocation mode. 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movq(Register dst, void* ptr, RelocInfo::Mode rmode); 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movq(Register dst, int64_t value, RelocInfo::Mode rmode); 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movq(Register dst, const char* s, RelocInfo::Mode rmode); 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Moves the address of the external reference into the register. 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movq(Register dst, ExternalReference ext); 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movq(Register dst, Handle<Object> handle, RelocInfo::Mode rmode); 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void movsxbq(Register dst, const Operand& src); 5593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void movsxwq(Register dst, const Operand& src); 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movsxlq(Register dst, Register src); 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movsxlq(Register dst, const Operand& src); 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movzxbq(Register dst, const Operand& src); 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movzxbl(Register dst, const Operand& src); 5643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void movzxwq(Register dst, const Operand& src); 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movzxwl(Register dst, const Operand& src); 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 567d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Repeated moves. 568d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 569d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void repmovsb(); 570d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void repmovsw(); 571d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void repmovsl(); 572d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void repmovsq(); 573d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // New x64 instruction to load from an immediate 64-bit pointer into RAX. 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void load_rax(void* ptr, RelocInfo::Mode rmode); 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void load_rax(ExternalReference ext); 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Conditional moves. 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmovq(Condition cc, Register dst, Register src); 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmovq(Condition cc, Register dst, const Operand& src); 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmovl(Condition cc, Register dst, Register src); 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmovl(Condition cc, Register dst, const Operand& src); 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exchange two registers 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void xchg(Register dst, Register src); 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Arithmetics 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void addl(Register dst, Register src) { 589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke arithmetic_op_32(0x03, dst, src); 590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void addl(Register dst, Immediate src) { 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op_32(0x0, dst, src); 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void addl(Register dst, const Operand& src) { 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op_32(0x03, dst, src); 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void addl(const Operand& dst, Immediate src) { 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op_32(0x0, dst, src); 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void addq(Register dst, Register src) { 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op(0x03, dst, src); 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void addq(Register dst, const Operand& src) { 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op(0x03, dst, src); 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void addq(const Operand& dst, Register src) { 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op(0x01, src, dst); 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void addq(Register dst, Immediate src) { 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op(0x0, dst, src); 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void addq(const Operand& dst, Immediate src) { 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op(0x0, dst, src); 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 62425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen void sbbl(Register dst, Register src) { 625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke arithmetic_op_32(0x1b, dst, src); 62625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 62725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpb(Register dst, Immediate src) { 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op_8(0x7, dst, src); 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpb_al(Immediate src); 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpb(Register dst, Register src) { 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op(0x3A, dst, src); 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpb(Register dst, const Operand& src) { 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op(0x3A, dst, src); 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpb(const Operand& dst, Register src) { 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op(0x38, src, dst); 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpb(const Operand& dst, Immediate src) { 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op_8(0x7, dst, src); 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpw(const Operand& dst, Immediate src) { 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op_16(0x7, dst, src); 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpw(Register dst, Immediate src) { 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op_16(0x7, dst, src); 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpw(Register dst, const Operand& src) { 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op_16(0x3B, dst, src); 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpw(Register dst, Register src) { 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op_16(0x3B, dst, src); 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpw(const Operand& dst, Register src) { 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op_16(0x39, src, dst); 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpl(Register dst, Register src) { 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op_32(0x3B, dst, src); 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpl(Register dst, const Operand& src) { 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op_32(0x3B, dst, src); 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpl(const Operand& dst, Register src) { 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op_32(0x39, src, dst); 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpl(Register dst, Immediate src) { 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op_32(0x7, dst, src); 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpl(const Operand& dst, Immediate src) { 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op_32(0x7, dst, src); 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpq(Register dst, Register src) { 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op(0x3B, dst, src); 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpq(Register dst, const Operand& src) { 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op(0x3B, dst, src); 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpq(const Operand& dst, Register src) { 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op(0x39, src, dst); 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpq(Register dst, Immediate src) { 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op(0x7, dst, src); 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpq(const Operand& dst, Immediate src) { 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op(0x7, dst, src); 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void and_(Register dst, Register src) { 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op(0x23, dst, src); 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void and_(Register dst, const Operand& src) { 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op(0x23, dst, src); 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void and_(const Operand& dst, Register src) { 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op(0x21, src, dst); 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void and_(Register dst, Immediate src) { 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op(0x4, dst, src); 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void and_(const Operand& dst, Immediate src) { 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op(0x4, dst, src); 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void andl(Register dst, Immediate src) { 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op_32(0x4, dst, src); 732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void andl(Register dst, Register src) { 7353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block arithmetic_op_32(0x23, dst, src); 7363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 7373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke void andb(Register dst, Immediate src) { 7394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke immediate_arithmetic_op_8(0x4, dst, src); 7404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 7413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void decq(Register dst); 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void decq(const Operand& dst); 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void decl(Register dst); 745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void decl(const Operand& dst); 7463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void decb(Register dst); 7473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void decb(const Operand& dst); 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Sign-extends rax into rdx:rax. 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cqo(); 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Sign-extends eax into edx:eax. 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cdq(); 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Divide rdx:rax by src. Quotient in rax, remainder in rdx. 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void idivq(Register src); 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Divide edx:eax by lower 32 bits of src. Quotient in eax, rem. in edx. 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void idivl(Register src); 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Signed multiply instructions. 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void imul(Register src); // rdx:rax = rax * src. 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void imul(Register dst, Register src); // dst = dst * src. 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void imul(Register dst, const Operand& src); // dst = dst * src. 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void imul(Register dst, Register src, Immediate imm); // dst = src * imm. 7646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Signed 32-bit multiply instructions. 7656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void imull(Register dst, Register src); // dst = dst * src. 7666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void imull(Register dst, Register src, Immediate imm); // dst = src * imm. 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void incq(Register dst); 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void incq(const Operand& dst); 7709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen void incl(Register dst); 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void incl(const Operand& dst); 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void lea(Register dst, const Operand& src); 7746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void leal(Register dst, const Operand& src); 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Multiply rax by src, put the result in rdx:rax. 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mul(Register src); 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void neg(Register dst); 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void neg(const Operand& dst); 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void negl(Register dst); 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void not_(Register dst); 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void not_(const Operand& dst); 7856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void notl(Register dst); 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void or_(Register dst, Register src) { 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op(0x0B, dst, src); 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void orl(Register dst, Register src) { 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op_32(0x0B, dst, src); 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void or_(Register dst, const Operand& src) { 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op(0x0B, dst, src); 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void or_(const Operand& dst, Register src) { 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op(0x09, src, dst); 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void or_(Register dst, Immediate src) { 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op(0x1, dst, src); 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void orl(Register dst, Immediate src) { 8083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block immediate_arithmetic_op_32(0x1, dst, src); 8093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void or_(const Operand& dst, Immediate src) { 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op(0x1, dst, src); 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void orl(const Operand& dst, Immediate src) { 8163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block immediate_arithmetic_op_32(0x1, dst, src); 8173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void rcl(Register dst, Immediate imm8) { 8213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shift(dst, imm8, 0x2); 8223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void rol(Register dst, Immediate imm8) { 8253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shift(dst, imm8, 0x0); 8263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void rcr(Register dst, Immediate imm8) { 8293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shift(dst, imm8, 0x3); 8303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void ror(Register dst, Immediate imm8) { 8333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block shift(dst, imm8, 0x1); 8343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Shifts dst:src left by cl bits, affecting only dst. 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void shld(Register dst, Register src); 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Shifts src:dst right by cl bits, affecting only dst. 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void shrd(Register dst, Register src); 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Shifts dst right, duplicating sign bit, by shift_amount bits. 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Shifting by 1 is handled efficiently. 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void sar(Register dst, Immediate shift_amount) { 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift(dst, shift_amount, 0x7); 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Shifts dst right, duplicating sign bit, by shift_amount bits. 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Shifting by 1 is handled efficiently. 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void sarl(Register dst, Immediate shift_amount) { 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift_32(dst, shift_amount, 0x7); 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Shifts dst right, duplicating sign bit, by cl % 64 bits. 855d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void sar_cl(Register dst) { 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift(dst, 0x7); 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Shifts dst right, duplicating sign bit, by cl % 64 bits. 860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void sarl_cl(Register dst) { 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift_32(dst, 0x7); 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void shl(Register dst, Immediate shift_amount) { 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift(dst, shift_amount, 0x4); 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void shl_cl(Register dst) { 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift(dst, 0x4); 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void shll_cl(Register dst) { 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift_32(dst, 0x4); 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void shll(Register dst, Immediate shift_amount) { 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift_32(dst, shift_amount, 0x4); 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void shr(Register dst, Immediate shift_amount) { 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift(dst, shift_amount, 0x5); 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 884d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void shr_cl(Register dst) { 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift(dst, 0x5); 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 888d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void shrl_cl(Register dst) { 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift_32(dst, 0x5); 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void shrl(Register dst, Immediate shift_amount) { 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift_32(dst, shift_amount, 0x5); 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void store_rax(void* dst, RelocInfo::Mode mode); 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void store_rax(ExternalReference ref); 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void subq(Register dst, Register src) { 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op(0x2B, dst, src); 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void subq(Register dst, const Operand& src) { 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op(0x2B, dst, src); 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void subq(const Operand& dst, Register src) { 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op(0x29, src, dst); 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void subq(Register dst, Immediate src) { 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op(0x5, dst, src); 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void subq(const Operand& dst, Immediate src) { 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op(0x5, dst, src); 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void subl(Register dst, Register src) { 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op_32(0x2B, dst, src); 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 923e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void subl(Register dst, const Operand& src) { 924e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke arithmetic_op_32(0x2B, dst, src); 925e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 926e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void subl(const Operand& dst, Immediate src) { 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op_32(0x5, dst, src); 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void subl(Register dst, Immediate src) { 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op_32(0x5, dst, src); 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void subb(Register dst, Immediate src) { 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op_8(0x5, dst, src); 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void testb(Register dst, Register src); 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void testb(Register reg, Immediate mask); 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void testb(const Operand& op, Immediate mask); 942e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void testb(const Operand& op, Register reg); 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void testl(Register dst, Register src); 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void testl(Register reg, Immediate mask); 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void testl(const Operand& op, Immediate mask); 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void testq(const Operand& op, Register reg); 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void testq(Register dst, Register src); 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void testq(Register dst, Immediate mask); 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void xor_(Register dst, Register src) { 951d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (dst.code() == src.code()) { 952d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block arithmetic_op_32(0x33, dst, src); 953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 954d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block arithmetic_op(0x33, dst, src); 955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void xorl(Register dst, Register src) { 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op_32(0x33, dst, src); 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void xor_(Register dst, const Operand& src) { 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op(0x33, dst, src); 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void xor_(const Operand& dst, Register src) { 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block arithmetic_op(0x31, src, dst); 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void xor_(Register dst, Immediate src) { 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op(0x6, dst, src); 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void xor_(const Operand& dst, Immediate src) { 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block immediate_arithmetic_op(0x6, dst, src); 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Bit operations. 979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void bt(const Operand& dst, Register src); 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void bts(const Operand& dst, Register src); 981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Miscellaneous 9833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void clc(); 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cpuid(); 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void hlt(); 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void int3(); 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void nop(); 988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void nop(int n); 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void rdtsc(); 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void ret(int imm16); 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void setcc(Condition cc, Register reg); 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Label operations & relative jumps (PPUM Appendix D) 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Takes a branch opcode (cc) and a label (L) and generates 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // either a backward branch or a forward branch and links it 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to the label fixup chain. Usage: 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Label L; // unbound label 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // j(cc, &L); // forward branch to unbound label 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bind(&L); // bind label to the current pc 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // j(cc, &L); // backward branch to bound label 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bind(&L); // illegal: a label may be bound only once 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Note: The same Label can be used for forward and backward branches 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // but it may be bound only once. 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void bind(Label* L); // binds an unbound label L to the current code position 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calls 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call near relative 32-bit displacement, relative to next instruction. 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void call(Label* L); 10133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void call(Handle<Code> target, RelocInfo::Mode rmode); 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call near absolute indirect, address in register 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void call(Register adr); 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call near indirect 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void call(const Operand& operand); 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jumps 1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump short or near relative. 10233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Use a 32-bit signed displacement. 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void jmp(Label* L); // unconditional jump to L 10253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void jmp(Handle<Code> target, RelocInfo::Mode rmode); 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump near absolute indirect (r64) 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void jmp(Register adr); 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump near absolute indirect (m64) 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void jmp(const Operand& src); 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Conditional jumps 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void j(Condition cc, Label* L); 10353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode); 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Floating-point operations 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fld(int i); 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fld1(); 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fldz(); 10426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void fldpi(); 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fld_s(const Operand& adr); 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fld_d(const Operand& adr); 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fstp_s(const Operand& adr); 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fstp_d(const Operand& adr); 10493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void fstp(int index); 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fild_s(const Operand& adr); 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fild_d(const Operand& adr); 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fist_s(const Operand& adr); 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fistp_s(const Operand& adr); 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fistp_d(const Operand& adr); 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fisttp_s(const Operand& adr); 1060d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void fisttp_d(const Operand& adr); 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fabs(); 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fchs(); 1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fadd(int i); 1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fsub(int i); 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fmul(int i); 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fdiv(int i); 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fisub_s(const Operand& adr); 1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void faddp(int i = 1); 1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fsubp(int i = 1); 1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fsubrp(int i = 1); 1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fmulp(int i = 1); 1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fdivp(int i = 1); 1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fprem(); 1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fprem1(); 1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fxch(int i = 1); 1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fincstp(); 1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void ffree(int i = 0); 1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void ftst(); 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fucomp(int i); 1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fucompp(); 10873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void fucomi(int i); 10883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void fucomip(); 10893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fcompp(); 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fnstsw_ax(); 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fwait(); 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fnclex(); 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fsin(); 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fcos(); 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void frndint(); 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void sahf(); 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // SSE2 instructions 11036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void movd(XMMRegister dst, Register src); 11046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void movd(Register dst, XMMRegister src); 11056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void movq(XMMRegister dst, Register src); 11066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void movq(Register dst, XMMRegister src); 11076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void extractps(Register dst, XMMRegister src, byte imm8); 11086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movsd(const Operand& dst, XMMRegister src); 11106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void movsd(XMMRegister dst, XMMRegister src); 11116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void movsd(XMMRegister dst, const Operand& src); 1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11138defd9ff6930b4e24729971a61cf7469daf119beSteve Block void movss(XMMRegister dst, const Operand& src); 11148defd9ff6930b4e24729971a61cf7469daf119beSteve Block void movss(const Operand& dst, XMMRegister src); 11158defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cvttss2si(Register dst, const Operand& src); 1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cvttsd2si(Register dst, const Operand& src); 111825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen void cvttsd2siq(Register dst, XMMRegister src); 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cvtlsi2sd(XMMRegister dst, const Operand& src); 1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cvtlsi2sd(XMMRegister dst, Register src); 1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cvtqsi2sd(XMMRegister dst, const Operand& src); 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cvtqsi2sd(XMMRegister dst, Register src); 1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11258defd9ff6930b4e24729971a61cf7469daf119beSteve Block void cvtlsi2ss(XMMRegister dst, Register src); 11268defd9ff6930b4e24729971a61cf7469daf119beSteve Block 11276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void cvtss2sd(XMMRegister dst, XMMRegister src); 11288defd9ff6930b4e24729971a61cf7469daf119beSteve Block void cvtss2sd(XMMRegister dst, const Operand& src); 11298defd9ff6930b4e24729971a61cf7469daf119beSteve Block void cvtsd2ss(XMMRegister dst, XMMRegister src); 11308defd9ff6930b4e24729971a61cf7469daf119beSteve Block 11318defd9ff6930b4e24729971a61cf7469daf119beSteve Block void cvtsd2si(Register dst, XMMRegister src); 11328defd9ff6930b4e24729971a61cf7469daf119beSteve Block void cvtsd2siq(Register dst, XMMRegister src); 11336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void addsd(XMMRegister dst, XMMRegister src); 1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void subsd(XMMRegister dst, XMMRegister src); 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mulsd(XMMRegister dst, XMMRegister src); 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void divsd(XMMRegister dst, XMMRegister src); 1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1139402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void xorpd(XMMRegister dst, XMMRegister src); 11406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void sqrtsd(XMMRegister dst, XMMRegister src); 1141402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1142402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void ucomisd(XMMRegister dst, XMMRegister src); 11438defd9ff6930b4e24729971a61cf7469daf119beSteve Block void ucomisd(XMMRegister dst, const Operand& src); 1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // The first argument is the reg field, the second argument is the r/m field. 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_sse_operand(XMMRegister dst, XMMRegister src); 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_sse_operand(XMMRegister reg, const Operand& adr); 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_sse_operand(XMMRegister dst, Register src); 11496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void emit_sse_operand(Register dst, XMMRegister src); 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use either movsd or movlpd. 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // void movdbl(XMMRegister dst, const Operand& src); 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // void movdbl(const Operand& dst, XMMRegister src); 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Debugging 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Print(); 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the code size generated from label to here. 1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int SizeOfCodeGeneratedSince(Label* l) { return pc_offset() - l->pos(); } 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mark address of the ExitJSFrame code. 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void RecordJSReturn(); 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Mark address of a debug break slot. 11657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void RecordDebugBreakSlot(); 11667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Record a comment relocation entry that can be used by a disassembler. 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use --debug_code to enable. 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void RecordComment(const char* msg); 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void RecordPosition(int pos); 1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void RecordStatementPosition(int pos); 11737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch bool WriteRecordedPositions(); 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int pc_offset() const { return static_cast<int>(pc_ - buffer_); } 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int current_statement_position() const { return current_statement_position_; } 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int current_position() const { return current_position_; } 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if there is less than kGap bytes available in the buffer. 1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If this is the case, we need to grow the buffer before emitting 1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // an instruction or relocation information. 1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline bool buffer_overflow() const { 1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return pc_ >= reloc_info_writer.pos() - kGap; 1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the number of bytes available in the buffer. 1187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block inline int available_space() const { 1188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return static_cast<int>(reloc_info_writer.pos() - pc_); 1189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch static bool IsNop(Address addr) { return *addr == 0x90; } 11927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Avoid overflows for displacements etc. 1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kMaximalBufferSize = 512*MB; 1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kMinimalBufferSize = 4*KB; 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* addr_at(int pos) { return buffer_ + pos; } 1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte byte_at(int pos) { return buffer_[pos]; } 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t long_at(int pos) { 1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return *reinterpret_cast<uint32_t*>(addr_at(pos)); 1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void long_at_put(int pos, uint32_t x) { 1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *reinterpret_cast<uint32_t*>(addr_at(pos)) = x; 1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code emission 1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void GrowBuffer(); 1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit(byte x) { *pc_++ = x; } 1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emitl(uint32_t x); 1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emitq(uint64_t x, RelocInfo::Mode rmode); 1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emitw(uint16_t x); 12143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block inline void emit_code_target(Handle<Code> target, RelocInfo::Mode rmode); 1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit(Immediate x) { emitl(x.value_); } 1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emits a REX prefix that encodes a 64-bit operand size and 1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the top bit of both register codes. 1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B. 1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // REX.W is set. 1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_rex_64(XMMRegister reg, Register rm_reg); 12226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block inline void emit_rex_64(Register reg, XMMRegister rm_reg); 12236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block inline void emit_rex_64(Register reg, Register rm_reg); 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emits a REX prefix that encodes a 64-bit operand size and 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the top bit of the destination, index, and base register codes. 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The high bit of reg is used for REX.R, the high bit of op's base 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register is used for REX.B, and the high bit of op's index register 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is used for REX.X. REX.W is set. 1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_rex_64(Register reg, const Operand& op); 1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_rex_64(XMMRegister reg, const Operand& op); 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emits a REX prefix that encodes a 64-bit operand size and 1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the top bit of the register code. 1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The high bit of register is used for REX.B. 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // REX.W is set and REX.R and REX.X are clear. 1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_rex_64(Register rm_reg); 1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emits a REX prefix that encodes a 64-bit operand size and 1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the top bit of the index and base register codes. 1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The high bit of op's base register is used for REX.B, and the high 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bit of op's index register is used for REX.X. 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // REX.W is set and REX.R clear. 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_rex_64(const Operand& op); 1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emit a REX prefix that only sets REX.W to choose a 64-bit operand size. 1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_rex_64() { emit(0x48); } 1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B. 1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // REX.W is clear. 1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_rex_32(Register reg, Register rm_reg); 1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The high bit of reg is used for REX.R, the high bit of op's base 1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register is used for REX.B, and the high bit of op's index register 1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is used for REX.X. REX.W is cleared. 1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_rex_32(Register reg, const Operand& op); 1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // High bit of rm_reg goes to REX.B. 1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // REX.W, REX.R and REX.X are clear. 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_rex_32(Register rm_reg); 1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // High bit of base goes to REX.B and high bit of index to REX.X. 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // REX.W and REX.R are clear. 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_rex_32(const Operand& op); 1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B. 1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // REX.W is cleared. If no REX bits are set, no byte is emitted. 1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_optional_rex_32(Register reg, Register rm_reg); 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The high bit of reg is used for REX.R, the high bit of op's base 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register is used for REX.B, and the high bit of op's index register 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is used for REX.X. REX.W is cleared. If no REX bits are set, nothing 1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is emitted. 1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_optional_rex_32(Register reg, const Operand& op); 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // As for emit_optional_rex_32(Register, Register), except that 1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the registers are XMM registers. 1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_optional_rex_32(XMMRegister reg, XMMRegister base); 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // As for emit_optional_rex_32(Register, Register), except that 12816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // one of the registers is an XMM registers. 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_optional_rex_32(XMMRegister reg, Register base); 1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // As for emit_optional_rex_32(Register, Register), except that 12856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // one of the registers is an XMM registers. 12866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block inline void emit_optional_rex_32(Register reg, XMMRegister base); 12876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // As for emit_optional_rex_32(Register, const Operand&), except that 1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the register is an XMM register. 1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_optional_rex_32(XMMRegister reg, const Operand& op); 1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Optionally do as emit_rex_32(Register) if the register number has 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the high bit set. 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_optional_rex_32(Register rm_reg); 1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Optionally do as emit_rex_32(const Operand&) if the operand register 1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // numbers have a high bit set. 1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_optional_rex_32(const Operand& op); 1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emit the ModR/M byte, and optionally the SIB byte and 1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 1- or 4-byte offset for a memory operand. Also encodes 1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the second operand of the operation, a register or operation 1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // subcode, into the reg field of the ModR/M byte. 1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_operand(Register reg, const Operand& adr) { 1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit_operand(reg.low_bits(), adr); 1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emit the ModR/M byte, and optionally the SIB byte and 1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 1- or 4-byte offset for a memory operand. Also used to encode 1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a three-bit opcode extension into the ModR/M byte. 1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_operand(int rm, const Operand& adr); 1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emit a ModR/M byte with registers coded in the reg and rm_reg fields. 1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_modrm(Register reg, Register rm_reg) { 1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(0xC0 | reg.low_bits() << 3 | rm_reg.low_bits()); 1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emit a ModR/M byte with an operation subcode in the reg field and 1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a register in the rm_reg field. 1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_modrm(int code, Register rm_reg) { 1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_uint3(code)); 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(0xC0 | code << 3 | rm_reg.low_bits()); 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emit the code-object-relative offset of the label's position 1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_code_relative_offset(Label* label); 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emit machine code for one of the operations ADD, ADC, SUB, SBC, 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // AND, OR, XOR, or CMP. The encodings of these operations are all 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // similar, differing just in the opcode or in the reg field of the 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ModR/M byte. 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void arithmetic_op_16(byte opcode, Register reg, Register rm_reg); 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg); 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void arithmetic_op_32(byte opcode, Register reg, Register rm_reg); 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void arithmetic_op_32(byte opcode, Register reg, const Operand& rm_reg); 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void arithmetic_op(byte opcode, Register reg, Register rm_reg); 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void arithmetic_op(byte opcode, Register reg, const Operand& rm_reg); 1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void immediate_arithmetic_op(byte subcode, Register dst, Immediate src); 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void immediate_arithmetic_op(byte subcode, const Operand& dst, Immediate src); 1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Operate on a byte in memory or register. 1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void immediate_arithmetic_op_8(byte subcode, 1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register dst, 1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate src); 1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void immediate_arithmetic_op_8(byte subcode, 1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const Operand& dst, 1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate src); 1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Operate on a word in memory or register. 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void immediate_arithmetic_op_16(byte subcode, 1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register dst, 1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate src); 1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void immediate_arithmetic_op_16(byte subcode, 1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const Operand& dst, 1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate src); 1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Operate on a 32-bit word in memory or register. 1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void immediate_arithmetic_op_32(byte subcode, 1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register dst, 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate src); 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void immediate_arithmetic_op_32(byte subcode, 1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const Operand& dst, 1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate src); 1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emit machine code for a shift operation. 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void shift(Register dst, Immediate shift_amount, int subcode); 1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void shift_32(Register dst, Immediate shift_amount, int subcode); 1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Shift dst by cl % 64 bits. 1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void shift(Register dst, int subcode); 1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void shift_32(Register dst, int subcode); 1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_farith(int b1, int b2, int i); 1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // labels 1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // void print(Label* L); 1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void bind_to(Label* L, int pos); 1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void link_to(Label* L, Label* appendix); 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // record reloc info for current pc_ 1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); 1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block friend class CodePatcher; 1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block friend class EnsureSpace; 1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block friend class RegExpMacroAssemblerX64; 1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Code buffer: 1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The buffer into which code and relocation info are generated. 1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* buffer_; 1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int buffer_size_; 1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // True if the assembler owns the buffer, false if buffer is external. 1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool own_buffer_; 1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // A previously allocated buffer of kMinimalBufferSize bytes, or NULL. 1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static byte* spare_buffer_; 1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code generation 1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* pc_; // the program counter; moves forward 1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfoWriter reloc_info_writer; 1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block List< Handle<Code> > code_targets_; 1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // push-pop elimination 1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* last_pc_; 1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // source position information 1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int current_statement_position_; 1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int current_position_; 1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int written_statement_position_; 1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int written_position_; 1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper class that ensures that there is enough space for generating 1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// instructions and relocation information. The constructor makes 1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// sure that there is enough space and (in debug mode) the destructor 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// checks that we did not generate too much. 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass EnsureSpace BASE_EMBEDDED { 1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) { 1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (assembler_->buffer_overflow()) assembler_->GrowBuffer(); 1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block space_before_ = assembler_->available_space(); 1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ~EnsureSpace() { 1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int bytes_generated = space_before_ - assembler_->available_space(); 1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(bytes_generated < assembler_->kGap); 1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Assembler* assembler_; 1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int space_before_; 1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // V8_X64_ASSEMBLER_X64_H_ 1439