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. 331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Copyright 2011 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 4044f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "isolate.h" 41d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "serialize.h" 42d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CPU Registers. 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 1) We would prefer to use an enum, but enum values are assignment- 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// compatible with int, which has caused code-generation bugs. 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 2) We would prefer to use a class instead of a struct but we don't like 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the register initialization to depend on the particular initialization 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// order (which appears to be different on OS X, Linux, and Windows for the 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// installed versions of C++ we tried). Using a struct permits C-style 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "initialization". Also, the Register objects cannot be const as this 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// forces initialization stubs in MSVC, making us dependent on initialization 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// order. 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 3) By not using an enum, we are possibly preventing the compiler from 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// doing certain constant folds, which may significantly reduce the 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// code generated for some assembly instructions (because they boil down 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to a few constants). If this is a problem, we could change the code 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// such that we use an enum in optimized mode, and the struct in debug 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// mode. This way we get the compile-time error checking in debug mode 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and best performance in optimized code. 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct Register { 681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static const int kNumAllocatableRegisters = 6; 69b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static const int kNumRegisters = 8; 70b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static inline const char* AllocationIndexToString(int index); 72b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static inline int ToAllocationIndex(Register reg); 74b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static inline Register FromAllocationIndex(int index); 76b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 77b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static Register from_code(int code) { 783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(code >= 0); 793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(code < kNumRegisters); 80b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register r = { code }; 81b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return r; 82b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 83b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } 840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool is(Register reg) const { return code_ == reg.code_; } 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax, ebx, ecx and edx are byte registers, the rest are not. 860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool is_byte_register() const { return code_ <= 3; } 870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int code() const { 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_valid()); 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return code_; 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int bit() const { 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_valid()); 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1 << code_; 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Unfortunately we can't make this private in a struct. 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int code_; 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_eax_Code = 0; 1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_ecx_Code = 1; 1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_edx_Code = 2; 1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_ebx_Code = 3; 1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_esp_Code = 4; 1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_ebp_Code = 5; 1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_esi_Code = 6; 1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_edi_Code = 7; 1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst int kRegister_no_reg_Code = -1; 1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register eax = { kRegister_eax_Code }; 1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register ecx = { kRegister_ecx_Code }; 1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register edx = { kRegister_edx_Code }; 1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register ebx = { kRegister_ebx_Code }; 1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register esp = { kRegister_esp_Code }; 1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register ebp = { kRegister_ebp_Code }; 1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register esi = { kRegister_esi_Code }; 1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register edi = { kRegister_edi_Code }; 1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Register no_reg = { kRegister_no_reg_Code }; 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockinline const char* Register::AllocationIndexToString(int index) { 1221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(index >= 0 && index < kNumAllocatableRegisters); 1231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // This is the mapping of allocation indices to registers. 1241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block const char* const kNames[] = { "eax", "ecx", "edx", "ebx", "esi", "edi" }; 1251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return kNames[index]; 1261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 1271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockinline int Register::ToAllocationIndex(Register reg) { 1301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(reg.is_valid() && !reg.is(esp) && !reg.is(ebp)); 1311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return (reg.code() >= 6) ? reg.code() - 2 : reg.code(); 1321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 1331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockinline Register Register::FromAllocationIndex(int index) { 1361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(index >= 0 && index < kNumAllocatableRegisters); 1371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return (index >= 4) ? from_code(index + 2) : from_code(index); 1381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 1391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct XMMRegister { 142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static const int kNumAllocatableRegisters = 7; 143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static const int kNumRegisters = 8; 144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static int ToAllocationIndex(XMMRegister reg) { 146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(reg.code() != 0); 147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return reg.code() - 1; 148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static XMMRegister FromAllocationIndex(int index) { 151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(index >= 0 && index < kNumAllocatableRegisters); 152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return from_code(index + 1); 153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static const char* AllocationIndexToString(int index) { 156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(index >= 0 && index < kNumAllocatableRegisters); 157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const char* const names[] = { 158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "xmm1", 159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "xmm2", 160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "xmm3", 161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "xmm4", 162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "xmm5", 163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "xmm6", 164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "xmm7" 165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch }; 166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return names[index]; 167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static XMMRegister from_code(int code) { 170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch XMMRegister r = { code }; 171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return r; 172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } 175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is(XMMRegister reg) const { return code_ == reg.code_; } 1760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int code() const { 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_valid()); 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return code_; 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int code_; 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm0 = { 0 }; 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm1 = { 1 }; 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm2 = { 2 }; 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm3 = { 3 }; 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm4 = { 4 }; 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm5 = { 5 }; 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm6 = { 6 }; 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst XMMRegister xmm7 = { 7 }; 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochtypedef XMMRegister DoubleRegister; 196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum Condition { 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // any value < 0 is considered no_condition 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block no_condition = -1, 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block overflow = 0, 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block no_overflow = 1, 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block below = 2, 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block above_equal = 3, 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block equal = 4, 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block not_equal = 5, 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block below_equal = 6, 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block above = 7, 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block negative = 8, 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block positive = 9, 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block parity_even = 10, 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block parity_odd = 11, 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block less = 12, 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block greater_equal = 13, 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block less_equal = 14, 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block greater = 15, 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // aliases 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block carry = below, 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block not_carry = above_equal, 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block zero = equal, 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block not_zero = not_equal, 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sign = negative, 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block not_sign = positive 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns the equivalent of !cc. 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Negation of the default no_condition (-1) results in a non-default 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// no_condition value (-2). As long as tests for no_condition check 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// for condition < 0, this will work as expected. 2339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monseninline Condition NegateCondition(Condition cc) { 2349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen return static_cast<Condition>(cc ^ 1); 2359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 2369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Corresponds to transposing the operands of a comparison. 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline Condition ReverseCondition(Condition cc) { 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (cc) { 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case below: 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return above; 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case above: 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return below; 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case above_equal: 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return below_equal; 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case below_equal: 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return above_equal; 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case less: 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return greater; 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case greater: 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return less; 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case greater_equal: 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return less_equal; 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case less_equal: 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return greater_equal; 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return cc; 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------- 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Machine instruction Immediates 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Immediate BASE_EMBEDDED { 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline explicit Immediate(int x); 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline explicit Immediate(const ExternalReference& ext); 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline explicit Immediate(Handle<Object> handle); 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline explicit Immediate(Smi* value); 272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch inline explicit Immediate(Address addr); 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static Immediate CodeRelativeOffset(Label* label) { 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Immediate(label); 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_zero() const { return x_ == 0 && rmode_ == RelocInfo::NONE; } 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_int8() const { 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return -128 <= x_ && x_ < 128 && rmode_ == RelocInfo::NONE; 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_int16() const { 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return -32768 <= x_ && x_ < 32768 && rmode_ == RelocInfo::NONE; 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline explicit Immediate(Label* value); 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int x_; 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode_; 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block friend class Assembler; 293053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block friend class MacroAssembler; 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------- 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Machine instruction Operands 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum ScaleFactor { 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block times_1 = 0, 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block times_2 = 1, 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block times_4 = 2, 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block times_8 = 3, 3054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke times_int_size = times_4, 3064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke times_half_pointer_size = times_2, 307402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu times_pointer_size = times_4, 308402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu times_twice_pointer_size = times_8 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Operand BASE_EMBEDDED { 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 3146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // XMM reg 3156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block INLINE(explicit Operand(XMMRegister xmm_reg)); 3166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [disp/r] 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block INLINE(explicit Operand(int32_t disp, RelocInfo::Mode rmode)); 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // disp only must always be relocated 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [base + disp/r] 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit Operand(Register base, int32_t disp, 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode = RelocInfo::NONE); 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [base + index*scale + disp/r] 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit Operand(Register base, 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register index, 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScaleFactor scale, 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t disp, 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode = RelocInfo::NONE); 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [index*scale + disp/r] 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit Operand(Register index, 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScaleFactor scale, 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t disp, 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::Mode rmode = RelocInfo::NONE); 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static Operand StaticVariable(const ExternalReference& ext) { 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Operand(reinterpret_cast<int32_t>(ext.address()), 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::EXTERNAL_REFERENCE); 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static Operand StaticArray(Register index, 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ScaleFactor scale, 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ExternalReference& arr) { 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Operand(index, scale, reinterpret_cast<int32_t>(arr.address()), 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::EXTERNAL_REFERENCE); 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static Operand Cell(Handle<JSGlobalPropertyCell> cell) { 351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Operand(reinterpret_cast<int32_t>(cell.location()), 352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RelocInfo::GLOBAL_PROPERTY_CELL); 353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns true if this Operand is a wrapper for the specified register. 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_reg(Register reg) const; 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Returns true if this Operand is a wrapper for one register. 3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_reg_only() const; 3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Asserts that this Operand is a wrapper for one register and returns the 3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // register. 3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg() const; 3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // reg 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch INLINE(explicit Operand(Register reg)); 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the ModRM byte without an encoded 'reg' register. The 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register is encoded later as part of the emit_operand operation. 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void set_modrm(int mod, Register rm); 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void set_sib(ScaleFactor scale, Register index, Register base); 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void set_disp8(int8_t disp); 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void set_dispr(int32_t disp, RelocInfo::Mode rmode); 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch byte buf_[6]; 3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The number of bytes in buf_. 3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned int len_; 3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Only valid if len_ > 4. 3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RelocInfo::Mode rmode_; 3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block friend class Assembler; 3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch friend class MacroAssembler; 3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch friend class LCodeGen; 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------- 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A Displacement describes the 32bit immediate field of an instruction which 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// may be used together with a Label in order to refer to a yet unknown code 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// position. Displacements stored in the instruction stream are used to describe 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the instruction and to chain a list of instructions using the same Label. 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A Displacement contains 2 different fields: 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// next field: position of next displacement in the chain (0 = end of list) 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// type field: instruction type 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A next value of null (0) indicates the end of a chain (note that there can 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// be no displacement at position zero, because there is always at least one 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// instruction byte before the displacement). 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Displacement _data field layout 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// |31.....2|1......0| 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// [ next | type | 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Displacement BASE_EMBEDDED { 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block enum Type { 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNCONDITIONAL_JUMP, 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CODE_RELATIVE, 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OTHER 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int data() const { return data_; } 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Type type() const { return TypeField::decode(data_); } 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void next(Label* L) const { 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int n = NextField::decode(data_); 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block n > 0 ? L->link_to(n) : L->Unuse(); 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void link_to(Label* L) { init(L, type()); } 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit Displacement(int data) { data_ = data; } 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Displacement(Label* L, Type type) { init(L, type); } 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void print() { 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("%s (%x) ", (type() == UNCONDITIONAL_JUMP ? "jmp" : "[other]"), 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NextField::decode(data_)); 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int data_; 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block class TypeField: public BitField<Type, 0, 2> {}; 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block class NextField: public BitField<int, 2, 32-2> {}; 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void init(Label* L, Type type); 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CpuFeatures keeps track of which features are supported by the target CPU. 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Supported features must be enabled by a Scope before use. 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Example: 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// if (CpuFeatures::IsSupported(SSE2)) { 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CpuFeatures::Scope fscope(SSE2); 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// // Generate SSE2 floating point code. 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// } else { 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// // Generate standard x87 floating point code. 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// } 4538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass CpuFeatures : public AllStatic { 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 4558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Detect features of the target CPU. Set safe defaults if the serializer 4568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // is enabled (snapshots must be portable). 4578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static void Probe(); 458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check whether a feature is supported by the target CPU. 4608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static bool IsSupported(CpuFeature f) { 4618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(initialized_); 4623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (f == SSE2 && !FLAG_enable_sse2) return false; 4633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (f == SSE3 && !FLAG_enable_sse3) return false; 464f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if (f == SSE4_1 && !FLAG_enable_sse4_1) return false; 4653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (f == CMOV && !FLAG_enable_cmov) return false; 4663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (f == RDTSC && !FLAG_enable_rdtsc) return false; 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return (supported_ & (static_cast<uint64_t>(1) << f)) != 0; 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 4698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 4708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef DEBUG 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check whether a feature is currently enabled. 4728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static bool IsEnabled(CpuFeature f) { 4738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(initialized_); 4748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Isolate* isolate = Isolate::UncheckedCurrent(); 4758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (isolate == NULL) { 4768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // When no isolate is available, work as if we're running in 4778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // release mode. 4788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return IsSupported(f); 4798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 4808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch uint64_t enabled = isolate->enabled_cpu_features(); 4818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return (enabled & (static_cast<uint64_t>(1) << f)) != 0; 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 4838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif 4848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Enable a specified feature within a scope. 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block class Scope BASE_EMBEDDED { 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 488589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 4908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch explicit Scope(CpuFeature f) { 491d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block uint64_t mask = static_cast<uint64_t>(1) << f; 4928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(CpuFeatures::IsSupported(f)); 49344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!Serializer::enabled() || 4948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch (CpuFeatures::found_by_runtime_probing_ & mask) == 0); 4958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch isolate_ = Isolate::UncheckedCurrent(); 4968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch old_enabled_ = 0; 4978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (isolate_ != NULL) { 4988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch old_enabled_ = isolate_->enabled_cpu_features(); 4998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch isolate_->set_enabled_cpu_features(old_enabled_ | mask); 5008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 50144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 50244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ~Scope() { 5038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_); 5048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (isolate_ != NULL) { 5058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch isolate_->set_enabled_cpu_features(old_enabled_); 5068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 508589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 51044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate_; 5118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch uint64_t old_enabled_; 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 513589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 515d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block explicit Scope(CpuFeature f) {} 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 51844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 5198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch class TryForceFeatureScope BASE_EMBEDDED { 5208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch public: 5218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch explicit TryForceFeatureScope(CpuFeature f) 5228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : old_supported_(CpuFeatures::supported_) { 5238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CanForce()) { 5248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CpuFeatures::supported_ |= (static_cast<uint64_t>(1) << f); 5258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 5268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 52744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 5288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ~TryForceFeatureScope() { 5298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CanForce()) { 5308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CpuFeatures::supported_ = old_supported_; 5318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 5328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 53344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 5348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch private: 5358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static bool CanForce() { 5368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // It's only safe to temporarily force support of CPU features 5378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // when there's only a single isolate, which is guaranteed when 5388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // the serializer is enabled. 5398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Serializer::enabled(); 5408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 5418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 5428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch const uint64_t old_supported_; 5438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch }; 5448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 5458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch private: 5468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef DEBUG 5478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static bool initialized_; 5488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif 5498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static uint64_t supported_; 5508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static uint64_t found_by_runtime_probing_; 55144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 55244f0eee88ff00398ff7f715fab053374d808c90dSteve Block DISALLOW_COPY_AND_ASSIGN(CpuFeatures); 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 55644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass Assembler : public AssemblerBase { 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We check before assembling an instruction that there is sufficient 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // space to write an instruction and its relocation information. 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The relocation writer's position must be kGap bytes above the end of 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the generated instructions. This leaves enough space for the 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // longest possible ia32 instruction, 15 bytes, and the longest possible 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // relocation information encoding, RelocInfoWriter::kMaxLength == 16. 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // (There is a 15 byte limit on ia32 instruction length that rules out some 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // otherwise valid instructions.) 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This allows for a single, fast space check per instruction. 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kGap = 32; 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Create an assembler. Instructions and relocation information are emitted 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // into a buffer, with the instructions starting from the beginning and the 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // relocation information starting from the end of the buffer. See CodeDesc 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for a detailed comment on the layout (globals.h). 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the provided buffer is NULL, the assembler allocates and grows its own 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // buffer, and buffer_size determines the initial buffer size. The buffer is 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // owned by the assembler and deallocated upon destruction of the assembler. 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the provided buffer is not NULL, the assembler uses the provided buffer 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for code generation and assumes its size to be buffer_size. If the buffer 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is too small, a fatal error occurs. No deallocation of the buffer is done 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // upon destruction of the assembler. 5838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // TODO(vitalyr): the assembler does not need an isolate. 5848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Assembler(Isolate* isolate, void* buffer, int buffer_size); 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ~Assembler(); 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 58744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Overrides the default provided by FLAG_debug_code. 58844f0eee88ff00398ff7f715fab053374d808c90dSteve Block void set_emit_debug_code(bool value) { emit_debug_code_ = value; } 58944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // GetCode emits any pending (non-emitted) code and fills the descriptor 591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // desc. GetCode() is idempotent; it returns the same result if no other 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Assembler functions are invoked in between GetCode() calls. 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void GetCode(CodeDesc* desc); 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Read/Modify the code target in the branch/call instruction at pc. 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline static Address target_address_at(Address pc); 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline static void set_target_address_at(Address pc, Address target); 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This sets the branch destination (which is in the instruction on x86). 600d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This is for calls and branches within generated code. 6013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline static void deserialization_set_special_target_at( 6023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address instruction_payload, Address target) { 603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block set_target_address_at(instruction_payload, target); 604d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 605d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This sets the branch destination (which is in the instruction on x86). 607d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This is for calls and branches to runtime code. 608d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block inline static void set_external_target_at(Address instruction_payload, 609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Address target) { 610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block set_target_address_at(instruction_payload, target); 611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 6133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kSpecialTargetSize = kPointerSize; 614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Distance between the address of the code target in the call instruction 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // and the return address 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kCallTargetAddressOffset = kPointerSize; 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Distance between start of patched return sequence and the emitted address 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to jump to. 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kPatchReturnSequenceAddressOffset = 1; // JMP imm32. 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Distance between start of patched debug break slot and the emitted address 6237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // to jump to. 6247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch static const int kPatchDebugBreakSlotAddressOffset = 1; // JMP imm32. 6257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static const int kCallInstructionLength = 5; 627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static const int kJSReturnSequenceLength = 6; 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // The debug break slot must be able to contain a call instruction. 6307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch static const int kDebugBreakSlotLength = kCallInstructionLength; 6317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // One byte opcode for test al, 0xXX. 633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static const byte kTestAlByte = 0xA8; 634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // One byte opcode for nop. 635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static const byte kNopByte = 0x90; 636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // One byte opcode for a short unconditional jump. 638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static const byte kJmpShortOpcode = 0xEB; 639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // One byte prefix for a short conditional jump. 640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static const byte kJccShortPrefix = 0x70; 641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static const byte kJncShortOpcode = kJccShortPrefix | not_carry; 642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static const byte kJcShortOpcode = kJccShortPrefix | carry; 643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------------------------------------------------------------- 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Code generation 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // - function names correspond one-to-one to ia32 instruction mnemonics 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // - unless specified otherwise, instructions operate on 32bit operands 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // - instructions on 8bit (byte) operands/registers have a trailing '_b' 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // - instructions on 16bit (word) operands/registers have a trailing '_w' 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // - naming conflicts with C++ keywords are resolved via a trailing '_' 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // NOTE ON INTERFACE: Currently, the interface is not very consistent 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // in the sense that some operations (e.g. mov()) can be called in more 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the one way to generate the same instruction: The Register argument 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // can in some cases be replaced with an Operand(Register) argument. 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This should be cleaned up and made more orthogonal. The questions 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is: should we always use Operands instead of Registers where an 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Operand is possible, or should we have a Register (overloaded) form 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // instead? We must be careful to make sure that the selected instruction 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is obvious from the parameters to avoid hard-to-find code generation 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bugs. 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Insert the smallest number of nop instructions 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // possible to align the pc offset to a multiple 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of m. m must be a power of 2. 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Align(int m); 6683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Nop(int bytes = 1); 6699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Aligns code to something that's optimal for a jump target for the platform. 6709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen void CodeTargetAlign(); 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stack 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void pushad(); 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void popad(); 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void pushfd(); 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void popfd(); 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void push(const Immediate& x); 680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void push_imm32(int32_t imm32); 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void push(Register src); 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void push(const Operand& src); 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void pop(Register dst); 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void pop(const Operand& dst); 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void enter(const Immediate& size); 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void leave(); 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Moves 6913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void mov_b(Register dst, Register src) { mov_b(dst, Operand(src)); } 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov_b(Register dst, const Operand& src); 6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void mov_b(Register dst, int8_t imm8) { mov_b(Operand(dst), imm8); } 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov_b(const Operand& dst, int8_t imm8); 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov_b(const Operand& dst, Register src); 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov_w(Register dst, const Operand& src); 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov_w(const Operand& dst, Register src); 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov(Register dst, int32_t imm32); 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov(Register dst, const Immediate& x); 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov(Register dst, Handle<Object> handle); 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov(Register dst, const Operand& src); 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov(Register dst, Register src); 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov(const Operand& dst, const Immediate& x); 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov(const Operand& dst, Handle<Object> handle); 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mov(const Operand& dst, Register src); 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void movsx_b(Register dst, Register src) { movsx_b(dst, Operand(src)); } 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movsx_b(Register dst, const Operand& src); 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void movsx_w(Register dst, Register src) { movsx_w(dst, Operand(src)); } 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movsx_w(Register dst, const Operand& src); 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void movzx_b(Register dst, Register src) { movzx_b(dst, Operand(src)); } 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movzx_b(Register dst, const Operand& src); 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void movzx_w(Register dst, Register src) { movzx_w(dst, Operand(src)); } 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movzx_w(Register dst, const Operand& src); 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Conditional moves 7223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void cmov(Condition cc, Register dst, Register src) { 7233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cmov(cc, dst, Operand(src)); 7243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmov(Condition cc, Register dst, const Operand& src); 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Flag management. 7286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void cld(); 7296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Repetitive string instructions. 731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void rep_movs(); 7326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void rep_stos(); 733f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke void stos(); 734e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exchange two registers 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void xchg(Register dst, Register src); 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Arithmetics 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void adc(Register dst, int32_t imm32); 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void adc(Register dst, const Operand& src); 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void add(Register dst, Register src) { add(dst, Operand(src)); } 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void add(Register dst, const Operand& src); 7443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void add(const Operand& dst, Register src); 7453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void add(Register dst, const Immediate& imm) { add(Operand(dst), imm); } 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void add(const Operand& dst, const Immediate& x); 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void and_(Register dst, int32_t imm32); 74959151504615d929945dc59db37bf1166937748c6Steve Block void and_(Register dst, const Immediate& x); 7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void and_(Register dst, Register src) { and_(dst, Operand(src)); } 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void and_(Register dst, const Operand& src); 7523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void and_(const Operand& dst, Register src); 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void and_(const Operand& dst, const Immediate& x); 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void cmpb(Register reg, int8_t imm8) { cmpb(Operand(reg), imm8); } 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpb(const Operand& op, int8_t imm8); 7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void cmpb(Register reg, const Operand& op); 7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void cmpb(const Operand& op, Register reg); 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpb_al(const Operand& op); 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpw_ax(const Operand& op); 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmpw(const Operand& op, Immediate imm16); 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmp(Register reg, int32_t imm32); 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmp(Register reg, Handle<Object> handle); 7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void cmp(Register reg0, Register reg1) { cmp(reg0, Operand(reg1)); } 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmp(Register reg, const Operand& op); 7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void cmp(Register reg, const Immediate& imm) { cmp(Operand(reg), imm); } 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmp(const Operand& op, const Immediate& imm); 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cmp(const Operand& op, Handle<Object> handle); 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void dec_b(Register dst); 7710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen void dec_b(const Operand& dst); 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void dec(Register dst); 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void dec(const Operand& dst); 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cdq(); 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void idiv(Register src); 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Signed multiply instructions. 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void imul(Register src); // edx:eax = eax * src. 7823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void imul(Register dst, Register src) { imul(dst, Operand(src)); } 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void imul(Register dst, const Operand& src); // dst = dst * src. 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void imul(Register dst, Register src, int32_t imm32); // dst = src * imm32. 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void inc(Register dst); 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void inc(const Operand& dst); 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void lea(Register dst, const Operand& src); 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Unsigned multiply instruction. 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mul(Register src); // edx:eax = eax * reg. 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void neg(Register dst); 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void not_(Register dst); 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void or_(Register dst, int32_t imm32); 7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void or_(Register dst, Register src) { or_(dst, Operand(src)); } 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void or_(Register dst, const Operand& src); 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void or_(const Operand& dst, Register src); 8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void or_(Register dst, const Immediate& imm) { or_(Operand(dst), imm); } 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void or_(const Operand& dst, const Immediate& x); 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void rcl(Register dst, uint8_t imm8); 806756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick void rcr(Register dst, uint8_t imm8); 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void sar(Register dst, uint8_t imm8); 809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void sar_cl(Register dst); 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void sbb(Register dst, const Operand& src); 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void shld(Register dst, Register src) { shld(dst, Operand(src)); } 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void shld(Register dst, const Operand& src); 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void shl(Register dst, uint8_t imm8); 817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void shl_cl(Register dst); 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void shrd(Register dst, Register src) { shrd(dst, Operand(src)); } 820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void shrd(Register dst, const Operand& src); 821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void shr(Register dst, uint8_t imm8); 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void shr_cl(Register dst); 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void sub(Register dst, const Immediate& imm) { sub(Operand(dst), imm); } 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void sub(const Operand& dst, const Immediate& x); 8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void sub(Register dst, Register src) { sub(dst, Operand(src)); } 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void sub(Register dst, const Operand& src); 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void sub(const Operand& dst, Register src); 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void test(Register reg, const Immediate& imm); 8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void test(Register reg0, Register reg1) { test(reg0, Operand(reg1)); } 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void test(Register reg, const Operand& op); 834e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void test_b(Register reg, const Operand& op); 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void test(const Operand& op, const Immediate& imm); 8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void test_b(Register reg, uint8_t imm8) { test_b(Operand(reg), imm8); } 8377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void test_b(const Operand& op, uint8_t imm8); 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void xor_(Register dst, int32_t imm32); 8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void xor_(Register dst, Register src) { xor_(dst, Operand(src)); } 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void xor_(Register dst, const Operand& src); 8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void xor_(const Operand& dst, Register src); 8433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void xor_(Register dst, const Immediate& imm) { xor_(Operand(dst), imm); } 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void xor_(const Operand& dst, const Immediate& x); 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Bit operations. 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void bt(const Operand& dst, Register src); 8483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void bts(Register dst, Register src) { bts(Operand(dst), src); } 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void bts(const Operand& dst, Register src); 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Miscellaneous 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void hlt(); 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void int3(); 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void nop(); 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void rdtsc(); 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void ret(int imm16); 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Label operations & relative jumps (PPUM Appendix D) 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Takes a branch opcode (cc) and a label (L) and generates 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // either a backward branch or a forward branch and links it 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to the label fixup chain. Usage: 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Label L; // unbound label 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // j(cc, &L); // forward branch to unbound label 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bind(&L); // bind label to the current pc 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // j(cc, &L); // backward branch to bound label 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bind(&L); // illegal: a label may be bound only once 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Note: The same Label can be used for forward and backward branches 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // but it may be bound only once. 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void bind(Label* L); // binds an unbound label L to the current code position 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calls 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void call(Label* L); 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void call(byte* entry, RelocInfo::Mode rmode); 878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int CallSize(const Operand& adr); 8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void call(Register reg) { call(Operand(reg)); } 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void call(const Operand& adr); 881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int CallSize(Handle<Code> code, RelocInfo::Mode mode); 882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void call(Handle<Code> code, 8833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RelocInfo::Mode rmode = RelocInfo::CODE_TARGET, 884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch unsigned ast_id = kNoASTId); 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jumps 887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // unconditional jump to L 888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void jmp(Label* L, Label::Distance distance = Label::kFar); 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void jmp(byte* entry, RelocInfo::Mode rmode); 8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void jmp(Register reg) { jmp(Operand(reg)); } 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void jmp(const Operand& adr); 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void jmp(Handle<Code> code, RelocInfo::Mode rmode); 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Conditional jumps 895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void j(Condition cc, 896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* L, 897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance distance = Label::kFar); 898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void j(Condition cc, byte* entry, RelocInfo::Mode rmode); 899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void j(Condition cc, Handle<Code> code); 9000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Floating-point operations 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fld(int i); 903402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void fstp(int i); 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fld1(); 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fldz(); 907402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void fldpi(); 908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void fldln2(); 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fld_s(const Operand& adr); 911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fld_d(const Operand& adr); 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fstp_s(const Operand& adr); 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fstp_d(const Operand& adr); 915402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void fst_d(const Operand& adr); 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fild_s(const Operand& adr); 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fild_d(const Operand& adr); 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fist_s(const Operand& adr); 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fistp_s(const Operand& adr); 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fistp_d(const Operand& adr); 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // The fisttp instructions require SSE3. 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fisttp_s(const Operand& adr); 927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void fisttp_d(const Operand& adr); 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fabs(); 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fchs(); 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fcos(); 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fsin(); 9333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void fptan(); 934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void fyl2x(); 9353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void f2xm1(); 9363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void fscale(); 9373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void fninit(); 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fadd(int i); 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fsub(int i); 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fmul(int i); 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fdiv(int i); 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fisub_s(const Operand& adr); 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void faddp(int i = 1); 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fsubp(int i = 1); 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fsubrp(int i = 1); 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fmulp(int i = 1); 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fdivp(int i = 1); 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fprem(); 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fprem1(); 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fxch(int i = 1); 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fincstp(); 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void ffree(int i = 0); 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void ftst(); 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fucomp(int i); 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fucompp(); 9613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void fucomi(int i); 9623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block void fucomip(); 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fcompp(); 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fnstsw_ax(); 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fwait(); 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void fnclex(); 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void frndint(); 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void sahf(); 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void setcc(Condition cc, Register reg); 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cpuid(); 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // SSE2 instructions 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cvttss2si(Register dst, const Operand& src); 977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cvttsd2si(Register dst, const Operand& src); 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void cvtsi2sd(XMMRegister dst, Register src) { cvtsi2sd(dst, Operand(src)); } 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void cvtsi2sd(XMMRegister dst, const Operand& src); 9816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void cvtss2sd(XMMRegister dst, XMMRegister src); 98244f0eee88ff00398ff7f715fab053374d808c90dSteve Block void cvtsd2ss(XMMRegister dst, XMMRegister src); 983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void addsd(XMMRegister dst, XMMRegister src); 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void subsd(XMMRegister dst, XMMRegister src); 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void mulsd(XMMRegister dst, XMMRegister src); 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void divsd(XMMRegister dst, XMMRegister src); 988e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void xorpd(XMMRegister dst, XMMRegister src); 989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void xorps(XMMRegister dst, XMMRegister src); 9906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void sqrtsd(XMMRegister dst, XMMRegister src); 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen void andpd(XMMRegister dst, XMMRegister src); 9930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 9946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void ucomisd(XMMRegister dst, XMMRegister src); 9953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void ucomisd(XMMRegister dst, const Operand& src); 99669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 99769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch enum RoundingMode { 99869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch kRoundToNearest = 0x0, 99969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch kRoundDown = 0x1, 100069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch kRoundUp = 0x2, 100169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch kRoundToZero = 0x3 100269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch }; 100369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 100469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode); 100569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 10066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void movmskpd(Register dst, XMMRegister src); 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen void cmpltsd(XMMRegister dst, XMMRegister src); 10090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 10100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen void movaps(XMMRegister dst, XMMRegister src); 10110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 1012e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void movdqa(XMMRegister dst, const Operand& src); 1013e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void movdqa(const Operand& dst, XMMRegister src); 1014e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void movdqu(XMMRegister dst, const Operand& src); 1015e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void movdqu(const Operand& dst, XMMRegister src); 1016e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use either movsd or movlpd. 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movdbl(XMMRegister dst, const Operand& src); 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movdbl(const Operand& dst, XMMRegister src); 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void movd(XMMRegister dst, Register src) { movd(dst, Operand(src)); } 10226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void movd(XMMRegister dst, const Operand& src); 10233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void movd(Register dst, XMMRegister src) { movd(Operand(dst), src); } 10243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void movd(const Operand& dst, XMMRegister src); 10256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void movsd(XMMRegister dst, XMMRegister src); 10266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 102744f0eee88ff00398ff7f715fab053374d808c90dSteve Block void movss(XMMRegister dst, const Operand& src); 10283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void movss(const Operand& dst, XMMRegister src); 102944f0eee88ff00398ff7f715fab053374d808c90dSteve Block void movss(XMMRegister dst, XMMRegister src); 10303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void extractps(Register dst, XMMRegister src, byte imm8); 103144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void pand(XMMRegister dst, XMMRegister src); 10336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void pxor(XMMRegister dst, XMMRegister src); 1034b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch void por(XMMRegister dst, XMMRegister src); 10356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void ptest(XMMRegister dst, XMMRegister src); 10366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void psllq(XMMRegister reg, int8_t shift); 1038b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch void psllq(XMMRegister dst, XMMRegister src); 1039b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch void psrlq(XMMRegister reg, int8_t shift); 1040b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch void psrlq(XMMRegister dst, XMMRegister src); 1041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void pshufd(XMMRegister dst, XMMRegister src, int8_t shuffle); 10423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void pextrd(Register dst, XMMRegister src, int8_t offset) { 10433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pextrd(Operand(dst), src, offset); 10443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void pextrd(const Operand& dst, XMMRegister src, int8_t offset); 10463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void pinsrd(XMMRegister dst, Register src, int8_t offset) { 10473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pinsrd(dst, Operand(src), offset); 10483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 10491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void pinsrd(XMMRegister dst, const Operand& src, int8_t offset); 10500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 10517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Parallel XMM operations. 10523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void movntdqa(XMMRegister dst, const Operand& src); 10537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void movntdq(const Operand& dst, XMMRegister src); 10547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Prefetch src position into cache level. 10557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Level 1, 2 or 3 specifies CPU cache level. Level 0 specifies a 10567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // non-temporal 10577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void prefetch(const Operand& src, int level); 10587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // TODO(lrn): Need SFENCE for movnt? 10597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Debugging 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Print(); 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the code size generated from label to here. 10643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int SizeOfCodeGeneratedSince(Label* label) { 10653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return pc_offset() - label->pos(); 10663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mark address of the ExitJSFrame code. 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void RecordJSReturn(); 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Mark address of a debug break slot. 10727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch void RecordDebugBreakSlot(); 10737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Record a comment relocation entry that can be used by a disassembler. 1075e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Use --code-comments to enable, or provide "force = true" flag to always 1076e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // write a comment. 1077e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void RecordComment(const char* msg, bool force = false); 1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Writes a single byte or word of data in the code stream. Used for 1080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // inline tables, e.g., jump-tables. 1081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void db(uint8_t data); 1082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void dd(uint32_t data); 1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int pc_offset() const { return pc_ - buffer_; } 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if there is less than kGap bytes available in the buffer. 1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If this is the case, we need to grow the buffer before emitting 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // an instruction or relocation information. 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; } 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the number of bytes available in the buffer. 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline int available_space() const { return reloc_info_writer.pos() - pc_; } 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static bool IsNop(Address addr); 10957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 10963e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu PositionsRecorder* positions_recorder() { return &positions_recorder_; } 10973e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 1098e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int relocation_writer_size() { 1099e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return (buffer_ + buffer_size_) - reloc_info_writer.pos(); 1100e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Avoid overflows for displacements etc. 1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kMaximalBufferSize = 512*MB; 1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kMinimalBufferSize = 4*KB; 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch byte byte_at(int pos) { return buffer_[pos]; } 11073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void set_byte_at(int pos, byte value) { buffer_[pos] = value; } 11083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block protected: 111044f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool emit_debug_code() const { return emit_debug_code_; } 111144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movsd(XMMRegister dst, const Operand& src); 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void movsd(const Operand& dst, XMMRegister src); 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_sse_operand(XMMRegister reg, const Operand& adr); 1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_sse_operand(XMMRegister dst, XMMRegister src); 11176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void emit_sse_operand(Register dst, XMMRegister src); 1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 111944f0eee88ff00398ff7f715fab053374d808c90dSteve Block byte* addr_at(int pos) { return buffer_ + pos; } 112044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 11213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t long_at(int pos) { 1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return *reinterpret_cast<uint32_t*>(addr_at(pos)); 1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void long_at_put(int pos, uint32_t x) { 1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *reinterpret_cast<uint32_t*>(addr_at(pos)) = x; 1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code emission 1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void GrowBuffer(); 1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit(uint32_t x); 1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit(Handle<Object> handle); 1134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch inline void emit(uint32_t x, 1135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RelocInfo::Mode rmode, 1136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch unsigned ast_id = kNoASTId); 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit(const Immediate& x); 1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_w(const Immediate& x); 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emit the code-object-relative offset of the label's position 1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_code_relative_offset(Label* label); 1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // instruction generation 1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_arith_b(int op1, int op2, Register dst, int imm8); 1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81) 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // with a given destination expression and an immediate operand. It attempts 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to use the shortest encoding possible. 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sel specifies the /n in the modrm byte (see the Intel PRM). 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_arith(int sel, Operand dst, const Immediate& x); 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_operand(Register reg, const Operand& adr); 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void emit_farith(int b1, int b2, int i); 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // labels 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void print(Label* L); 1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void bind_to(Label* L, int pos); 1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // displacements 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline Displacement disp_at(Label* L); 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void disp_at_put(Label* L, Displacement disp); 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void emit_disp(Label* L, Displacement::Type type); 1164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch inline void emit_near_disp(Label* L); 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // record reloc info for current pc_ 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block friend class CodePatcher; 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block friend class EnsureSpace; 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Code buffer: 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The buffer into which code and relocation info are generated. 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* buffer_; 1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int buffer_size_; 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // True if the assembler owns the buffer, false if buffer is external. 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool own_buffer_; 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code generation 1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* pc_; // the program counter; moves forward 1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfoWriter reloc_info_writer; 1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11833e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu PositionsRecorder positions_recorder_; 11843e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 118544f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool emit_debug_code_; 118644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 11873e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu friend class PositionsRecorder; 1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper class that ensures that there is enough space for generating 1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// instructions and relocation information. The constructor makes 1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// sure that there is enough space and (in debug mode) the destructor 1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// checks that we did not generate too much. 1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass EnsureSpace BASE_EMBEDDED { 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) { 1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (assembler_->overflow()) assembler_->GrowBuffer(); 1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block space_before_ = assembler_->available_space(); 1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ~EnsureSpace() { 1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int bytes_generated = space_before_ - assembler_->available_space(); 1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(bytes_generated < assembler_->kGap); 1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Assembler* assembler_; 1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int space_before_; 1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // V8_IA32_ASSEMBLER_IA32_H_ 1221