13100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Copyright (c) 1994-2006 Sun Microsystems Inc. 23100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// All Rights Reserved. 33100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// 43100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Redistribution and use in source and binary forms, with or without 53100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// modification, are permitted provided that the following conditions are 63100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// met: 73100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// 83100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// - Redistributions of source code must retain the above copyright notice, 93100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// this list of conditions and the following disclaimer. 103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// 113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// - Redistribution in binary form must reproduce the above copyright 123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// notice, this list of conditions and the following disclaimer in the 133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// documentation and/or other materials provided with the distribution. 143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// 153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// - Neither the name of Sun Microsystems or the names of contributors may 163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// be used to endorse or promote products derived from this software without 173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// specific prior written permission. 183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// 193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// The original source code covered by the above license above has been 323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// modified significantly by Google Inc. 333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#ifndef V8_MIPS_ASSEMBLER_MIPS_H_ 373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define V8_MIPS_ASSEMBLER_MIPS_H_ 383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include <stdio.h> 403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "assembler.h" 413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "constants-mips.h" 423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "serialize.h" 433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace v8 { 453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace internal { 463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// CPU Registers. 483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// 493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// 1) We would prefer to use an enum, but enum values are assignment- 503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// compatible with int, which has caused code-generation bugs. 513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// 523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// 2) We would prefer to use a class instead of a struct but we don't like 533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// the register initialization to depend on the particular initialization 543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// order (which appears to be different on OS X, Linux, and Windows for the 553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// installed versions of C++ we tried). Using a struct permits C-style 563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// "initialization". Also, the Register objects cannot be const as this 573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// forces initialization stubs in MSVC, making us dependent on initialization 583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// order. 593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// 603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// 3) By not using an enum, we are possibly preventing the compiler from 613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// doing certain constant folds, which may significantly reduce the 623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// code generated for some assembly instructions (because they boil down 633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// to a few constants). If this is a problem, we could change the code 643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// such that we use an enum in optimized mode, and the struct in debug 653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// mode. This way we get the compile-time error checking in debug mode 663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// and best performance in optimized code. 673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// ----------------------------------------------------------------------------- 70257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Implementation of Register and FPURegister. 713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Core register. 733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescustruct Register { 7444f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kNumRegisters = v8::internal::kNumRegisters; 75257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kNumAllocatableRegisters = 14; // v0 through t7. 76257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kSizeInBytes = 4; 7744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 7844f0eee88ff00398ff7f715fab053374d808c90dSteve Block static int ToAllocationIndex(Register reg) { 7944f0eee88ff00398ff7f715fab053374d808c90dSteve Block return reg.code() - 2; // zero_reg and 'at' are skipped. 8044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 8144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8244f0eee88ff00398ff7f715fab053374d808c90dSteve Block static Register FromAllocationIndex(int index) { 8344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(index >= 0 && index < kNumAllocatableRegisters); 8444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return from_code(index + 2); // zero_reg and 'at' are skipped. 8544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 8644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8744f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const char* AllocationIndexToString(int index) { 8844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(index >= 0 && index < kNumAllocatableRegisters); 8944f0eee88ff00398ff7f715fab053374d808c90dSteve Block const char* const names[] = { 9044f0eee88ff00398ff7f715fab053374d808c90dSteve Block "v0", 9144f0eee88ff00398ff7f715fab053374d808c90dSteve Block "v1", 9244f0eee88ff00398ff7f715fab053374d808c90dSteve Block "a0", 9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block "a1", 9444f0eee88ff00398ff7f715fab053374d808c90dSteve Block "a2", 9544f0eee88ff00398ff7f715fab053374d808c90dSteve Block "a3", 9644f0eee88ff00398ff7f715fab053374d808c90dSteve Block "t0", 9744f0eee88ff00398ff7f715fab053374d808c90dSteve Block "t1", 9844f0eee88ff00398ff7f715fab053374d808c90dSteve Block "t2", 9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block "t3", 10044f0eee88ff00398ff7f715fab053374d808c90dSteve Block "t4", 10144f0eee88ff00398ff7f715fab053374d808c90dSteve Block "t5", 10244f0eee88ff00398ff7f715fab053374d808c90dSteve Block "t6", 10344f0eee88ff00398ff7f715fab053374d808c90dSteve Block "t7", 10444f0eee88ff00398ff7f715fab053374d808c90dSteve Block }; 10544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return names[index]; 10644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 10744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 10844f0eee88ff00398ff7f715fab053374d808c90dSteve Block static Register from_code(int code) { 10944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register r = { code }; 11044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return r; 11144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 11244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } 1140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool is(Register reg) const { return code_ == reg.code_; } 1150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int code() const { 1163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(is_valid()); 1173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return code_; 1183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 1190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int bit() const { 1203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(is_valid()); 1213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return 1 << code_; 1223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 1233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Unfortunately we can't make this private in a struct. 1253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int code_; 1263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}; 1273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 128db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch#define REGISTER(N, C) \ 129db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch const int kRegister_ ## N ## _Code = C; \ 130db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch const Register N = { C } 131db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch 132db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(no_reg, -1); 133db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// Always zero. 134db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(zero_reg, 0); 135db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// at: Reserved for synthetic instructions. 136db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(at, 1); 137db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// v0, v1: Used when returning multiple values from subroutines. 138db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(v0, 2); 139db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(v1, 3); 140db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// a0 - a4: Used to pass non-FP parameters. 141db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(a0, 4); 142db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(a1, 5); 143db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(a2, 6); 144db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(a3, 7); 145db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// t0 - t9: Can be used without reservation, act as temporary registers and are 146db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// allowed to be destroyed by subroutines. 147db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(t0, 8); 148db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(t1, 9); 149db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(t2, 10); 150db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(t3, 11); 151db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(t4, 12); 152db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(t5, 13); 153db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(t6, 14); 154db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(t7, 15); 155db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// s0 - s7: Subroutine register variables. Subroutines that write to these 156db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// registers must restore their values before exiting so that the caller can 157db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// expect the values to be preserved. 158db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(s0, 16); 159db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(s1, 17); 160db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(s2, 18); 161db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(s3, 19); 162db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(s4, 20); 163db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(s5, 21); 164db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(s6, 22); 165db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(s7, 23); 166db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(t8, 24); 167db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(t9, 25); 168db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// k0, k1: Reserved for system calls and interrupt handlers. 169db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(k0, 26); 170db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(k1, 27); 171db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// gp: Reserved. 172db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(gp, 28); 173db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// sp: Stack pointer. 174db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(sp, 29); 175db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// fp: Frame pointer. 176db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(fp, 30); 177db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// ra: Return address pointer. 178db1b4389239a7132c9cde0915dbd3f775dc1027aBen MurdochREGISTER(ra, 31); 179db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch 180db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch#undef REGISTER 18144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuint ToNumber(Register reg); 1843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuRegister ToRegister(int num); 1863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Coprocessor register. 1883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescustruct FPURegister { 18944f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kNumRegisters = v8::internal::kNumFPURegisters; 190589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 191589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // TODO(plind): Warning, inconsistent numbering here. kNumFPURegisters refers 192589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to 193589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // number of Double regs (64-bit regs, or FPU-reg-pairs). 194589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 195589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // A few double registers are reserved: one as a scratch register and one to 196589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // hold 0.0. 197589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // f28: 0.0 198589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // f30: scratch register. 199589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch static const int kNumReservedRegisters = 2; 200589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch static const int kNumAllocatableRegisters = kNumRegisters / 2 - 201589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch kNumReservedRegisters; 202589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 20344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline static int ToAllocationIndex(FPURegister reg); 20544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 20644f0eee88ff00398ff7f715fab053374d808c90dSteve Block static FPURegister FromAllocationIndex(int index) { 20744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(index >= 0 && index < kNumAllocatableRegisters); 208589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return from_code(index * 2); 20944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 21044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 21144f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const char* AllocationIndexToString(int index) { 21244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(index >= 0 && index < kNumAllocatableRegisters); 21344f0eee88ff00398ff7f715fab053374d808c90dSteve Block const char* const names[] = { 214589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch "f0", 21544f0eee88ff00398ff7f715fab053374d808c90dSteve Block "f2", 21644f0eee88ff00398ff7f715fab053374d808c90dSteve Block "f4", 21744f0eee88ff00398ff7f715fab053374d808c90dSteve Block "f6", 21844f0eee88ff00398ff7f715fab053374d808c90dSteve Block "f8", 21944f0eee88ff00398ff7f715fab053374d808c90dSteve Block "f10", 22044f0eee88ff00398ff7f715fab053374d808c90dSteve Block "f12", 22144f0eee88ff00398ff7f715fab053374d808c90dSteve Block "f14", 22244f0eee88ff00398ff7f715fab053374d808c90dSteve Block "f16", 22344f0eee88ff00398ff7f715fab053374d808c90dSteve Block "f18", 22444f0eee88ff00398ff7f715fab053374d808c90dSteve Block "f20", 22544f0eee88ff00398ff7f715fab053374d808c90dSteve Block "f22", 22644f0eee88ff00398ff7f715fab053374d808c90dSteve Block "f24", 227589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch "f26" 22844f0eee88ff00398ff7f715fab053374d808c90dSteve Block }; 22944f0eee88ff00398ff7f715fab053374d808c90dSteve Block return names[index]; 23044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 23144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 23244f0eee88ff00398ff7f715fab053374d808c90dSteve Block static FPURegister from_code(int code) { 23344f0eee88ff00398ff7f715fab053374d808c90dSteve Block FPURegister r = { code }; 23444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return r; 23544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 23644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 23744f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool is_valid() const { return 0 <= code_ && code_ < kNumFPURegisters ; } 2380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool is(FPURegister creg) const { return code_ == creg.code_; } 239589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch FPURegister low() const { 240589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Find low reg of a Double-reg pair, which is the reg itself. 241589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(code_ % 2 == 0); // Specified Double reg must be even. 242589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch FPURegister reg; 243589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch reg.code_ = code_; 244589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(reg.is_valid()); 245589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return reg; 246589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 247589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch FPURegister high() const { 248589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Find high reg of a Doubel-reg pair, which is reg + 1. 249589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(code_ % 2 == 0); // Specified Double reg must be even. 250589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch FPURegister reg; 251589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch reg.code_ = code_ + 1; 252589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(reg.is_valid()); 253589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return reg; 254589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 255589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 2560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int code() const { 2573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(is_valid()); 2583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return code_; 2593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 2600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int bit() const { 2613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(is_valid()); 2623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return 1 << code_; 2633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 26444f0eee88ff00398ff7f715fab053374d808c90dSteve Block void setcode(int f) { 26544f0eee88ff00398ff7f715fab053374d808c90dSteve Block code_ = f; 26644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(is_valid()); 26744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 2683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Unfortunately we can't make this private in a struct. 2693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int code_; 2703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}; 2713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 272589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// V8 now supports the O32 ABI, and the FPU Registers are organized as 32 273589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// 32-bit registers, f0 through f31. When used as 'double' they are used 274589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// in pairs, starting with the even numbered register. So a double operation 275589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// on f0 really uses f0 and f1. 276589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// (Modern mips hardware also supports 32 64-bit registers, via setting 277589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// (priviledged) Status Register FR bit to 1. This is used by the N32 ABI, 278589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// but it is not in common use. Someday we will want to support this in v8.) 279589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 280589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// For O32 ABI, Floats and Doubles refer to same set of 32 32-bit registers. 28144f0eee88ff00398ff7f715fab053374d808c90dSteve Blocktypedef FPURegister DoubleRegister; 282589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochtypedef FPURegister FloatRegister; 28344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 284589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochconst FPURegister no_freg = { -1 }; 28544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 28644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f0 = { 0 }; // Return value in hard float mode. 28744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f1 = { 1 }; 28844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f2 = { 2 }; 28944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f3 = { 3 }; 29044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f4 = { 4 }; 29144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f5 = { 5 }; 29244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f6 = { 6 }; 29344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f7 = { 7 }; 29444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f8 = { 8 }; 29544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f9 = { 9 }; 29644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f10 = { 10 }; 29744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f11 = { 11 }; 29844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f12 = { 12 }; // Arg 0 in hard float mode. 29944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f13 = { 13 }; 30044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f14 = { 14 }; // Arg 1 in hard float mode. 30144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f15 = { 15 }; 30244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f16 = { 16 }; 30344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f17 = { 17 }; 30444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f18 = { 18 }; 30544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f19 = { 19 }; 30644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f20 = { 20 }; 30744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f21 = { 21 }; 30844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f22 = { 22 }; 30944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f23 = { 23 }; 31044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f24 = { 24 }; 31144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f25 = { 25 }; 31244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f26 = { 26 }; 31344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f27 = { 27 }; 31444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f28 = { 28 }; 31544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f29 = { 29 }; 31644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f30 = { 30 }; 31744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPURegister f31 = { 31 }; 31844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Register aliases. 3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// cp is assumed to be a callee saved register. 3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const Register& kLithiumScratchReg = s3; // Scratch register. 3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const Register& kLithiumScratchReg2 = s4; // Scratch register. 3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const Register& kRootRegister = s6; // Roots array pointer. 3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const Register& cp = s7; // JavaScript context pointer. 3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const DoubleRegister& kLithiumScratchDouble = f30; 3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const FPURegister& kDoubleRegZero = f28; 327589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 32844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// FPU (coprocessor 1) control registers. 32944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Currently only FCSR (#31) is implemented. 33044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstruct FPUControlRegister { 33144f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool is_valid() const { return code_ == kFCSRRegister; } 33244f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool is(FPUControlRegister creg) const { return code_ == creg.code_; } 33344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int code() const { 33444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(is_valid()); 33544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return code_; 33644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 33744f0eee88ff00398ff7f715fab053374d808c90dSteve Block int bit() const { 33844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(is_valid()); 33944f0eee88ff00398ff7f715fab053374d808c90dSteve Block return 1 << code_; 34044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 34144f0eee88ff00398ff7f715fab053374d808c90dSteve Block void setcode(int f) { 34244f0eee88ff00398ff7f715fab053374d808c90dSteve Block code_ = f; 34344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(is_valid()); 34444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 34544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Unfortunately we can't make this private in a struct. 34644f0eee88ff00398ff7f715fab053374d808c90dSteve Block int code_; 3473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}; 3483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochconst FPUControlRegister no_fpucreg = { kInvalidFPUControlRegister }; 35044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst FPUControlRegister FCSR = { kFCSRRegister }; 3513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// ----------------------------------------------------------------------------- 3543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Machine instruction Operands. 3553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Class Operand represents a shifter operand in data processing instructions. 3573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuclass Operand BASE_EMBEDDED { 3583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu public: 3593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Immediate. 3603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu INLINE(explicit Operand(int32_t immediate, 3613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu RelocInfo::Mode rmode = RelocInfo::NONE)); 3623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu INLINE(explicit Operand(const ExternalReference& f)); 3633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu INLINE(explicit Operand(const char* s)); 3643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu INLINE(explicit Operand(Object** opp)); 3653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu INLINE(explicit Operand(Context** cpp)); 3663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu explicit Operand(Handle<Object> handle); 3673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu INLINE(explicit Operand(Smi* value)); 3683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Register. 3703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu INLINE(explicit Operand(Register rm)); 3713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Return true if this is a register operand. 3733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu INLINE(bool is_reg() const); 3743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register rm() const { return rm_; } 3763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu private: 3783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register rm_; 379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int32_t imm32_; // Valid if rm_ == no_reg. 3803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu RelocInfo::Mode rmode_; 3813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu friend class Assembler; 3833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu friend class MacroAssembler; 3843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}; 3853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// On MIPS we have only one adressing mode with base_reg + offset. 3883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Class MemOperand represents a memory operand in load and store instructions. 3893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuclass MemOperand : public Operand { 3903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu public: 39144f0eee88ff00398ff7f715fab053374d808c90dSteve Block explicit MemOperand(Register rn, int32_t offset = 0); 3923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int32_t offset() const { return offset_; } 3933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 394589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch bool OffsetIsInt16Encodable() const { 395589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return is_int16(offset_); 396589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 397589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 3983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu private: 39944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t offset_; 4003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 4013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu friend class Assembler; 4023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}; 4033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 4043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 40544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// CpuFeatures keeps track of which features are supported by the target CPU. 40644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Supported features must be enabled by a Scope before use. 407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass CpuFeatures : public AllStatic { 40844f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 40944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Detect features of the target CPU. Set safe defaults if the serializer 41044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // is enabled (snapshots must be portable). 411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static void Probe(); 41244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 41344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check whether a feature is supported by the target CPU. 414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static bool IsSupported(CpuFeature f) { 415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(initialized_); 41644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (f == FPU && !FLAG_enable_fpu) return false; 41744f0eee88ff00398ff7f715fab053374d808c90dSteve Block return (supported_ & (1u << f)) != 0; 41844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 41944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef DEBUG 42244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check whether a feature is currently enabled. 423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static bool IsEnabled(CpuFeature f) { 424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(initialized_); 425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Isolate* isolate = Isolate::UncheckedCurrent(); 426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (isolate == NULL) { 427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // When no isolate is available, work as if we're running in 428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // release mode. 429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return IsSupported(f); 430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch unsigned enabled = static_cast<unsigned>(isolate->enabled_cpu_features()); 432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return (enabled & (1u << f)) != 0; 43344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif 43544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 43644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Enable a specified feature within a scope. 43744f0eee88ff00398ff7f715fab053374d808c90dSteve Block class Scope BASE_EMBEDDED { 43844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG 4393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 44044f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch explicit Scope(CpuFeature f) { 442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch unsigned mask = 1u << f; 443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(CpuFeatures::IsSupported(f)); 44444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!Serializer::enabled() || 445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (CpuFeatures::found_by_runtime_probing_ & mask) == 0); 446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate_ = Isolate::UncheckedCurrent(); 447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch old_enabled_ = 0; 448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (isolate_ != NULL) { 449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch old_enabled_ = static_cast<unsigned>(isolate_->enabled_cpu_features()); 450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate_->set_enabled_cpu_features(old_enabled_ | mask); 451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 45244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 45344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ~Scope() { 454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_); 455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (isolate_ != NULL) { 456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate_->set_enabled_cpu_features(old_enabled_); 457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 4593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private: 46144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate_; 462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch unsigned old_enabled_; 46344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#else 4643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch public: 46644f0eee88ff00398ff7f715fab053374d808c90dSteve Block explicit Scope(CpuFeature f) {} 46744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif 46844f0eee88ff00398ff7f715fab053374d808c90dSteve Block }; 46944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch class TryForceFeatureScope BASE_EMBEDDED { 471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public: 472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch explicit TryForceFeatureScope(CpuFeature f) 473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : old_supported_(CpuFeatures::supported_) { 474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CanForce()) { 475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::supported_ |= (1u << f); 476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 47844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ~TryForceFeatureScope() { 480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CanForce()) { 481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::supported_ = old_supported_; 482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 48444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private: 486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static bool CanForce() { 487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // It's only safe to temporarily force support of CPU features 488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // when there's only a single isolate, which is guaranteed when 489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the serializer is enabled. 490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Serializer::enabled(); 491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const unsigned old_supported_; 494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch }; 495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private: 497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef DEBUG 498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static bool initialized_; 499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif 500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static unsigned supported_; 501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static unsigned found_by_runtime_probing_; 50244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 50344f0eee88ff00398ff7f715fab053374d808c90dSteve Block DISALLOW_COPY_AND_ASSIGN(CpuFeatures); 50444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}; 50544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 50644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 50744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass Assembler : public AssemblerBase { 5083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu public: 5093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Create an assembler. Instructions and relocation information are emitted 5103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // into a buffer, with the instructions starting from the beginning and the 5113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // relocation information starting from the end of the buffer. See CodeDesc 5123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // for a detailed comment on the layout (globals.h). 5133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // 5143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // If the provided buffer is NULL, the assembler allocates and grows its own 5153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // buffer, and buffer_size determines the initial buffer size. The buffer is 5163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // owned by the assembler and deallocated upon destruction of the assembler. 5173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // 5183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // If the provided buffer is not NULL, the assembler uses the provided buffer 5193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // for code generation and assumes its size to be buffer_size. If the buffer 5203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // is too small, a fatal error occurs. No deallocation of the buffer is done 5213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // upon destruction of the assembler. 522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Assembler(Isolate* isolate, void* buffer, int buffer_size); 5233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ~Assembler(); 5243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 52544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Overrides the default provided by FLAG_debug_code. 52644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void set_emit_debug_code(bool value) { emit_debug_code_ = value; } 52744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 5283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // GetCode emits any pending (non-emitted) code and fills the descriptor 5293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // desc. GetCode() is idempotent; it returns the same result if no other 5303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Assembler functions are invoked in between GetCode() calls. 5313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void GetCode(CodeDesc* desc); 5323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 5333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Label operations & relative jumps (PPUM Appendix D). 5343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // 5353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Takes a branch opcode (cc) and a label (L) and generates 5363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // either a backward branch or a forward branch and links it 5373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // to the label fixup chain. Usage: 5383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // 5393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Label L; // unbound label 5403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // j(cc, &L); // forward branch to unbound label 5413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // bind(&L); // bind label to the current pc 5423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // j(cc, &L); // backward branch to bound label 5433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // bind(&L); // illegal: a label may be bound only once 5443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // 5453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Note: The same Label can be used for forward and backward branches 5463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // but it may be bound only once. 547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void bind(Label* L); // Binds an unbound label L to current code position. 5483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Determines if Label is bound and near enough so that branch instruction 5493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // can be used to reach it, instead of jump instruction. 5503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool is_near(Label* L); 5513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Returns the branch offset to the given label from the current code 553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // position. Links the label to the current position if it is still unbound. 5543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Manages the jump elimination optimization if the second parameter is true. 5553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t branch_offset(Label* L, bool jump_elimination_allowed); 5563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t shifted_branch_offset(Label* L, bool jump_elimination_allowed) { 5573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t o = branch_offset(L, jump_elimination_allowed); 5583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT((o & 3) == 0); // Assert the offset is aligned. 5593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return o >> 2; 5603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 5613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t jump_address(Label* L); 5623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 5633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Puts a labels target address at the given position. 5643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // The high 8 bits are set to zero. 5653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void label_at_put(Label* L, int at_offset); 5663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 5673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Read/Modify the code target address in the branch/call instruction at pc. 5683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu static Address target_address_at(Address pc); 5693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu static void set_target_address_at(Address pc, Address target); 5703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 571589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch static void JumpLabelToJumpRegister(Address pc); 572589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 573db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch static void QuietNaN(HeapObject* nan); 574db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch 5753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // This sets the branch destination (which gets loaded at the call address). 5763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // This is for calls and branches within generated code. The serializer 5773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // has already deserialized the lui/ori instructions etc. 5783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inline static void deserialization_set_special_target_at( 5793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address instruction_payload, Address target) { 5803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_target_address_at( 5813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instruction_payload - kInstructionsFor32BitConstant * kInstrSize, 5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch target); 5833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 5843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 5853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // This sets the branch destination. 5863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // This is for calls and branches to runtime code. 5873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline static void set_external_target_at(Address instruction_payload, 5883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Address target) { 5893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_target_address_at(instruction_payload, target); 5903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 5913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 59244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Size of an instruction. 59344f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kInstrSize = sizeof(Instr); 59444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 59544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Difference between address of current opcode and target address offset. 59644f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kBranchPCOffset = 4; 59744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 59844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Here we are patching the address in the LUI/ORI instruction pair. 59944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // These values are used in the serialization process and must be zero for 60044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // MIPS platform, as Code, Embedded Object or External-reference pointers 60144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // are split across two consecutive instructions and don't exist separately 60244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // in the code, so the serializer should not step forwards in memory after 60344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // a target is resolved and written. 6043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kSpecialTargetSize = 0; 60544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 60644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Number of consecutive instructions used to store 32bit constant. 607589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Before jump-optimizations, this constant was used in 608589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // RelocInfo::target_address_address() function to tell serializer address of 609589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // the instruction that follows LUI/ORI instruction pair. Now, with new jump 610589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // optimization, where jump-through-register instruction that usually 611589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // follows LUI/ORI pair is substituted with J/JAL, this constant equals 612589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // to 3 instructions (LUI+ORI+J/JAL/JR/JALR). 613589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch static const int kInstructionsFor32BitConstant = 3; 6143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 6153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Distance between the instruction referring to the address of the call 6163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // target and the return address. 6173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu static const int kCallTargetAddressOffset = 4 * kInstrSize; 6183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 6193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Distance between start of patched return sequence and the emitted address 6203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // to jump to. 62144f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kPatchReturnSequenceAddressOffset = 0; 6223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 6237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Distance between start of patched debug break slot and the emitted address 6247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // to jump to. 62544f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize; 62644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 62744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Difference between address of current opcode and value read from pc 62844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // register. 62944f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kPcLoadDelta = 4; 63044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 63144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Number of instructions used for the JS return sequence. The constant is 63244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // used by the debugger to patch the JS return sequence. 63344f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kJSReturnSequenceInstructions = 7; 63444f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kDebugBreakSlotInstructions = 4; 63544f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kDebugBreakSlotLength = 63644f0eee88ff00398ff7f715fab053374d808c90dSteve Block kDebugBreakSlotInstructions * kInstrSize; 63744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 6383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 6393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // --------------------------------------------------------------------------- 6403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Code generation. 6413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 64244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Insert the smallest number of nop instructions 64344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // possible to align the pc offset to a multiple 64444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // of m. m must be a power of 2 (>= 4). 64544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Align(int m); 64644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Aligns code to something that's optimal for a jump target for the platform. 64744f0eee88ff00398ff7f715fab053374d808c90dSteve Block void CodeTargetAlign(); 64844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 64944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Different nop operations are used by the code generator to detect certain 65044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // states of the generated code. 65144f0eee88ff00398ff7f715fab053374d808c90dSteve Block enum NopMarkerTypes { 65244f0eee88ff00398ff7f715fab053374d808c90dSteve Block NON_MARKING_NOP = 0, 65344f0eee88ff00398ff7f715fab053374d808c90dSteve Block DEBUG_BREAK_NOP, 65444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // IC markers. 65544f0eee88ff00398ff7f715fab053374d808c90dSteve Block PROPERTY_ACCESS_INLINED, 65644f0eee88ff00398ff7f715fab053374d808c90dSteve Block PROPERTY_ACCESS_INLINED_CONTEXT, 65744f0eee88ff00398ff7f715fab053374d808c90dSteve Block PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE, 65844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Helper values. 65944f0eee88ff00398ff7f715fab053374d808c90dSteve Block LAST_CODE_MARKER, 66044f0eee88ff00398ff7f715fab053374d808c90dSteve Block FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED 66144f0eee88ff00398ff7f715fab053374d808c90dSteve Block }; 66244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Type == 0 is the default non-marking type. 66444f0eee88ff00398ff7f715fab053374d808c90dSteve Block void nop(unsigned int type = 0) { 66544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(type < 32); 66644f0eee88ff00398ff7f715fab053374d808c90dSteve Block sll(zero_reg, zero_reg, type, true); 66744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 6683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 6693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // --------Branch-and-jump-instructions---------- 6713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // We don't use likely variant of instructions. 6723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void b(int16_t offset); 6733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void b(Label* L) { b(branch_offset(L, false)>>2); } 6743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void bal(int16_t offset); 6753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void bal(Label* L) { bal(branch_offset(L, false)>>2); } 6763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 6773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void beq(Register rs, Register rt, int16_t offset); 6783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void beq(Register rs, Register rt, Label* L) { 6793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu beq(rs, rt, branch_offset(L, false) >> 2); 6803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 6813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void bgez(Register rs, int16_t offset); 6823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void bgezal(Register rs, int16_t offset); 6833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void bgtz(Register rs, int16_t offset); 6843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void blez(Register rs, int16_t offset); 6853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void bltz(Register rs, int16_t offset); 6863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void bltzal(Register rs, int16_t offset); 6873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void bne(Register rs, Register rt, int16_t offset); 6883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void bne(Register rs, Register rt, Label* L) { 6893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bne(rs, rt, branch_offset(L, false)>>2); 6903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 6913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 6923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Never use the int16_t b(l)cond version with a branch offset 693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // instead of using the Label* version. 6943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 6953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Jump targets must be in the current 256 MB-aligned region. i.e. 28 bits. 6963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void j(int32_t target); 6973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void jal(int32_t target); 6983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void jalr(Register rs, Register rd = ra); 6993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void jr(Register target); 700589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch void j_or_jr(int32_t target, Register rs); 701589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch void jal_or_jalr(int32_t target, Register rs); 7023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu //-------Data-processing-instructions--------- 7053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Arithmetic. 7073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void addu(Register rd, Register rs, Register rt); 7083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void subu(Register rd, Register rs, Register rt); 7093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void mult(Register rs, Register rt); 7103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void multu(Register rs, Register rt); 7113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void div(Register rs, Register rt); 7123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void divu(Register rs, Register rt); 7133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void mul(Register rd, Register rs, Register rt); 7143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void addiu(Register rd, Register rs, int32_t j); 7163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Logical. 7183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void and_(Register rd, Register rs, Register rt); 7193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void or_(Register rd, Register rs, Register rt); 7203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void xor_(Register rd, Register rs, Register rt); 7213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void nor(Register rd, Register rs, Register rt); 7223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void andi(Register rd, Register rs, int32_t j); 7243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void ori(Register rd, Register rs, int32_t j); 7253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void xori(Register rd, Register rs, int32_t j); 7263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void lui(Register rd, int32_t j); 7273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Shifts. 72944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Please note: sll(zero_reg, zero_reg, x) instructions are reserved as nop 73044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // and may cause problems in normal code. coming_from_nop makes sure this 73144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // doesn't happen. 73244f0eee88ff00398ff7f715fab053374d808c90dSteve Block void sll(Register rd, Register rt, uint16_t sa, bool coming_from_nop = false); 7333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void sllv(Register rd, Register rt, Register rs); 7343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void srl(Register rd, Register rt, uint16_t sa); 7353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void srlv(Register rd, Register rt, Register rs); 7363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void sra(Register rt, Register rd, uint16_t sa); 7373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void srav(Register rt, Register rd, Register rs); 73844f0eee88ff00398ff7f715fab053374d808c90dSteve Block void rotr(Register rd, Register rt, uint16_t sa); 73944f0eee88ff00398ff7f715fab053374d808c90dSteve Block void rotrv(Register rd, Register rt, Register rs); 7403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu //------------Memory-instructions------------- 7433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void lb(Register rd, const MemOperand& rs); 7453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void lbu(Register rd, const MemOperand& rs); 74644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void lh(Register rd, const MemOperand& rs); 74744f0eee88ff00398ff7f715fab053374d808c90dSteve Block void lhu(Register rd, const MemOperand& rs); 7483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void lw(Register rd, const MemOperand& rs); 74944f0eee88ff00398ff7f715fab053374d808c90dSteve Block void lwl(Register rd, const MemOperand& rs); 75044f0eee88ff00398ff7f715fab053374d808c90dSteve Block void lwr(Register rd, const MemOperand& rs); 7513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void sb(Register rd, const MemOperand& rs); 75244f0eee88ff00398ff7f715fab053374d808c90dSteve Block void sh(Register rd, const MemOperand& rs); 7533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void sw(Register rd, const MemOperand& rs); 75444f0eee88ff00398ff7f715fab053374d808c90dSteve Block void swl(Register rd, const MemOperand& rs); 75544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void swr(Register rd, const MemOperand& rs); 7563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu //-------------Misc-instructions-------------- 7593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Break / Trap instructions. 7613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void break_(uint32_t code, bool break_as_stop = false); 7623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void stop(const char* msg, uint32_t code = kMaxStopCode); 7633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void tge(Register rs, Register rt, uint16_t code); 7643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void tgeu(Register rs, Register rt, uint16_t code); 7653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void tlt(Register rs, Register rt, uint16_t code); 7663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void tltu(Register rs, Register rt, uint16_t code); 7673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void teq(Register rs, Register rt, uint16_t code); 7683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void tne(Register rs, Register rt, uint16_t code); 7693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Move from HI/LO register. 7713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void mfhi(Register rd); 7723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void mflo(Register rd); 7733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Set on less than. 7753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void slt(Register rd, Register rs, Register rt); 7763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void sltu(Register rd, Register rs, Register rt); 7773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void slti(Register rd, Register rs, int32_t j); 7783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void sltiu(Register rd, Register rs, int32_t j); 7793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 78044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Conditional move. 78144f0eee88ff00398ff7f715fab053374d808c90dSteve Block void movz(Register rd, Register rs, Register rt); 78244f0eee88ff00398ff7f715fab053374d808c90dSteve Block void movn(Register rd, Register rs, Register rt); 78344f0eee88ff00398ff7f715fab053374d808c90dSteve Block void movt(Register rd, Register rs, uint16_t cc = 0); 78444f0eee88ff00398ff7f715fab053374d808c90dSteve Block void movf(Register rd, Register rs, uint16_t cc = 0); 78544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 78644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Bit twiddling. 78744f0eee88ff00398ff7f715fab053374d808c90dSteve Block void clz(Register rd, Register rs); 78844f0eee88ff00398ff7f715fab053374d808c90dSteve Block void ins_(Register rt, Register rs, uint16_t pos, uint16_t size); 78944f0eee88ff00398ff7f715fab053374d808c90dSteve Block void ext_(Register rt, Register rs, uint16_t pos, uint16_t size); 7903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu //--------Coprocessor-instructions---------------- 7923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Load, store, and move. 7943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void lwc1(FPURegister fd, const MemOperand& src); 7953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void ldc1(FPURegister fd, const MemOperand& src); 7963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void swc1(FPURegister fs, const MemOperand& dst); 7983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void sdc1(FPURegister fs, const MemOperand& dst); 7993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 80044f0eee88ff00398ff7f715fab053374d808c90dSteve Block void mtc1(Register rt, FPURegister fs); 80144f0eee88ff00398ff7f715fab053374d808c90dSteve Block void mfc1(Register rt, FPURegister fs); 80244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 80344f0eee88ff00398ff7f715fab053374d808c90dSteve Block void ctc1(Register rt, FPUControlRegister fs); 80444f0eee88ff00398ff7f715fab053374d808c90dSteve Block void cfc1(Register rt, FPUControlRegister fs); 80544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 80644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Arithmetic. 80744f0eee88ff00398ff7f715fab053374d808c90dSteve Block void add_d(FPURegister fd, FPURegister fs, FPURegister ft); 80844f0eee88ff00398ff7f715fab053374d808c90dSteve Block void sub_d(FPURegister fd, FPURegister fs, FPURegister ft); 80944f0eee88ff00398ff7f715fab053374d808c90dSteve Block void mul_d(FPURegister fd, FPURegister fs, FPURegister ft); 81044f0eee88ff00398ff7f715fab053374d808c90dSteve Block void div_d(FPURegister fd, FPURegister fs, FPURegister ft); 81144f0eee88ff00398ff7f715fab053374d808c90dSteve Block void abs_d(FPURegister fd, FPURegister fs); 81244f0eee88ff00398ff7f715fab053374d808c90dSteve Block void mov_d(FPURegister fd, FPURegister fs); 81344f0eee88ff00398ff7f715fab053374d808c90dSteve Block void neg_d(FPURegister fd, FPURegister fs); 81444f0eee88ff00398ff7f715fab053374d808c90dSteve Block void sqrt_d(FPURegister fd, FPURegister fs); 8153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Conversion. 8173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void cvt_w_s(FPURegister fd, FPURegister fs); 8183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void cvt_w_d(FPURegister fd, FPURegister fs); 81944f0eee88ff00398ff7f715fab053374d808c90dSteve Block void trunc_w_s(FPURegister fd, FPURegister fs); 82044f0eee88ff00398ff7f715fab053374d808c90dSteve Block void trunc_w_d(FPURegister fd, FPURegister fs); 82144f0eee88ff00398ff7f715fab053374d808c90dSteve Block void round_w_s(FPURegister fd, FPURegister fs); 82244f0eee88ff00398ff7f715fab053374d808c90dSteve Block void round_w_d(FPURegister fd, FPURegister fs); 82344f0eee88ff00398ff7f715fab053374d808c90dSteve Block void floor_w_s(FPURegister fd, FPURegister fs); 82444f0eee88ff00398ff7f715fab053374d808c90dSteve Block void floor_w_d(FPURegister fd, FPURegister fs); 82544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void ceil_w_s(FPURegister fd, FPURegister fs); 82644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void ceil_w_d(FPURegister fd, FPURegister fs); 8273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void cvt_l_s(FPURegister fd, FPURegister fs); 8293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void cvt_l_d(FPURegister fd, FPURegister fs); 83044f0eee88ff00398ff7f715fab053374d808c90dSteve Block void trunc_l_s(FPURegister fd, FPURegister fs); 83144f0eee88ff00398ff7f715fab053374d808c90dSteve Block void trunc_l_d(FPURegister fd, FPURegister fs); 83244f0eee88ff00398ff7f715fab053374d808c90dSteve Block void round_l_s(FPURegister fd, FPURegister fs); 83344f0eee88ff00398ff7f715fab053374d808c90dSteve Block void round_l_d(FPURegister fd, FPURegister fs); 83444f0eee88ff00398ff7f715fab053374d808c90dSteve Block void floor_l_s(FPURegister fd, FPURegister fs); 83544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void floor_l_d(FPURegister fd, FPURegister fs); 83644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void ceil_l_s(FPURegister fd, FPURegister fs); 83744f0eee88ff00398ff7f715fab053374d808c90dSteve Block void ceil_l_d(FPURegister fd, FPURegister fs); 8383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void cvt_s_w(FPURegister fd, FPURegister fs); 8403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void cvt_s_l(FPURegister fd, FPURegister fs); 8413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void cvt_s_d(FPURegister fd, FPURegister fs); 8423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void cvt_d_w(FPURegister fd, FPURegister fs); 8443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void cvt_d_l(FPURegister fd, FPURegister fs); 8453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void cvt_d_s(FPURegister fd, FPURegister fs); 8463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Conditions and branches. 8483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void c(FPUCondition cond, SecondaryField fmt, 8493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu FPURegister ft, FPURegister fs, uint16_t cc = 0); 8503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void bc1f(int16_t offset, uint16_t cc = 0); 8523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void bc1f(Label* L, uint16_t cc = 0) { bc1f(branch_offset(L, false)>>2, cc); } 8533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void bc1t(int16_t offset, uint16_t cc = 0); 8543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void bc1t(Label* L, uint16_t cc = 0) { bc1t(branch_offset(L, false)>>2, cc); } 85544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void fcmp(FPURegister src1, const double src2, FPUCondition cond); 8563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Check the code size generated from label to here. 8583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int SizeOfCodeGeneratedSince(Label* label) { 8593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return pc_offset() - label->pos(); 8603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check the number of instructions generated from label to here. 8633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int InstructionsGeneratedSince(Label* label) { 8643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return SizeOfCodeGeneratedSince(label) / kInstrSize; 8653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 8663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 86744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Class for scoping postponing the trampoline pool generation. 86844f0eee88ff00398ff7f715fab053374d808c90dSteve Block class BlockTrampolinePoolScope { 86944f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 87044f0eee88ff00398ff7f715fab053374d808c90dSteve Block explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) { 87144f0eee88ff00398ff7f715fab053374d808c90dSteve Block assem_->StartBlockTrampolinePool(); 87244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 87344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ~BlockTrampolinePoolScope() { 87444f0eee88ff00398ff7f715fab053374d808c90dSteve Block assem_->EndBlockTrampolinePool(); 87544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 87644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 87744f0eee88ff00398ff7f715fab053374d808c90dSteve Block private: 87844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Assembler* assem_; 87944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 88044f0eee88ff00398ff7f715fab053374d808c90dSteve Block DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope); 88144f0eee88ff00398ff7f715fab053374d808c90dSteve Block }; 88244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Class for postponing the assembly buffer growth. Typically used for 8843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // sequences of instructions that must be emitted as a unit, before 8853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // buffer growth (and relocation) can occur. 8863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This blocking scope is not nestable. 8873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch class BlockGrowBufferScope { 8883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch public: 8893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch explicit BlockGrowBufferScope(Assembler* assem) : assem_(assem) { 8903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch assem_->StartBlockGrowBuffer(); 8913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ~BlockGrowBufferScope() { 8933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch assem_->EndBlockGrowBuffer(); 8943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private: 8973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Assembler* assem_; 8983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DISALLOW_IMPLICIT_CONSTRUCTORS(BlockGrowBufferScope); 9003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch }; 9013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 9023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Debugging. 9033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Mark address of the ExitJSFrame code. 9053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void RecordJSReturn(); 9063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 90744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Mark address of a debug break slot. 90844f0eee88ff00398ff7f715fab053374d808c90dSteve Block void RecordDebugBreakSlot(); 90944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Record the AST id of the CallIC being compiled, so that it can be placed 911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // in the relocation information. 9123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void SetRecordedAstId(unsigned ast_id) { 9133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(recorded_ast_id_ == kNoASTId); 9143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch recorded_ast_id_ = ast_id; 9153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 9163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 9173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch unsigned RecordedAstId() { 9183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(recorded_ast_id_ != kNoASTId); 9193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return recorded_ast_id_; 9203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 9213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 9223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void ClearRecordedAstId() { recorded_ast_id_ = kNoASTId; } 923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 9243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Record a comment relocation entry that can be used by a disassembler. 92544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Use --code-comments to enable. 9263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void RecordComment(const char* msg); 9273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static int RelocateInternalReference(byte* pc, intptr_t pc_delta); 9293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 93044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Writes a single byte or word of data in the code stream. Used for 93144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // inline tables, e.g., jump-tables. 93244f0eee88ff00398ff7f715fab053374d808c90dSteve Block void db(uint8_t data); 93344f0eee88ff00398ff7f715fab053374d808c90dSteve Block void dd(uint32_t data); 9343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t pc_offset() const { return pc_ - buffer_; } 93644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 93744f0eee88ff00398ff7f715fab053374d808c90dSteve Block PositionsRecorder* positions_recorder() { return &positions_recorder_; } 93844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 93944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Postpone the generation of the trampoline pool for the specified number of 94044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // instructions. 94144f0eee88ff00398ff7f715fab053374d808c90dSteve Block void BlockTrampolinePoolFor(int instructions); 94244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 9433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Check if there is less than kGap bytes available in the buffer. 9443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // If this is the case, we need to grow the buffer before emitting 9453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // an instruction or relocation information. 9463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; } 9473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Get the number of bytes available in the buffer. 9493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline int available_space() const { return reloc_info_writer.pos() - pc_; } 9503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Read/patch instructions. 9523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); } 95344f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void instr_at_put(byte* pc, Instr instr) { 9543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu *reinterpret_cast<Instr*>(pc) = instr; 9553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 9563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); } 9573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void instr_at_put(int pos, Instr instr) { 9583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu *reinterpret_cast<Instr*>(buffer_ + pos) = instr; 9593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 9603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Check if an instruction is a branch of some kind. 96244f0eee88ff00398ff7f715fab053374d808c90dSteve Block static bool IsBranch(Instr instr); 963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static bool IsBeq(Instr instr); 964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static bool IsBne(Instr instr); 96544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 9663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static bool IsJump(Instr instr); 9673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static bool IsJ(Instr instr); 9683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static bool IsLui(Instr instr); 9693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static bool IsOri(Instr instr); 9703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 971589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch static bool IsJal(Instr instr); 972589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch static bool IsJr(Instr instr); 973589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch static bool IsJalr(Instr instr); 974589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 97544f0eee88ff00398ff7f715fab053374d808c90dSteve Block static bool IsNop(Instr instr, unsigned int type); 97644f0eee88ff00398ff7f715fab053374d808c90dSteve Block static bool IsPop(Instr instr); 97744f0eee88ff00398ff7f715fab053374d808c90dSteve Block static bool IsPush(Instr instr); 97844f0eee88ff00398ff7f715fab053374d808c90dSteve Block static bool IsLwRegFpOffset(Instr instr); 97944f0eee88ff00398ff7f715fab053374d808c90dSteve Block static bool IsSwRegFpOffset(Instr instr); 98044f0eee88ff00398ff7f715fab053374d808c90dSteve Block static bool IsLwRegFpNegOffset(Instr instr); 98144f0eee88ff00398ff7f715fab053374d808c90dSteve Block static bool IsSwRegFpNegOffset(Instr instr); 98244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static Register GetRtReg(Instr instr); 984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static Register GetRsReg(Instr instr); 985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static Register GetRdReg(Instr instr); 986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static uint32_t GetRt(Instr instr); 988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static uint32_t GetRtField(Instr instr); 989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static uint32_t GetRs(Instr instr); 990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static uint32_t GetRsField(Instr instr); 991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static uint32_t GetRd(Instr instr); 992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static uint32_t GetRdField(Instr instr); 993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static uint32_t GetSa(Instr instr); 994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static uint32_t GetSaField(Instr instr); 995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static uint32_t GetOpcodeField(Instr instr); 9963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static uint32_t GetFunction(Instr instr); 9973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static uint32_t GetFunctionField(Instr instr); 998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static uint32_t GetImmediate16(Instr instr); 999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static uint32_t GetLabelConst(Instr instr); 100044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 100144f0eee88ff00398ff7f715fab053374d808c90dSteve Block static int32_t GetBranchOffset(Instr instr); 100244f0eee88ff00398ff7f715fab053374d808c90dSteve Block static bool IsLw(Instr instr); 100344f0eee88ff00398ff7f715fab053374d808c90dSteve Block static int16_t GetLwOffset(Instr instr); 100444f0eee88ff00398ff7f715fab053374d808c90dSteve Block static Instr SetLwOffset(Instr instr, int16_t offset); 100544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 100644f0eee88ff00398ff7f715fab053374d808c90dSteve Block static bool IsSw(Instr instr); 100744f0eee88ff00398ff7f715fab053374d808c90dSteve Block static Instr SetSwOffset(Instr instr, int16_t offset); 100844f0eee88ff00398ff7f715fab053374d808c90dSteve Block static bool IsAddImmediate(Instr instr); 100944f0eee88ff00398ff7f715fab053374d808c90dSteve Block static Instr SetAddImmediateOffset(Instr instr, int16_t offset); 101044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static bool IsAndImmediate(Instr instr); 1012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 10133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void CheckTrampolinePool(); 101444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 101544f0eee88ff00398ff7f715fab053374d808c90dSteve Block protected: 1016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Relocation for a type-recording IC has the AST id added to it. This 1017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // member variable is a way to pass the information from the call site to 1018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the relocation info. 10193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch unsigned recorded_ast_id_; 1020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 102144f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool emit_debug_code() const { return emit_debug_code_; } 102244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 102344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t buffer_space() const { return reloc_info_writer.pos() - pc_; } 10243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Decode branch instruction at pos and return branch target pos. 10263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int target_at(int32_t pos); 10273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Patch branch instruction at pos to branch to given branch target pos. 10293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void target_at_put(int32_t pos, int32_t target_pos); 10303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Say if we need to relocate with this mode. 103244f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool MustUseReg(RelocInfo::Mode rmode); 10333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Record reloc info for current pc_. 10353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); 10363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 103744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Block the emission of the trampoline pool before pc_offset. 103844f0eee88ff00398ff7f715fab053374d808c90dSteve Block void BlockTrampolinePoolBefore(int pc_offset) { 103944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (no_trampoline_pool_before_ < pc_offset) 104044f0eee88ff00398ff7f715fab053374d808c90dSteve Block no_trampoline_pool_before_ = pc_offset; 104144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 104244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 104344f0eee88ff00398ff7f715fab053374d808c90dSteve Block void StartBlockTrampolinePool() { 104444f0eee88ff00398ff7f715fab053374d808c90dSteve Block trampoline_pool_blocked_nesting_++; 104544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 10463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 104744f0eee88ff00398ff7f715fab053374d808c90dSteve Block void EndBlockTrampolinePool() { 104844f0eee88ff00398ff7f715fab053374d808c90dSteve Block trampoline_pool_blocked_nesting_--; 104944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 105044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 105144f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool is_trampoline_pool_blocked() const { 105244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return trampoline_pool_blocked_nesting_ > 0; 105344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 105444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool has_exception() const { 1056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return internal_trampoline_exception_; 1057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1059589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi); 1060589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 10613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool is_trampoline_emitted() const { 10623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return trampoline_emitted_; 10633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 10643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 10653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Temporarily block automatic assembly buffer growth. 10663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void StartBlockGrowBuffer() { 10673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(!block_buffer_growth_); 10683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch block_buffer_growth_ = true; 10693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 10703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 10713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void EndBlockGrowBuffer() { 10723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(block_buffer_growth_); 10733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch block_buffer_growth_ = false; 10743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 10753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 10763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool is_buffer_growth_blocked() const { 10773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return block_buffer_growth_; 10783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 10793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 10803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu private: 10813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Code buffer: 10823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // The buffer into which code and relocation info are generated. 10833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu byte* buffer_; 10843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int buffer_size_; 10853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // True if the assembler owns the buffer, false if buffer is external. 10863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bool own_buffer_; 10873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Buffer size and constant pool distance are checked together at regular 10893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // intervals of kBufferCheckInterval emitted bytes. 10903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu static const int kBufferCheckInterval = 1*KB/2; 10913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Code generation. 10933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // The relocation writer's position is at least kGap bytes below the end of 10943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // the generated instructions. This is so that multi-instruction sequences do 10953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // not have to check for overflow. The same is true for writes of large 10963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // relocation info entries. 10973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu static const int kGap = 32; 10983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu byte* pc_; // The program counter - moves forward. 10993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 110044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 110144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Repeated checking whether the trampoline pool should be emitted is rather 110244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // expensive. By default we only check again once a number of instructions 110344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // has been generated. 110444f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kCheckConstIntervalInst = 32; 110544f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize; 110644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 110744f0eee88ff00398ff7f715fab053374d808c90dSteve Block int next_buffer_check_; // pc offset of next buffer check. 110844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 110944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Emission of the trampoline pool may be blocked in some code sequences. 111044f0eee88ff00398ff7f715fab053374d808c90dSteve Block int trampoline_pool_blocked_nesting_; // Block emission if this is not zero. 111144f0eee88ff00398ff7f715fab053374d808c90dSteve Block int no_trampoline_pool_before_; // Block emission before this pc offset. 111244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 111344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Keep track of the last emitted pool to guarantee a maximal distance. 111444f0eee88ff00398ff7f715fab053374d808c90dSteve Block int last_trampoline_pool_end_; // pc offset of the end of the last pool. 111544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 11163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Automatic growth of the assembly buffer may be blocked for some sequences. 11173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool block_buffer_growth_; // Block growth when true. 11183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 11193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Relocation information generation. 11203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Each relocation is encoded as a variable size value. 11213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; 11223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu RelocInfoWriter reloc_info_writer; 11233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // The bound position, before this we cannot do instruction elimination. 11253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int last_bound_pos_; 11263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Code emission. 11283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline void CheckBuffer(); 11293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void GrowBuffer(); 11303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline void emit(Instr x); 113144f0eee88ff00398ff7f715fab053374d808c90dSteve Block inline void CheckTrampolinePoolQuick(); 11323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Instruction generation. 11343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // We have 3 different kind of encoding layout on MIPS. 11353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // However due to many different types of objects encoded in the same fields 11363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // we have quite a few aliases for each mode. 11373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Using the same structure to refer to Register and FPURegister would spare a 11383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // few aliases, but mixing both does not look clean to me. 11393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Anyway we could surely implement this differently. 11403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void GenInstrRegister(Opcode opcode, 11423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register rs, 11433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register rt, 11443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register rd, 11453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uint16_t sa = 0, 11463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SecondaryField func = NULLSF); 11473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void GenInstrRegister(Opcode opcode, 114944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register rs, 115044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register rt, 115144f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint16_t msb, 115244f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint16_t lsb, 115344f0eee88ff00398ff7f715fab053374d808c90dSteve Block SecondaryField func); 115444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 115544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void GenInstrRegister(Opcode opcode, 11563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SecondaryField fmt, 11573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu FPURegister ft, 11583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu FPURegister fs, 11593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu FPURegister fd, 11603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SecondaryField func = NULLSF); 11613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void GenInstrRegister(Opcode opcode, 11633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SecondaryField fmt, 11643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register rt, 11653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu FPURegister fs, 11663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu FPURegister fd, 11673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SecondaryField func = NULLSF); 11683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 116944f0eee88ff00398ff7f715fab053374d808c90dSteve Block void GenInstrRegister(Opcode opcode, 117044f0eee88ff00398ff7f715fab053374d808c90dSteve Block SecondaryField fmt, 117144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register rt, 117244f0eee88ff00398ff7f715fab053374d808c90dSteve Block FPUControlRegister fs, 117344f0eee88ff00398ff7f715fab053374d808c90dSteve Block SecondaryField func = NULLSF); 117444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 11753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void GenInstrImmediate(Opcode opcode, 11773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register rs, 11783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register rt, 11793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t j); 11803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void GenInstrImmediate(Opcode opcode, 11813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register rs, 11823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SecondaryField SF, 11833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t j); 11843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void GenInstrImmediate(Opcode opcode, 11853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register r1, 11863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu FPURegister r2, 11873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t j); 11883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void GenInstrJump(Opcode opcode, 11913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uint32_t address); 11923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 119344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Helpers. 119444f0eee88ff00398ff7f715fab053374d808c90dSteve Block void LoadRegPlusOffsetToAt(const MemOperand& src); 11953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Labels. 11973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void print(Label* L); 11983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void bind_to(Label* L, int pos); 11993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void next(Label* L); 12003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 120144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // One trampoline consists of: 120244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // - space for trampoline slots, 120344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // - space for labels. 120444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // 120544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Space for trampoline slots is equal to slot_count * 2 * kInstrSize. 120644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Space for trampoline slots preceeds space for labels. Each label is of one 120744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // instruction size, so total amount for labels is equal to 120844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // label_count * kInstrSize. 120944f0eee88ff00398ff7f715fab053374d808c90dSteve Block class Trampoline { 121044f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 12113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Trampoline() { 12123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch start_ = 0; 12133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch next_slot_ = 0; 12143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch free_slot_count_ = 0; 12153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch end_ = 0; 12163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 12173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Trampoline(int start, int slot_count) { 121844f0eee88ff00398ff7f715fab053374d808c90dSteve Block start_ = start; 121944f0eee88ff00398ff7f715fab053374d808c90dSteve Block next_slot_ = start; 122044f0eee88ff00398ff7f715fab053374d808c90dSteve Block free_slot_count_ = slot_count; 12213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch end_ = start + slot_count * kTrampolineSlotsSize; 122244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 122344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int start() { 122444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return start_; 122544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 122644f0eee88ff00398ff7f715fab053374d808c90dSteve Block int end() { 122744f0eee88ff00398ff7f715fab053374d808c90dSteve Block return end_; 122844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 122944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int take_slot() { 1230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int trampoline_slot = kInvalidSlotPos; 1231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (free_slot_count_ <= 0) { 1232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We have run out of space on trampolines. 1233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Make sure we fail in debug mode, so we become aware of each case 1234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // when this happens. 1235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(0); 1236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Internal exception will be caught. 1237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch trampoline_slot = next_slot_; 1239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch free_slot_count_--; 12403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch next_slot_ += kTrampolineSlotsSize; 1241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 124244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return trampoline_slot; 124344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1244589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 124544f0eee88ff00398ff7f715fab053374d808c90dSteve Block private: 124644f0eee88ff00398ff7f715fab053374d808c90dSteve Block int start_; 124744f0eee88ff00398ff7f715fab053374d808c90dSteve Block int end_; 124844f0eee88ff00398ff7f715fab053374d808c90dSteve Block int next_slot_; 124944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int free_slot_count_; 125044f0eee88ff00398ff7f715fab053374d808c90dSteve Block }; 125144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 12523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int32_t get_trampoline_entry(int32_t pos); 12533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int unbound_labels_count_; 12543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // If trampoline is emitted, generated code is becoming large. As this is 12553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // already a slow case which can possibly break our code generation for the 12563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // extreme case, we use this information to trigger different mode of 12573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // branch instruction generation, where we use jump instructions rather 12583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // than regular branch instructions. 12593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool trampoline_emitted_; 12603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static const int kTrampolineSlotsSize = 4 * kInstrSize; 126144f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kMaxBranchOffset = (1 << (18 - 1)) - 1; 1262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kInvalidSlotPos = -1; 126344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 12643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Trampoline trampoline_; 1265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool internal_trampoline_exception_; 126644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 12673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu friend class RegExpMacroAssemblerMIPS; 12683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu friend class RelocInfo; 126944f0eee88ff00398ff7f715fab053374d808c90dSteve Block friend class CodePatcher; 127044f0eee88ff00398ff7f715fab053374d808c90dSteve Block friend class BlockTrampolinePoolScope; 127144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 127244f0eee88ff00398ff7f715fab053374d808c90dSteve Block PositionsRecorder positions_recorder_; 127344f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool emit_debug_code_; 127444f0eee88ff00398ff7f715fab053374d808c90dSteve Block friend class PositionsRecorder; 127544f0eee88ff00398ff7f715fab053374d808c90dSteve Block friend class EnsureSpace; 127644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}; 127744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 127844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 127944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass EnsureSpace BASE_EMBEDDED { 128044f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 128144f0eee88ff00398ff7f715fab053374d808c90dSteve Block explicit EnsureSpace(Assembler* assembler) { 128244f0eee88ff00398ff7f715fab053374d808c90dSteve Block assembler->CheckBuffer(); 128344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 12843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}; 12853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} } // namespace v8::internal 12873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#endif // V8_ARM_ASSEMBLER_MIPS_H_ 1289