assembler-ia32.h revision 9dcf7e2f83591d471e88bf7d230651900b8e424b
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-2008 the V8 project authors. All rights reserved. 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A light-weight IA32 Assembler. 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_IA32_ASSEMBLER_IA32_H_ 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_IA32_ASSEMBLER_IA32_H_ 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 40d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "serialize.h" 41d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CPU Registers. 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 1) We would prefer to use an enum, but enum values are assignment- 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// compatible with int, which has caused code-generation bugs. 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 2) We would prefer to use a class instead of a struct but we don't like 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the register initialization to depend on the particular initialization 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// order (which appears to be different on OS X, Linux, and Windows for the 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// installed versions of C++ we tried). Using a struct permits C-style 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "initialization". Also, the Register objects cannot be const as this 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// forces initialization stubs in MSVC, making us dependent on initialization 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// order. 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 3) By not using an enum, we are possibly preventing the compiler from 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// doing certain constant folds, which may significantly reduce the 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// code generated for some assembly instructions (because they boil down 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to a few constants). If this is a problem, we could change the code 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// such that we use an enum in optimized mode, and the struct in debug 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// mode. This way we get the compile-time error checking in debug mode 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and best performance in optimized code. 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct Register { 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_valid() const { return 0 <= code_ && code_ < 8; } 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is(Register reg) const { return code_ == reg.code_; } 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax, ebx, ecx and edx are byte registers, the rest are not. 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_byte_register() const { return code_ <= 3; } 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int code() const { 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_valid()); 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return code_; 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int bit() const { 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_valid()); 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1 << code_; 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Unfortunately we can't make this private in a struct. 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int code_; 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst Register eax = { 0 }; 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst Register ecx = { 1 }; 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst Register edx = { 2 }; 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst Register ebx = { 3 }; 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst Register esp = { 4 }; 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst Register ebp = { 5 }; 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst Register esi = { 6 }; 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst Register edi = { 7 }; 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst Register no_reg = { -1 }; 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct XMMRegister { 966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool is_valid() const { return 0 <= code_ && code_ < 8; } 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int code() const { 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_valid()); 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return code_; 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int code_; 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm0 = { 0 }; 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm1 = { 1 }; 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm2 = { 2 }; 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm3 = { 3 }; 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm4 = { 4 }; 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm5 = { 5 }; 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm6 = { 6 }; 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm7 = { 7 }; 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum Condition { 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // any value < 0 is considered no_condition 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block no_condition = -1, 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block overflow = 0, 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block no_overflow = 1, 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block below = 2, 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block above_equal = 3, 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block equal = 4, 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block not_equal = 5, 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block below_equal = 6, 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block above = 7, 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block negative = 8, 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block positive = 9, 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block parity_even = 10, 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block parity_odd = 11, 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block less = 12, 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block greater_equal = 13, 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block less_equal = 14, 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block greater = 15, 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // aliases 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block carry = below, 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block not_carry = above_equal, 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block zero = equal, 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block not_zero = not_equal, 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sign = negative, 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block not_sign = positive 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns the equivalent of !cc. 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Negation of the default no_condition (-1) results in a non-default 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// no_condition value (-2). As long as tests for no_condition check 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// for condition < 0, this will work as expected. 1499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monseninline Condition NegateCondition(Condition cc) { 1509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen return static_cast<Condition>(cc ^ 1); 1519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 1529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Corresponds to transposing the operands of a comparison. 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline Condition ReverseCondition(Condition cc) { 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (cc) { 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case below: 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return above; 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case above: 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return below; 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case above_equal: 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return below_equal; 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case below_equal: 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return above_equal; 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case less: 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return greater; 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case greater: 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return less; 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case greater_equal: 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return less_equal; 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case less_equal: 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return greater_equal; 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return cc; 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum Hint { 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block no_hint = 0, 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block not_taken = 0x2e, 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block taken = 0x3e 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The result of negating a hint is as if the corresponding condition 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// were negated by NegateCondition. That is, no_hint is mapped to 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// itself and not_taken and taken are mapped to each other. 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline Hint NegateHint(Hint hint) { 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return (hint == no_hint) 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ? no_hint 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : ((hint == not_taken) ? taken : not_taken); 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------- 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Machine instruction Immediates 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Immediate BASE_EMBEDDED { 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline explicit Immediate(int x); 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline explicit Immediate(const ExternalReference& ext); 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline explicit Immediate(Handle<Object> handle); 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline explicit Immediate(Smi* value); 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static Immediate CodeRelativeOffset(Label* label) { 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Immediate(label); 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_zero() const { return x_ == 0 && rmode_ == RelocInfo::NONE; } 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_int8() const { 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return -128 <= x_ && x_ < 128 && rmode_ == RelocInfo::NONE; 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_int16() const { 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return -32768 <= x_ && x_ < 32768 && rmode_ == RelocInfo::NONE; 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline explicit Immediate(Label* value); 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int x_; 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode_; 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block friend class Assembler; 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------- 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Machine instruction Operands 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum ScaleFactor { 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block times_1 = 0, 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block times_2 = 1, 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block times_4 = 2, 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block times_8 = 3, 2364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke times_int_size = times_4, 2374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke times_half_pointer_size = times_2, 238402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu times_pointer_size = times_4, 239402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu times_twice_pointer_size = times_8 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Operand BASE_EMBEDDED { 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // reg 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block INLINE(explicit Operand(Register reg)); 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // XMM reg 2496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block INLINE(explicit Operand(XMMRegister xmm_reg)); 2506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [disp/r] 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block INLINE(explicit Operand(int32_t disp, RelocInfo::Mode rmode)); 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // disp only must always be relocated 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [base + disp/r] 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit Operand(Register base, int32_t disp, 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode = RelocInfo::NONE); 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [base + index*scale + disp/r] 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit Operand(Register base, 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register index, 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScaleFactor scale, 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t disp, 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode = RelocInfo::NONE); 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [index*scale + disp/r] 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit Operand(Register index, 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScaleFactor scale, 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t disp, 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode = RelocInfo::NONE); 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static Operand StaticVariable(const ExternalReference& ext) { 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Operand(reinterpret_cast<int32_t>(ext.address()), 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::EXTERNAL_REFERENCE); 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static Operand StaticArray(Register index, 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScaleFactor scale, 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ExternalReference& arr) { 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Operand(index, scale, reinterpret_cast<int32_t>(arr.address()), 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::EXTERNAL_REFERENCE); 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns true if this Operand is a wrapper for the specified register. 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_reg(Register reg) const; 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte buf_[6]; 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The number of bytes in buf_. 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned int len_; 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Only valid if len_ > 4. 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode_; 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the ModRM byte without an encoded 'reg' register. The 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register is encoded later as part of the emit_operand operation. 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void set_modrm(int mod, Register rm); 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void set_sib(ScaleFactor scale, Register index, Register base); 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void set_disp8(int8_t disp); 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void set_dispr(int32_t disp, RelocInfo::Mode rmode); 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block friend class Assembler; 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------- 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A Displacement describes the 32bit immediate field of an instruction which 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// may be used together with a Label in order to refer to a yet unknown code 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// position. Displacements stored in the instruction stream are used to describe 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the instruction and to chain a list of instructions using the same Label. 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A Displacement contains 2 different fields: 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// next field: position of next displacement in the chain (0 = end of list) 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// type field: instruction type 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A next value of null (0) indicates the end of a chain (note that there can 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// be no displacement at position zero, because there is always at least one 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// instruction byte before the displacement). 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Displacement _data field layout 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// |31.....2|1......0| 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// [ next | type | 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Displacement BASE_EMBEDDED { 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block enum Type { 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNCONDITIONAL_JUMP, 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CODE_RELATIVE, 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OTHER 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int data() const { return data_; } 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Type type() const { return TypeField::decode(data_); } 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void next(Label* L) const { 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int n = NextField::decode(data_); 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block n > 0 ? L->link_to(n) : L->Unuse(); 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void link_to(Label* L) { init(L, type()); } 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit Displacement(int data) { data_ = data; } 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Displacement(Label* L, Type type) { init(L, type); } 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void print() { 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("%s (%x) ", (type() == UNCONDITIONAL_JUMP ? "jmp" : "[other]"), 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NextField::decode(data_)); 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int data_; 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block class TypeField: public BitField<Type, 0, 2> {}; 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block class NextField: public BitField<int, 2, 32-2> {}; 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void init(Label* L, Type type); 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CpuFeatures keeps track of which features are supported by the target CPU. 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Supported features must be enabled by a Scope before use. 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Example: 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// if (CpuFeatures::IsSupported(SSE2)) { 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CpuFeatures::Scope fscope(SSE2); 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// // Generate SSE2 floating point code. 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// } else { 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// // Generate standard x87 floating point code. 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// } 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CpuFeatures : public AllStatic { 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Detect features of the target CPU. Set safe defaults if the serializer 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is enabled (snapshots must be portable). 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static void Probe(); 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check whether a feature is supported by the target CPU. 376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static bool IsSupported(CpuFeature f) { 3773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (f == SSE2 && !FLAG_enable_sse2) return false; 3783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (f == SSE3 && !FLAG_enable_sse3) return false; 3793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (f == CMOV && !FLAG_enable_cmov) return false; 3803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (f == RDTSC && !FLAG_enable_rdtsc) return false; 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return (supported_ & (static_cast<uint64_t>(1) << f)) != 0; 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check whether a feature is currently enabled. 384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static bool IsEnabled(CpuFeature f) { 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return (enabled_ & (static_cast<uint64_t>(1) << f)) != 0; 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Enable a specified feature within a scope. 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block class Scope BASE_EMBEDDED { 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block explicit Scope(CpuFeature f) { 392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block uint64_t mask = static_cast<uint64_t>(1) << f; 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(CpuFeatures::IsSupported(f)); 394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(!Serializer::enabled() || (found_by_runtime_probing_ & mask) == 0); 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block old_enabled_ = CpuFeatures::enabled_; 396d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CpuFeatures::enabled_ |= mask; 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ~Scope() { CpuFeatures::enabled_ = old_enabled_; } 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint64_t old_enabled_; 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 403d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block explicit Scope(CpuFeature f) {} 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static uint64_t supported_; 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static uint64_t enabled_; 409d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static uint64_t found_by_runtime_probing_; 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Assembler : public Malloced { 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We check before assembling an instruction that there is sufficient 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // space to write an instruction and its relocation information. 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The relocation writer's position must be kGap bytes above the end of 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the generated instructions. This leaves enough space for the 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // longest possible ia32 instruction, 15 bytes, and the longest possible 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // relocation information encoding, RelocInfoWriter::kMaxLength == 16. 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // (There is a 15 byte limit on ia32 instruction length that rules out some 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // otherwise valid instructions.) 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This allows for a single, fast space check per instruction. 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kGap = 32; 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Create an assembler. Instructions and relocation information are emitted 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // into a buffer, with the instructions starting from the beginning and the 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // relocation information starting from the end of the buffer. See CodeDesc 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for a detailed comment on the layout (globals.h). 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the provided buffer is NULL, the assembler allocates and grows its own 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // buffer, and buffer_size determines the initial buffer size. The buffer is 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // owned by the assembler and deallocated upon destruction of the assembler. 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the provided buffer is not NULL, the assembler uses the provided buffer 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for code generation and assumes its size to be buffer_size. If the buffer 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is too small, a fatal error occurs. No deallocation of the buffer is done 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // upon destruction of the assembler. 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Assembler(void* buffer, int buffer_size); 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ~Assembler(); 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // GetCode emits any pending (non-emitted) code and fills the descriptor 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // desc. GetCode() is idempotent; it returns the same result if no other 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Assembler functions are invoked in between GetCode() calls. 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void GetCode(CodeDesc* desc); 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Read/Modify the code target in the branch/call instruction at pc. 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline static Address target_address_at(Address pc); 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline static void set_target_address_at(Address pc, Address target); 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 452d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This sets the branch destination (which is in the instruction on x86). 453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This is for calls and branches within generated code. 454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block inline static void set_target_at(Address instruction_payload, 455d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Address target) { 456d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block set_target_address_at(instruction_payload, target); 457d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This sets the branch destination (which is in the instruction on x86). 460d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This is for calls and branches to runtime code. 461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block inline static void set_external_target_at(Address instruction_payload, 462d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Address target) { 463d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block set_target_address_at(instruction_payload, target); 464d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 465d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 466d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static const int kCallTargetSize = kPointerSize; 467d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static const int kExternalTargetSize = kPointerSize; 468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Distance between the address of the code target in the call instruction 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // and the return address 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kCallTargetAddressOffset = kPointerSize; 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Distance between start of patched return sequence and the emitted address 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to jump to. 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kPatchReturnSequenceAddressOffset = 1; // JMP imm32. 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Distance between start of patched debug break slot and the emitted address 4777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // to jump to. 4787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch static const int kPatchDebugBreakSlotAddressOffset = 1; // JMP imm32. 4797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 480d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static const int kCallInstructionLength = 5; 481d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static const int kJSReturnSequenceLength = 6; 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // The debug break slot must be able to contain a call instruction. 4847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch static const int kDebugBreakSlotLength = kCallInstructionLength; 4857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Code generation 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // - function names correspond one-to-one to ia32 instruction mnemonics 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // - unless specified otherwise, instructions operate on 32bit operands 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // - instructions on 8bit (byte) operands/registers have a trailing '_b' 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // - instructions on 16bit (word) operands/registers have a trailing '_w' 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // - naming conflicts with C++ keywords are resolved via a trailing '_' 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // NOTE ON INTERFACE: Currently, the interface is not very consistent 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // in the sense that some operations (e.g. mov()) can be called in more 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the one way to generate the same instruction: The Register argument 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // can in some cases be replaced with an Operand(Register) argument. 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This should be cleaned up and made more orthogonal. The questions 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is: should we always use Operands instead of Registers where an 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Operand is possible, or should we have a Register (overloaded) form 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // instead? We must be careful to make sure that the selected instruction 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is obvious from the parameters to avoid hard-to-find code generation 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bugs. 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Insert the smallest number of nop instructions 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // possible to align the pc offset to a multiple 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of m. m must be a power of 2. 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Align(int m); 5109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Aligns code to something that's optimal for a jump target for the platform. 5119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen void CodeTargetAlign(); 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stack 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void pushad(); 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void popad(); 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void pushfd(); 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void popfd(); 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void push(const Immediate& x); 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void push(Register src); 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void push(const Operand& src); 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void push(Label* label, RelocInfo::Mode relocation_mode); 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void pop(Register dst); 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void pop(const Operand& dst); 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void enter(const Immediate& size); 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void leave(); 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Moves 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov_b(Register dst, const Operand& src); 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov_b(const Operand& dst, int8_t imm8); 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov_b(const Operand& dst, Register src); 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov_w(Register dst, const Operand& src); 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov_w(const Operand& dst, Register src); 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov(Register dst, int32_t imm32); 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov(Register dst, const Immediate& x); 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov(Register dst, Handle<Object> handle); 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov(Register dst, const Operand& src); 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov(Register dst, Register src); 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov(const Operand& dst, const Immediate& x); 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov(const Operand& dst, Handle<Object> handle); 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov(const Operand& dst, Register src); 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movsx_b(Register dst, const Operand& src); 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movsx_w(Register dst, const Operand& src); 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movzx_b(Register dst, const Operand& src); 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movzx_w(Register dst, const Operand& src); 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Conditional moves 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmov(Condition cc, Register dst, int32_t imm32); 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmov(Condition cc, Register dst, Handle<Object> handle); 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmov(Condition cc, Register dst, const Operand& src); 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Flag management. 5626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void cld(); 5636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 564e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Repetitive string instructions. 565e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void rep_movs(); 5666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void rep_stos(); 567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke void stos(); 568e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exchange two registers 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void xchg(Register dst, Register src); 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Arithmetics 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void adc(Register dst, int32_t imm32); 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void adc(Register dst, const Operand& src); 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void add(Register dst, const Operand& src); 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void add(const Operand& dst, const Immediate& x); 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void and_(Register dst, int32_t imm32); 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void and_(Register dst, const Operand& src); 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void and_(const Operand& src, Register dst); 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void and_(const Operand& dst, const Immediate& x); 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpb(const Operand& op, int8_t imm8); 585d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void cmpb(Register src, const Operand& dst); 586d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void cmpb(const Operand& dst, Register src); 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpb_al(const Operand& op); 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpw_ax(const Operand& op); 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpw(const Operand& op, Immediate imm16); 590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmp(Register reg, int32_t imm32); 591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmp(Register reg, Handle<Object> handle); 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmp(Register reg, const Operand& op); 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmp(const Operand& op, const Immediate& imm); 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmp(const Operand& op, Handle<Object> handle); 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void dec_b(Register dst); 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void dec(Register dst); 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void dec(const Operand& dst); 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cdq(); 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void idiv(Register src); 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Signed multiply instructions. 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void imul(Register src); // edx:eax = eax * src. 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void imul(Register dst, const Operand& src); // dst = dst * src. 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void imul(Register dst, Register src, int32_t imm32); // dst = src * imm32. 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void inc(Register dst); 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void inc(const Operand& dst); 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void lea(Register dst, const Operand& src); 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Unsigned multiply instruction. 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mul(Register src); // edx:eax = eax * reg. 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void neg(Register dst); 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void not_(Register dst); 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void or_(Register dst, int32_t imm32); 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void or_(Register dst, const Operand& src); 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void or_(const Operand& dst, Register src); 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void or_(const Operand& dst, const Immediate& x); 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void rcl(Register dst, uint8_t imm8); 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void sar(Register dst, uint8_t imm8); 630d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void sar_cl(Register dst); 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void sbb(Register dst, const Operand& src); 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void shld(Register dst, const Operand& src); 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void shl(Register dst, uint8_t imm8); 637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void shl_cl(Register dst); 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void shrd(Register dst, const Operand& src); 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void shr(Register dst, uint8_t imm8); 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void shr_cl(Register dst); 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void subb(const Operand& dst, int8_t imm8); 645e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void subb(Register dst, const Operand& src); 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void sub(const Operand& dst, const Immediate& x); 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void sub(Register dst, const Operand& src); 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void sub(const Operand& dst, Register src); 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void test(Register reg, const Immediate& imm); 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void test(Register reg, const Operand& op); 652e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void test_b(Register reg, const Operand& op); 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void test(const Operand& op, const Immediate& imm); 6547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void test_b(const Operand& op, uint8_t imm8); 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void xor_(Register dst, int32_t imm32); 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void xor_(Register dst, const Operand& src); 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void xor_(const Operand& src, Register dst); 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void xor_(const Operand& dst, const Immediate& x); 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Bit operations. 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void bt(const Operand& dst, Register src); 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void bts(const Operand& dst, Register src); 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Miscellaneous 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void hlt(); 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void int3(); 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void nop(); 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void rdtsc(); 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void ret(int imm16); 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Label operations & relative jumps (PPUM Appendix D) 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Takes a branch opcode (cc) and a label (L) and generates 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // either a backward branch or a forward branch and links it 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to the label fixup chain. Usage: 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Label L; // unbound label 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // j(cc, &L); // forward branch to unbound label 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bind(&L); // bind label to the current pc 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // j(cc, &L); // backward branch to bound label 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bind(&L); // illegal: a label may be bound only once 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Note: The same Label can be used for forward and backward branches 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // but it may be bound only once. 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void bind(Label* L); // binds an unbound label L to the current code position 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calls 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void call(Label* L); 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void call(byte* entry, RelocInfo::Mode rmode); 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void call(const Operand& adr); 693402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void call(const ExternalReference& target); 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void call(Handle<Code> code, RelocInfo::Mode rmode); 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jumps 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void jmp(Label* L); // unconditional jump to L 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void jmp(byte* entry, RelocInfo::Mode rmode); 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void jmp(const Operand& adr); 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void jmp(Handle<Code> code, RelocInfo::Mode rmode); 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Conditional jumps 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void j(Condition cc, Label* L, Hint hint = no_hint); 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void j(Condition cc, byte* entry, RelocInfo::Mode rmode, Hint hint = no_hint); 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void j(Condition cc, Handle<Code> code, Hint hint = no_hint); 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Floating-point operations 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fld(int i); 709402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void fstp(int i); 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fld1(); 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fldz(); 713402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void fldpi(); 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fld_s(const Operand& adr); 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fld_d(const Operand& adr); 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fstp_s(const Operand& adr); 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fstp_d(const Operand& adr); 720402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void fst_d(const Operand& adr); 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fild_s(const Operand& adr); 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fild_d(const Operand& adr); 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fist_s(const Operand& adr); 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fistp_s(const Operand& adr); 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fistp_d(const Operand& adr); 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // The fisttp instructions require SSE3. 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fisttp_s(const Operand& adr); 732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void fisttp_d(const Operand& adr); 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fabs(); 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fchs(); 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fcos(); 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fsin(); 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fadd(int i); 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fsub(int i); 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fmul(int i); 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fdiv(int i); 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fisub_s(const Operand& adr); 745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void faddp(int i = 1); 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fsubp(int i = 1); 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fsubrp(int i = 1); 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fmulp(int i = 1); 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fdivp(int i = 1); 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fprem(); 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fprem1(); 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fxch(int i = 1); 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fincstp(); 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void ffree(int i = 0); 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void ftst(); 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fucomp(int i); 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fucompp(); 7613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void fucomi(int i); 7623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void fucomip(); 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fcompp(); 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fnstsw_ax(); 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fwait(); 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fnclex(); 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void frndint(); 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void sahf(); 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void setcc(Condition cc, Register reg); 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cpuid(); 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // SSE2 instructions 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cvttss2si(Register dst, const Operand& src); 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cvttsd2si(Register dst, const Operand& src); 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cvtsi2sd(XMMRegister dst, const Operand& src); 7806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void cvtss2sd(XMMRegister dst, XMMRegister src); 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void addsd(XMMRegister dst, XMMRegister src); 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void subsd(XMMRegister dst, XMMRegister src); 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mulsd(XMMRegister dst, XMMRegister src); 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void divsd(XMMRegister dst, XMMRegister src); 786e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void xorpd(XMMRegister dst, XMMRegister src); 7876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void sqrtsd(XMMRegister dst, XMMRegister src); 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void ucomisd(XMMRegister dst, XMMRegister src); 7906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void movmskpd(Register dst, XMMRegister src); 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 792e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void movdqa(XMMRegister dst, const Operand& src); 793e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void movdqa(const Operand& dst, XMMRegister src); 794e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void movdqu(XMMRegister dst, const Operand& src); 795e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void movdqu(const Operand& dst, XMMRegister src); 796e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use either movsd or movlpd. 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movdbl(XMMRegister dst, const Operand& src); 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movdbl(const Operand& dst, XMMRegister src); 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void movd(XMMRegister dst, const Operand& src); 8026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void movsd(XMMRegister dst, XMMRegister src); 8036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void pxor(XMMRegister dst, XMMRegister src); 8056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void ptest(XMMRegister dst, XMMRegister src); 8066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Parallel XMM operations. 8087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void movntdqa(XMMRegister src, const Operand& dst); 8097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void movntdq(const Operand& dst, XMMRegister src); 8107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Prefetch src position into cache level. 8117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Level 1, 2 or 3 specifies CPU cache level. Level 0 specifies a 8127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // non-temporal 8137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void prefetch(const Operand& src, int level); 8147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // TODO(lrn): Need SFENCE for movnt? 8157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Debugging 817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Print(); 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the code size generated from label to here. 820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int SizeOfCodeGeneratedSince(Label* l) { return pc_offset() - l->pos(); } 821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mark address of the ExitJSFrame code. 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void RecordJSReturn(); 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Mark address of a debug break slot. 8267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void RecordDebugBreakSlot(); 8277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Record a comment relocation entry that can be used by a disassembler. 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use --debug_code to enable. 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void RecordComment(const char* msg); 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void RecordPosition(int pos); 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void RecordStatementPosition(int pos); 8347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch bool WriteRecordedPositions(); 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Writes a single word of data in the code stream. 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Used for inline tables, e.g., jump-tables. 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void dd(uint32_t data, RelocInfo::Mode reloc_info); 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int pc_offset() const { return pc_ - buffer_; } 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int current_statement_position() const { return current_statement_position_; } 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int current_position() const { return current_position_; } 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if there is less than kGap bytes available in the buffer. 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If this is the case, we need to grow the buffer before emitting 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // an instruction or relocation information. 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; } 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the number of bytes available in the buffer. 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline int available_space() const { return reloc_info_writer.pos() - pc_; } 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch static bool IsNop(Address addr) { return *addr == 0x90; } 8537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Avoid overflows for displacements etc. 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kMaximalBufferSize = 512*MB; 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kMinimalBufferSize = 4*KB; 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block protected: 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movsd(XMMRegister dst, const Operand& src); 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movsd(const Operand& dst, XMMRegister src); 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_sse_operand(XMMRegister reg, const Operand& adr); 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_sse_operand(XMMRegister dst, XMMRegister src); 8646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void emit_sse_operand(Register dst, XMMRegister src); 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* addr_at(int pos) { return buffer_ + pos; } 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte byte_at(int pos) { return buffer_[pos]; } 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t long_at(int pos) { 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return *reinterpret_cast<uint32_t*>(addr_at(pos)); 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void long_at_put(int pos, uint32_t x) { 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *reinterpret_cast<uint32_t*>(addr_at(pos)) = x; 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code emission 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void GrowBuffer(); 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit(uint32_t x); 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit(Handle<Object> handle); 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit(uint32_t x, RelocInfo::Mode rmode); 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit(const Immediate& x); 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_w(const Immediate& x); 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emit the code-object-relative offset of the label's position 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_code_relative_offset(Label* label); 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // instruction generation 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_arith_b(int op1, int op2, Register dst, int imm8); 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81) 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // with a given destination expression and an immediate operand. It attempts 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to use the shortest encoding possible. 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sel specifies the /n in the modrm byte (see the Intel PRM). 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_arith(int sel, Operand dst, const Immediate& x); 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_operand(Register reg, const Operand& adr); 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_farith(int b1, int b2, int i); 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // labels 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void print(Label* L); 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void bind_to(Label* L, int pos); 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void link_to(Label* L, Label* appendix); 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // displacements 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline Displacement disp_at(Label* L); 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void disp_at_put(Label* L, Displacement disp); 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_disp(Label* L, Displacement::Type type); 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // record reloc info for current pc_ 911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block friend class CodePatcher; 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block friend class EnsureSpace; 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Code buffer: 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The buffer into which code and relocation info are generated. 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* buffer_; 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int buffer_size_; 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // True if the assembler owns the buffer, false if buffer is external. 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool own_buffer_; 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // A previously allocated buffer of kMinimalBufferSize bytes, or NULL. 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static byte* spare_buffer_; 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code generation 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* pc_; // the program counter; moves forward 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfoWriter reloc_info_writer; 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // push-pop elimination 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* last_pc_; 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // source position information 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int current_statement_position_; 934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int current_position_; 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int written_statement_position_; 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int written_position_; 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper class that ensures that there is enough space for generating 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// instructions and relocation information. The constructor makes 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// sure that there is enough space and (in debug mode) the destructor 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// checks that we did not generate too much. 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass EnsureSpace BASE_EMBEDDED { 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) { 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (assembler_->overflow()) assembler_->GrowBuffer(); 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block space_before_ = assembler_->available_space(); 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ~EnsureSpace() { 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int bytes_generated = space_before_ - assembler_->available_space(); 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(bytes_generated < assembler_->kGap); 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Assembler* assembler_; 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int space_before_; 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // V8_IA32_ASSEMBLER_IA32_H_ 970