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#include "v8.h" 37f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 38f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_MIPS) 39f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "mips/assembler-mips-inl.h" 413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "serialize.h" 423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace v8 { 443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace internal { 453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 46257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef DEBUG 47257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochbool CpuFeatures::initialized_ = false; 48257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif 49257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochunsigned CpuFeatures::supported_ = 0; 50257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochunsigned CpuFeatures::found_by_runtime_probing_ = 0; 513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 52589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 53589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// Get the CPU features enabled by the build. For cross compilation the 54589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// preprocessor symbols CAN_USE_FPU_INSTRUCTIONS 55589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// can be defined to enable FPU instructions when building the 56589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// snapshot. 57589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochstatic uint64_t CpuFeaturesImpliedByCompiler() { 58589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint64_t answer = 0; 59589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#ifdef CAN_USE_FPU_INSTRUCTIONS 60589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch answer |= 1u << FPU; 61589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#endif // def CAN_USE_FPU_INSTRUCTIONS 62589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 63589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#ifdef __mips__ 64589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // If the compiler is allowed to use FPU then we can use FPU too in our code 65589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // generation even when generating snapshots. This won't work for cross 66589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // compilation. 67589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#if(defined(__mips_hard_float) && __mips_hard_float != 0) 68589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch answer |= 1u << FPU; 69589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#endif // defined(__mips_hard_float) && __mips_hard_float != 0 70589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#endif // def __mips__ 71589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 72589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return answer; 73589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch} 74589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 75589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 76257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid CpuFeatures::Probe() { 773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned standard_features = (OS::CpuFeaturesImpliedByPlatform() | 783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CpuFeaturesImpliedByCompiler()); 793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(supported_ == 0 || supported_ == standard_features); 80257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef DEBUG 81257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch initialized_ = true; 82257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif 83589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 84589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Get the features implied by the OS and the compiler settings. This is the 85589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // minimal set of features which is also allowed for generated code in the 86589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // snapshot. 873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch supported_ |= standard_features; 88589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 89589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (Serializer::enabled()) { 90589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // No probing for features if we might serialize (generate snapshot). 91589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return; 92589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 93589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 9444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // If the compiler is allowed to use fpu then we can use fpu too in our 9544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // code generation. 9644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#if !defined(__mips__) 9744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // For the simulator=mips build, use FPU when FLAG_enable_fpu is enabled. 9844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (FLAG_enable_fpu) { 9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block supported_ |= 1u << FPU; 10044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 10144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#else 102589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Probe for additional features not already known to be available. 10344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (OS::MipsCpuHasFeature(FPU)) { 10444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // This implementation also sets the FPU flags if 10544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // runtime detection of FPU returns true. 10644f0eee88ff00398ff7f715fab053374d808c90dSteve Block supported_ |= 1u << FPU; 10744f0eee88ff00398ff7f715fab053374d808c90dSteve Block found_by_runtime_probing_ |= 1u << FPU; 10844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 10944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif 11044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 1113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuint ToNumber(Register reg) { 1143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(reg.is_valid()); 1153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu const int kNumbers[] = { 1163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 0, // zero_reg 1173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1, // at 1183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2, // v0 1193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3, // v1 1203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 4, // a0 1213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 5, // a1 1223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 6, // a2 1233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7, // a3 1243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8, // t0 1253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9, // t1 1263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10, // t2 1273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11, // t3 1283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12, // t4 1293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13, // t5 1303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 14, // t6 1313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15, // t7 1323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 16, // s0 1333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 17, // s1 1343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18, // s2 1353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 19, // s3 1363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 20, // s4 1373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 21, // s5 1383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 22, // s6 1393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 23, // s7 1403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 24, // t8 1413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 25, // t9 1423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 26, // k0 1433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 27, // k1 1443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 28, // gp 1453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 29, // sp 146db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch 30, // fp 1473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 31, // ra 1483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu }; 1493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return kNumbers[reg.code()]; 1503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 1513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuRegister ToRegister(int num) { 1543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(num >= 0 && num < kNumRegisters); 1553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu const Register kRegisters[] = { 1563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu zero_reg, 1573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu at, 1583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu v0, v1, 1593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu a0, a1, a2, a3, 1603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu t0, t1, t2, t3, t4, t5, t6, t7, 1613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu s0, s1, s2, s3, s4, s5, s6, s7, 1623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu t8, t9, 1633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu k0, k1, 1643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu gp, 1653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu sp, 166db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch fp, 1673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ra 1683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu }; 1693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return kRegisters[num]; 1703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 1713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// ----------------------------------------------------------------------------- 1743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Implementation of RelocInfo. 1753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 176589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochconst int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask | 177589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1 << RelocInfo::INTERNAL_REFERENCE; 1783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 17944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 18044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool RelocInfo::IsCodedSpecially() { 18144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // The deserializer needs to know whether a pointer is specially coded. Being 18244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // specially coded on MIPS means that it is a lui/ori instruction, and that is 18344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // always the case inside code objects. 18444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return true; 18544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 18644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 18744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Patch the code at the current address with the supplied instructions. 1893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid RelocInfo::PatchCode(byte* instructions, int instruction_count) { 1903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr* pc = reinterpret_cast<Instr*>(pc_); 1913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr* instr = reinterpret_cast<Instr*>(instructions); 1923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu for (int i = 0; i < instruction_count; i++) { 1933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu *(pc + i) = *(instr + i); 1943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 1953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Indicate that code has changed. 1973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu CPU::FlushICache(pc_, instruction_count * Assembler::kInstrSize); 1983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 1993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Patch the code at the current PC with a call to the target address. 2023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Additional guard instructions can be added if required. 2033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) { 2043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Patch the code at the current address with a call to the target. 2053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNIMPLEMENTED_MIPS(); 2063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 2073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// ----------------------------------------------------------------------------- 2103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Implementation of Operand and MemOperand. 2113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// See assembler-mips-inl.h for inlined constructors. 2123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuOperand::Operand(Handle<Object> handle) { 2143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu rm_ = no_reg; 2153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Verify all Objects referred by code are NOT in new space. 2163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Object* obj = *handle; 21744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!HEAP->InNewSpace(obj)); 2183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (obj->IsHeapObject()) { 2193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu imm32_ = reinterpret_cast<intptr_t>(handle.location()); 2203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu rmode_ = RelocInfo::EMBEDDED_OBJECT; 2213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 2223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // No relocation needed. 2233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu imm32_ = reinterpret_cast<intptr_t>(obj); 2243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu rmode_ = RelocInfo::NONE; 2253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 2263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 2273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 22844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 22944f0eee88ff00398ff7f715fab053374d808c90dSteve BlockMemOperand::MemOperand(Register rm, int32_t offset) : Operand(rm) { 2303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu offset_ = offset; 2313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 2323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// ----------------------------------------------------------------------------- 23544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Specific instructions, constants, and masks. 23644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 23744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const int kNegOffset = 0x00008000; 23844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// addiu(sp, sp, 4) aka Pop() operation or part of Pop(r) 23944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// operations as post-increment of sp. 240db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdochconst Instr kPopInstruction = ADDIU | (kRegister_sp_Code << kRsShift) 241db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch | (kRegister_sp_Code << kRtShift) | (kPointerSize & kImm16Mask); 24244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// addiu(sp, sp, -4) part of Push(r) operation as pre-decrement of sp. 243db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdochconst Instr kPushInstruction = ADDIU | (kRegister_sp_Code << kRsShift) 244db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch | (kRegister_sp_Code << kRtShift) | (-kPointerSize & kImm16Mask); 24544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// sw(r, MemOperand(sp, 0)) 246db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdochconst Instr kPushRegPattern = SW | (kRegister_sp_Code << kRsShift) 24744f0eee88ff00398ff7f715fab053374d808c90dSteve Block | (0 & kImm16Mask); 24844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// lw(r, MemOperand(sp, 0)) 249db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdochconst Instr kPopRegPattern = LW | (kRegister_sp_Code << kRsShift) 25044f0eee88ff00398ff7f715fab053374d808c90dSteve Block | (0 & kImm16Mask); 25144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 252db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdochconst Instr kLwRegFpOffsetPattern = LW | (kRegister_fp_Code << kRsShift) 25344f0eee88ff00398ff7f715fab053374d808c90dSteve Block | (0 & kImm16Mask); 25444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 255db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdochconst Instr kSwRegFpOffsetPattern = SW | (kRegister_fp_Code << kRsShift) 25644f0eee88ff00398ff7f715fab053374d808c90dSteve Block | (0 & kImm16Mask); 25744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 258db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdochconst Instr kLwRegFpNegOffsetPattern = LW | (kRegister_fp_Code << kRsShift) 25944f0eee88ff00398ff7f715fab053374d808c90dSteve Block | (kNegOffset & kImm16Mask); 26044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 261db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdochconst Instr kSwRegFpNegOffsetPattern = SW | (kRegister_fp_Code << kRsShift) 26244f0eee88ff00398ff7f715fab053374d808c90dSteve Block | (kNegOffset & kImm16Mask); 26344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// A mask for the Rt register for push, pop, lw, sw instructions. 26444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst Instr kRtMask = kRtFieldMask; 26544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst Instr kLwSwInstrTypeMask = 0xffe00000; 26644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst Instr kLwSwInstrArgumentMask = ~kLwSwInstrTypeMask; 26744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst Instr kLwSwOffsetMask = kImm16Mask; 26844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 26944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 27044f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Spare buffer. 27144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const int kMinimalBufferSize = 4 * KB; 27244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 27344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochAssembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size) 275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : AssemblerBase(arg_isolate), 27644f0eee88ff00398ff7f715fab053374d808c90dSteve Block positions_recorder_(this), 277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch emit_debug_code_(FLAG_debug_code) { 2783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (buffer == NULL) { 2793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Do our own buffer management. 2803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (buffer_size <= kMinimalBufferSize) { 2813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu buffer_size = kMinimalBufferSize; 2823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 28344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (isolate()->assembler_spare_buffer() != NULL) { 28444f0eee88ff00398ff7f715fab053374d808c90dSteve Block buffer = isolate()->assembler_spare_buffer(); 28544f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->set_assembler_spare_buffer(NULL); 2863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 2873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 2883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (buffer == NULL) { 2893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu buffer_ = NewArray<byte>(buffer_size); 2903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 2913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu buffer_ = static_cast<byte*>(buffer); 2923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 2933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu buffer_size_ = buffer_size; 2943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu own_buffer_ = true; 2953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 2973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Use externally provided buffer instead. 2983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(buffer_size > 0); 2993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu buffer_ = static_cast<byte*>(buffer); 3003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu buffer_size_ = buffer_size; 3013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu own_buffer_ = false; 3023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 3033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up buffer pointers. 3053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(buffer_ != NULL); 3063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu pc_ = buffer_; 3073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); 30844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 30944f0eee88ff00398ff7f715fab053374d808c90dSteve Block last_trampoline_pool_end_ = 0; 31044f0eee88ff00398ff7f715fab053374d808c90dSteve Block no_trampoline_pool_before_ = 0; 31144f0eee88ff00398ff7f715fab053374d808c90dSteve Block trampoline_pool_blocked_nesting_ = 0; 3123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // We leave space (16 * kTrampolineSlotsSize) 3133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // for BlockTrampolinePoolScope buffer. 3143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch next_buffer_check_ = kMaxBranchOffset - kTrampolineSlotsSize * 16; 315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch internal_trampoline_exception_ = false; 316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch last_bound_pos_ = 0; 317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch trampoline_emitted_ = false; 3193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch unbound_labels_count_ = 0; 3203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch block_buffer_growth_ = false; 3213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ClearRecordedAstId(); 3233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 3243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuAssembler::~Assembler() { 3273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (own_buffer_) { 32844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (isolate()->assembler_spare_buffer() == NULL && 329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch buffer_size_ == kMinimalBufferSize) { 33044f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->set_assembler_spare_buffer(buffer_); 3313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 3323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu DeleteArray(buffer_); 3333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 3343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 3353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 3363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::GetCode(CodeDesc* desc) { 33944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(pc_ <= reloc_info_writer.pos()); // No overlap. 3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up code descriptor. 3413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu desc->buffer = buffer_; 3423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu desc->buffer_size = buffer_size_; 3433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu desc->instr_size = pc_offset(); 3443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 3453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 3463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 34844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::Align(int m) { 34944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(m >= 4 && IsPowerOf2(m)); 35044f0eee88ff00398ff7f715fab053374d808c90dSteve Block while ((pc_offset() & (m - 1)) != 0) { 35144f0eee88ff00398ff7f715fab053374d808c90dSteve Block nop(); 35244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 35344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 35444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 35544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 35644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::CodeTargetAlign() { 35744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // No advantage to aligning branch/call targets to more than 35844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // single instruction, that I am aware of. 35944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Align(4); 36044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 36144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 36244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochRegister Assembler::GetRtReg(Instr instr) { 36444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register rt; 365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch rt.code_ = (instr & kRtFieldMask) >> kRtShift; 36644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return rt; 36744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 36844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 36944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochRegister Assembler::GetRsReg(Instr instr) { 371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register rs; 372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch rs.code_ = (instr & kRsFieldMask) >> kRsShift; 373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return rs; 374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochRegister Assembler::GetRdReg(Instr instr) { 378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register rd; 379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch rd.code_ = (instr & kRdFieldMask) >> kRdShift; 380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return rd; 381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetRt(Instr instr) { 385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return (instr & kRtFieldMask) >> kRtShift; 386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetRtField(Instr instr) { 390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return instr & kRtFieldMask; 391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetRs(Instr instr) { 395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return (instr & kRsFieldMask) >> kRsShift; 396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetRsField(Instr instr) { 400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return instr & kRsFieldMask; 401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetRd(Instr instr) { 405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return (instr & kRdFieldMask) >> kRdShift; 406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetRdField(Instr instr) { 410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return instr & kRdFieldMask; 411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetSa(Instr instr) { 415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return (instr & kSaFieldMask) >> kSaShift; 416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetSaField(Instr instr) { 420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return instr & kSaFieldMask; 421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetOpcodeField(Instr instr) { 425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return instr & kOpcodeMask; 426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochuint32_t Assembler::GetFunction(Instr instr) { 4303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return (instr & kFunctionFieldMask) >> kFunctionShift; 4313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 4323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochuint32_t Assembler::GetFunctionField(Instr instr) { 4353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return instr & kFunctionFieldMask; 4363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 4373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetImmediate16(Instr instr) { 440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return instr & kImm16Mask; 441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetLabelConst(Instr instr) { 445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return instr & ~kImm16Mask; 446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 44944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsPop(Instr instr) { 45044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return (instr & ~kRtMask) == kPopRegPattern; 45144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 45244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 45344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 45444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsPush(Instr instr) { 45544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return (instr & ~kRtMask) == kPushRegPattern; 45644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 45744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 45844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 45944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsSwRegFpOffset(Instr instr) { 46044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return ((instr & kLwSwInstrTypeMask) == kSwRegFpOffsetPattern); 46144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 46244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 46344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 46444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsLwRegFpOffset(Instr instr) { 46544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return ((instr & kLwSwInstrTypeMask) == kLwRegFpOffsetPattern); 46644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 46744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 46844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 46944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsSwRegFpNegOffset(Instr instr) { 47044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return ((instr & (kLwSwInstrTypeMask | kNegOffset)) == 47144f0eee88ff00398ff7f715fab053374d808c90dSteve Block kSwRegFpNegOffsetPattern); 47244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 47344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 47444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 47544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsLwRegFpNegOffset(Instr instr) { 47644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return ((instr & (kLwSwInstrTypeMask | kNegOffset)) == 47744f0eee88ff00398ff7f715fab053374d808c90dSteve Block kLwRegFpNegOffsetPattern); 47844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 47944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 48044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 4813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Labels refer to positions in the (to be) generated code. 4823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// There are bound, linked, and unused labels. 4833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// 4843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Bound labels refer to known positions in the already 4853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// generated code. pos() is the position the label refers to. 4863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// 4873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Linked labels refer to unknown positions in the code 4883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// to be generated; pos() is the position of the last 4893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// instruction using the label. 4903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 49144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// The link chain is terminated by a value in the instruction of -1, 49244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// which is an otherwise illegal value (branch -1 is inf loop). 49344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// The instruction 16-bit offset field addresses 32-bit words, but in 49444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// code is conv to an 18-bit value addressing bytes, hence the -4 value. 4953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 4963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuconst int kEndOfChain = -4; 4973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// Determines the end of the Jump chain (a subset of the label link chain). 4983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochconst int kEndOfJumpChain = 0; 4993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 50044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 50144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsBranch(Instr instr) { 502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uint32_t opcode = GetOpcodeField(instr); 503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uint32_t rt_field = GetRtField(instr); 504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uint32_t rs_field = GetRsField(instr); 505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uint32_t label_constant = GetLabelConst(instr); 5063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Checks if the instruction is a branch. 5073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return opcode == BEQ || 5083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu opcode == BNE || 5093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu opcode == BLEZ || 5103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu opcode == BGTZ || 5113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu opcode == BEQL || 5123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu opcode == BNEL || 5133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu opcode == BLEZL || 514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch opcode == BGTZL || 5153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ || 5163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu rt_field == BLTZAL || rt_field == BGEZAL)) || 51744f0eee88ff00398ff7f715fab053374d808c90dSteve Block (opcode == COP1 && rs_field == BC1) || // Coprocessor branch. 51844f0eee88ff00398ff7f715fab053374d808c90dSteve Block label_constant == 0; // Emitted label const in reg-exp engine. 51944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 52044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 52144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochbool Assembler::IsBeq(Instr instr) { 523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetOpcodeField(instr) == BEQ; 524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochbool Assembler::IsBne(Instr instr) { 528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetOpcodeField(instr) == BNE; 529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochbool Assembler::IsJump(Instr instr) { 5333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t opcode = GetOpcodeField(instr); 5343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t rt_field = GetRtField(instr); 5353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t rd_field = GetRdField(instr); 5363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t function_field = GetFunctionField(instr); 5373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Checks if the instruction is a jump. 5383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return opcode == J || opcode == JAL || 5393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch (opcode == SPECIAL && rt_field == 0 && 5403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ((function_field == JALR) || (rd_field == 0 && (function_field == JR)))); 5413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 5423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 5433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 5443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochbool Assembler::IsJ(Instr instr) { 5453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t opcode = GetOpcodeField(instr); 5463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Checks if the instruction is a jump. 5473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return opcode == J; 5483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 5493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 5503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 551589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochbool Assembler::IsJal(Instr instr) { 552589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return GetOpcodeField(instr) == JAL; 553589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch} 554589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 555589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochbool Assembler::IsJr(Instr instr) { 556589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JR; 557589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch} 558589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 559589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochbool Assembler::IsJalr(Instr instr) { 560589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JALR; 561589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch} 562589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 563589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 5643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochbool Assembler::IsLui(Instr instr) { 5653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t opcode = GetOpcodeField(instr); 5663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Checks if the instruction is a load upper immediate. 5673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return opcode == LUI; 5683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 5693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 5703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 5713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochbool Assembler::IsOri(Instr instr) { 5723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t opcode = GetOpcodeField(instr); 5733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Checks if the instruction is a load upper immediate. 5743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return opcode == ORI; 5753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 5763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 5773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 57844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsNop(Instr instr, unsigned int type) { 57944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // See Assembler::nop(type). 58044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(type < 32); 581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uint32_t opcode = GetOpcodeField(instr); 582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uint32_t rt = GetRt(instr); 583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uint32_t rs = GetRs(instr); 584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uint32_t sa = GetSa(instr); 58544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 58644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // nop(type) == sll(zero_reg, zero_reg, type); 58744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Technically all these values will be 0 but 58844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // this makes more sense to the reader. 58944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 59044f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool ret = (opcode == SLL && 59144f0eee88ff00398ff7f715fab053374d808c90dSteve Block rt == static_cast<uint32_t>(ToNumber(zero_reg)) && 59244f0eee88ff00398ff7f715fab053374d808c90dSteve Block rs == static_cast<uint32_t>(ToNumber(zero_reg)) && 59344f0eee88ff00398ff7f715fab053374d808c90dSteve Block sa == type); 59444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 59544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return ret; 59644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 59744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 59844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 59944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint32_t Assembler::GetBranchOffset(Instr instr) { 60044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(IsBranch(instr)); 60144f0eee88ff00398ff7f715fab053374d808c90dSteve Block return ((int16_t)(instr & kImm16Mask)) << 2; 60244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 60344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 60444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 60544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsLw(Instr instr) { 60644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return ((instr & kOpcodeMask) == LW); 60744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 60844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 60944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 61044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint16_t Assembler::GetLwOffset(Instr instr) { 61144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(IsLw(instr)); 61244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return ((instr & kImm16Mask)); 61344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 61444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 61544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 61644f0eee88ff00398ff7f715fab053374d808c90dSteve BlockInstr Assembler::SetLwOffset(Instr instr, int16_t offset) { 61744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(IsLw(instr)); 61844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 61944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // We actually create a new lw instruction based on the original one. 62044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Instr temp_instr = LW | (instr & kRsFieldMask) | (instr & kRtFieldMask) 62144f0eee88ff00398ff7f715fab053374d808c90dSteve Block | (offset & kImm16Mask); 62244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 62344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return temp_instr; 62444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 62544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 62644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 62744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsSw(Instr instr) { 62844f0eee88ff00398ff7f715fab053374d808c90dSteve Block return ((instr & kOpcodeMask) == SW); 62944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 63044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 63144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 63244f0eee88ff00398ff7f715fab053374d808c90dSteve BlockInstr Assembler::SetSwOffset(Instr instr, int16_t offset) { 63344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(IsSw(instr)); 63444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); 63544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 63644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 63744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 63844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsAddImmediate(Instr instr) { 63944f0eee88ff00398ff7f715fab053374d808c90dSteve Block return ((instr & kOpcodeMask) == ADDIU); 64044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 64144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 64244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 64344f0eee88ff00398ff7f715fab053374d808c90dSteve BlockInstr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) { 64444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(IsAddImmediate(instr)); 64544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); 6463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 6473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 6483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochbool Assembler::IsAndImmediate(Instr instr) { 650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetOpcodeField(instr) == ANDI; 651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuint Assembler::target_at(int32_t pos) { 6553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr = instr_at(pos); 6563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if ((instr & ~kImm16Mask) == 0) { 6573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Emitted label constant, not part of a branch. 65844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr == 0) { 65944f0eee88ff00398ff7f715fab053374d808c90dSteve Block return kEndOfChain; 66044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 66144f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; 66244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return (imm18 + pos); 66344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 6643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 6653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check we have a branch or jump instruction. 6663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(IsBranch(instr) || IsJ(instr) || IsLui(instr)); 6673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming 6683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // the compiler uses arithmectic shifts for signed integers. 6693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (IsBranch(instr)) { 6703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int32_t imm18 = ((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; 6713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 6723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (imm18 == kEndOfChain) { 6733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // EndOfChain sentinel is returned directly, not relative to pc or pos. 6743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return kEndOfChain; 6753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 6763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return pos + kBranchPCOffset + imm18; 6773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else if (IsLui(instr)) { 6793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); 6803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); 6813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(IsOri(instr_ori)); 6823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; 6833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch imm |= (instr_ori & static_cast<int32_t>(kImm16Mask)); 6843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (imm == kEndOfJumpChain) { 6863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // EndOfChain sentinel is returned directly, not relative to pc or pos. 6873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return kEndOfChain; 6883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 6893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); 6903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int32_t delta = instr_address - imm; 6913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(pos > delta); 6923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return pos - delta; 6933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 69444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 6953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; 6963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (imm28 == kEndOfJumpChain) { 6973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // EndOfChain sentinel is returned directly, not relative to pc or pos. 6983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return kEndOfChain; 6993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 7003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); 7013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr_address &= kImm28Mask; 7023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int32_t delta = instr_address - imm28; 7033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(pos > delta); 7043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return pos - delta; 7053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 70644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 7073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 7083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::target_at_put(int32_t pos, int32_t target_pos) { 7113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr = instr_at(pos); 7123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if ((instr & ~kImm16Mask) == 0) { 7133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(target_pos == kEndOfChain || target_pos >= 0); 7143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Emitted label constant, not part of a branch. 7153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Make label relative to Code* of generated Code object. 7163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); 7173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return; 7183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 7193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(IsBranch(instr) || IsJ(instr) || IsLui(instr)); 7213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (IsBranch(instr)) { 7223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int32_t imm18 = target_pos - (pos + kBranchPCOffset); 7233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT((imm18 & 3) == 0); 7243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr &= ~kImm16Mask; 7263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int32_t imm16 = imm18 >> 2; 7273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(is_int16(imm16)); 7283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr_at_put(pos, instr | (imm16 & kImm16Mask)); 7303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else if (IsLui(instr)) { 7313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); 7323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); 7333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(IsOri(instr_ori)); 7343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t imm = (uint32_t)buffer_ + target_pos; 7353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT((imm & 3) == 0); 7363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr_lui &= ~kImm16Mask; 7383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr_ori &= ~kImm16Mask; 7393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr_at_put(pos + 0 * Assembler::kInstrSize, 7413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr_lui | ((imm & kHiMask) >> kLuiShift)); 7423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr_at_put(pos + 1 * Assembler::kInstrSize, 7433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr_ori | (imm & kImm16Mask)); 7443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 7453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t imm28 = (uint32_t)buffer_ + target_pos; 7463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch imm28 &= kImm28Mask; 7473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT((imm28 & 3) == 0); 7483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr &= ~kImm26Mask; 7503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t imm26 = imm28 >> 2; 7513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(is_uint26(imm26)); 7523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr_at_put(pos, instr | (imm26 & kImm26Mask)); 7543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 7553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 7563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::print(Label* L) { 7593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (L->is_unused()) { 7603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("unused label\n"); 7613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else if (L->is_bound()) { 7623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("bound label to %d\n", L->pos()); 7633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else if (L->is_linked()) { 7643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label l = *L; 7653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("unbound label"); 7663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu while (l.is_linked()) { 7673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("@ %d ", l.pos()); 7683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr = instr_at(l.pos()); 7693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if ((instr & ~kImm16Mask) == 0) { 7703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("value\n"); 7713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 7723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("%d\n", instr); 7733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 7743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu next(&l); 7753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 7763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 7773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("label in inconsistent state (pos = %d)\n", L->pos_); 7783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 7793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 7803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bind_to(Label* L, int pos) { 78344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(0 <= pos && pos <= pc_offset()); // Must have valid binding position. 7843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int32_t trampoline_pos = kInvalidSlotPos; 7853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (L->is_linked() && !trampoline_emitted_) { 7863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch unbound_labels_count_--; 7873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch next_buffer_check_ += kTrampolineSlotsSize; 7883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 7893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu while (L->is_linked()) { 7913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t fixup_pos = L->pos(); 79244f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t dist = pos - fixup_pos; 79344f0eee88ff00398ff7f715fab053374d808c90dSteve Block next(L); // Call next before overwriting link with target at fixup_pos. 7943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Instr instr = instr_at(fixup_pos); 7953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (IsBranch(instr)) { 7963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (dist > kMaxBranchOffset) { 7973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (trampoline_pos == kInvalidSlotPos) { 7983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch trampoline_pos = get_trampoline_entry(fixup_pos); 7993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CHECK(trampoline_pos != kInvalidSlotPos); 800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 80144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT((trampoline_pos - fixup_pos) <= kMaxBranchOffset); 80244f0eee88ff00398ff7f715fab053374d808c90dSteve Block target_at_put(fixup_pos, trampoline_pos); 80344f0eee88ff00398ff7f715fab053374d808c90dSteve Block fixup_pos = trampoline_pos; 80444f0eee88ff00398ff7f715fab053374d808c90dSteve Block dist = pos - fixup_pos; 8053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch target_at_put(fixup_pos, pos); 8073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 8083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(IsJ(instr) || IsLui(instr)); 8093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch target_at_put(fixup_pos, pos); 8103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 8123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu L->bind_to(pos); 8133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Keep track of the last bound label so we don't eliminate any instructions 8153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // before a bound label. 8163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (pos > last_bound_pos_) 8173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu last_bound_pos_ = pos; 8183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 8193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bind(Label* L) { 82244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!L->is_bound()); // Label can only be bound once. 8233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bind_to(L, pc_offset()); 8243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 8253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::next(Label* L) { 8283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(L->is_linked()); 8293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int link = target_at(L->pos()); 83044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (link == kEndOfChain) { 8313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu L->Unuse(); 83269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else { 83369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch ASSERT(link >= 0); 83444f0eee88ff00398ff7f715fab053374d808c90dSteve Block L->link_to(link); 8353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 8363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 8373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochbool Assembler::is_near(Label* L) { 8393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (L->is_bound()) { 8403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ((pc_offset() - L->pos()) < kMaxBranchOffset - 4 * kInstrSize); 8413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return false; 8433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 8443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// We have to use a temporary register for things that can be relocated even 8463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// if they can be encoded in the MIPS's 16 bits of immediate-offset instruction 8473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// space. There is no guarantee that the relocated location can be similarly 8483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// encoded. 84944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::MustUseReg(RelocInfo::Mode rmode) { 85044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return rmode != RelocInfo::NONE; 8513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 8523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::GenInstrRegister(Opcode opcode, 8543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register rs, 8553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register rt, 8563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register rd, 8573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uint16_t sa, 8583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SecondaryField func) { 8593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(rd.is_valid() && rs.is_valid() && rt.is_valid() && is_uint5(sa)); 8603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift) 8613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu | (rd.code() << kRdShift) | (sa << kSaShift) | func; 8623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu emit(instr); 8633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 8643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::GenInstrRegister(Opcode opcode, 86744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register rs, 86844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register rt, 86944f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint16_t msb, 87044f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint16_t lsb, 87144f0eee88ff00398ff7f715fab053374d808c90dSteve Block SecondaryField func) { 87244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(rs.is_valid() && rt.is_valid() && is_uint5(msb) && is_uint5(lsb)); 87344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift) 87444f0eee88ff00398ff7f715fab053374d808c90dSteve Block | (msb << kRdShift) | (lsb << kSaShift) | func; 87544f0eee88ff00398ff7f715fab053374d808c90dSteve Block emit(instr); 87644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 87744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 87844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 87944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::GenInstrRegister(Opcode opcode, 8803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SecondaryField fmt, 8813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu FPURegister ft, 8823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu FPURegister fs, 8833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu FPURegister fd, 8843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SecondaryField func) { 8853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(fd.is_valid() && fs.is_valid() && ft.is_valid()); 886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(CpuFeatures::IsEnabled(FPU)); 88744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Instr instr = opcode | fmt | (ft.code() << kFtShift) | (fs.code() << kFsShift) 88844f0eee88ff00398ff7f715fab053374d808c90dSteve Block | (fd.code() << kFdShift) | func; 8893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu emit(instr); 8903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 8913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::GenInstrRegister(Opcode opcode, 8943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SecondaryField fmt, 8953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register rt, 8963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu FPURegister fs, 8973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu FPURegister fd, 8983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SecondaryField func) { 8993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(fd.is_valid() && fs.is_valid() && rt.is_valid()); 900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(CpuFeatures::IsEnabled(FPU)); 9013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr = opcode | fmt | (rt.code() << kRtShift) 90244f0eee88ff00398ff7f715fab053374d808c90dSteve Block | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func; 90344f0eee88ff00398ff7f715fab053374d808c90dSteve Block emit(instr); 90444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 90544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 90644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 90744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::GenInstrRegister(Opcode opcode, 90844f0eee88ff00398ff7f715fab053374d808c90dSteve Block SecondaryField fmt, 90944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register rt, 91044f0eee88ff00398ff7f715fab053374d808c90dSteve Block FPUControlRegister fs, 91144f0eee88ff00398ff7f715fab053374d808c90dSteve Block SecondaryField func) { 91244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(fs.is_valid() && rt.is_valid()); 913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(CpuFeatures::IsEnabled(FPU)); 91444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Instr instr = 91544f0eee88ff00398ff7f715fab053374d808c90dSteve Block opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func; 9163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu emit(instr); 9173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 9183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Instructions with immediate value. 9213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Registers are in the order of the instruction encoding, from left to right. 9223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::GenInstrImmediate(Opcode opcode, 9233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register rs, 9243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register rt, 9253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t j) { 9263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j))); 9273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift) 9283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu | (j & kImm16Mask); 9293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu emit(instr); 9303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 9313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::GenInstrImmediate(Opcode opcode, 9343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register rs, 9353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SecondaryField SF, 9363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t j) { 9373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(rs.is_valid() && (is_int16(j) || is_uint16(j))); 9383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask); 9393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu emit(instr); 9403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 9413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::GenInstrImmediate(Opcode opcode, 9443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register rs, 9453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu FPURegister ft, 9463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t j) { 9473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j))); 948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(CpuFeatures::IsEnabled(FPU)); 9493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift) 9503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu | (j & kImm16Mask); 9513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu emit(instr); 9523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 9533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::GenInstrJump(Opcode opcode, 956589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint32_t address) { 95744f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolScope block_trampoline_pool(this); 9583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(is_uint26(address)); 9593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr = opcode | address; 9603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu emit(instr); 96144f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolFor(1); // For associated delay slot. 96244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 96344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 96444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 9653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// Returns the next free trampoline entry. 9663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochint32_t Assembler::get_trampoline_entry(int32_t pos) { 9673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int32_t trampoline_entry = kInvalidSlotPos; 96844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 9693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!internal_trampoline_exception_) { 9703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (trampoline_.start() > pos) { 9713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch trampoline_entry = trampoline_.take_slot(); 97244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 9733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 9743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (kInvalidSlotPos == trampoline_entry) { 9753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch internal_trampoline_exception_ = true; 97644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 97744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 9783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return trampoline_entry; 97944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 98044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 98144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 9823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochuint32_t Assembler::jump_address(Label* L) { 9833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int32_t target_pos; 98444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 9853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (L->is_bound()) { 9863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch target_pos = L->pos(); 9873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 9883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (L->is_linked()) { 9893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch target_pos = L->pos(); // L's link. 9903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch L->link_to(pc_offset()); 9913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 9923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch L->link_to(pc_offset()); 9933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return kEndOfJumpChain; 994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 99544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 9963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 9973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t imm = (uint32_t)buffer_ + target_pos; 9983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT((imm & 3) == 0); 9993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 10003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return imm; 10013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 10023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuint32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { 10053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t target_pos; 100644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 10073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (L->is_bound()) { 10083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu target_pos = L->pos(); 10093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 10103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (L->is_linked()) { 10113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch target_pos = L->pos(); 101244f0eee88ff00398ff7f715fab053374d808c90dSteve Block L->link_to(pc_offset()); 10133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 101444f0eee88ff00398ff7f715fab053374d808c90dSteve Block L->link_to(pc_offset()); 10153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!trampoline_emitted_) { 10163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch unbound_labels_count_++; 10173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch next_buffer_check_ -= kTrampolineSlotsSize; 10183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 101944f0eee88ff00398ff7f715fab053374d808c90dSteve Block return kEndOfChain; 10203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 10213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 10223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t offset = target_pos - (pc_offset() + kBranchPCOffset); 102444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT((offset & 3) == 0); 102544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(is_int16(offset >> 2)); 102644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 10273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return offset; 10283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 10293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::label_at_put(Label* L, int at_offset) { 10323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int target_pos; 10333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (L->is_bound()) { 10343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu target_pos = L->pos(); 103544f0eee88ff00398ff7f715fab053374d808c90dSteve Block instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag)); 10363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 10373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (L->is_linked()) { 103844f0eee88ff00398ff7f715fab053374d808c90dSteve Block target_pos = L->pos(); // L's link. 103944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t imm18 = target_pos - at_offset; 104044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT((imm18 & 3) == 0); 104144f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t imm16 = imm18 >> 2; 104244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(is_int16(imm16)); 104344f0eee88ff00398ff7f715fab053374d808c90dSteve Block instr_at_put(at_offset, (imm16 & kImm16Mask)); 10443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 10453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu target_pos = kEndOfChain; 104644f0eee88ff00398ff7f715fab053374d808c90dSteve Block instr_at_put(at_offset, 0); 10473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!trampoline_emitted_) { 10483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch unbound_labels_count_++; 10493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch next_buffer_check_ -= kTrampolineSlotsSize; 10503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 10513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 10523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu L->link_to(at_offset); 10533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 10543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 10553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//------- Branch and jump instructions -------- 10583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::b(int16_t offset) { 10603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu beq(zero_reg, zero_reg, offset); 10613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 10623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bal(int16_t offset) { 106544f0eee88ff00398ff7f715fab053374d808c90dSteve Block positions_recorder()->WriteRecordedPositions(); 10663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bgezal(zero_reg, offset); 10673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 10683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::beq(Register rs, Register rt, int16_t offset) { 107144f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolScope block_trampoline_pool(this); 10723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrImmediate(BEQ, rs, rt, offset); 107344f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolFor(1); // For associated delay slot. 10743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 10753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bgez(Register rs, int16_t offset) { 107844f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolScope block_trampoline_pool(this); 10793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrImmediate(REGIMM, rs, BGEZ, offset); 108044f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolFor(1); // For associated delay slot. 10813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 10823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bgezal(Register rs, int16_t offset) { 108544f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolScope block_trampoline_pool(this); 108644f0eee88ff00398ff7f715fab053374d808c90dSteve Block positions_recorder()->WriteRecordedPositions(); 10873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrImmediate(REGIMM, rs, BGEZAL, offset); 108844f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolFor(1); // For associated delay slot. 10893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 10903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bgtz(Register rs, int16_t offset) { 109344f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolScope block_trampoline_pool(this); 10943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrImmediate(BGTZ, rs, zero_reg, offset); 109544f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolFor(1); // For associated delay slot. 10963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 10973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::blez(Register rs, int16_t offset) { 110044f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolScope block_trampoline_pool(this); 11013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrImmediate(BLEZ, rs, zero_reg, offset); 110244f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolFor(1); // For associated delay slot. 11033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 11043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bltz(Register rs, int16_t offset) { 110744f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolScope block_trampoline_pool(this); 11083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrImmediate(REGIMM, rs, BLTZ, offset); 110944f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolFor(1); // For associated delay slot. 11103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 11113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bltzal(Register rs, int16_t offset) { 111444f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolScope block_trampoline_pool(this); 111544f0eee88ff00398ff7f715fab053374d808c90dSteve Block positions_recorder()->WriteRecordedPositions(); 11163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrImmediate(REGIMM, rs, BLTZAL, offset); 111744f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolFor(1); // For associated delay slot. 11183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 11193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bne(Register rs, Register rt, int16_t offset) { 112244f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolScope block_trampoline_pool(this); 11233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrImmediate(BNE, rs, rt, offset); 112444f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolFor(1); // For associated delay slot. 11253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 11263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::j(int32_t target) { 1129589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#if DEBUG 1130589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Get pc of delay slot. 1131589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize); 1132589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch bool in_range = ((uint32_t)(ipc^target) >> (kImm26Bits+kImmFieldShift)) == 0; 1133589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(in_range && ((target & 3) == 0)); 1134589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#endif 11353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrJump(J, target >> 2); 11363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 11373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::jr(Register rs) { 114044f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolScope block_trampoline_pool(this); 114144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (rs.is(ra)) { 114244f0eee88ff00398ff7f715fab053374d808c90dSteve Block positions_recorder()->WriteRecordedPositions(); 114344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 11443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR); 114544f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolFor(1); // For associated delay slot. 11463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 11473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::jal(int32_t target) { 1150589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#ifdef DEBUG 1151589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Get pc of delay slot. 1152589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize); 1153589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch bool in_range = ((uint32_t)(ipc^target) >> (kImm26Bits+kImmFieldShift)) == 0; 1154589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(in_range && ((target & 3) == 0)); 1155589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#endif 115644f0eee88ff00398ff7f715fab053374d808c90dSteve Block positions_recorder()->WriteRecordedPositions(); 11573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrJump(JAL, target >> 2); 11583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 11593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::jalr(Register rs, Register rd) { 116244f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolScope block_trampoline_pool(this); 116344f0eee88ff00398ff7f715fab053374d808c90dSteve Block positions_recorder()->WriteRecordedPositions(); 11643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR); 116544f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolFor(1); // For associated delay slot. 11663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 11673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1169589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid Assembler::j_or_jr(int32_t target, Register rs) { 1170589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Get pc of delay slot. 1171589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize); 1172589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch bool in_range = ((uint32_t)(ipc^target) >> (kImm26Bits+kImmFieldShift)) == 0; 1173589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1174589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (in_range) { 1175589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch j(target); 1176589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 1177589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch jr(t9); 1178589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 1179589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch} 1180589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1181589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1182589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid Assembler::jal_or_jalr(int32_t target, Register rs) { 1183589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Get pc of delay slot. 1184589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize); 1185589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch bool in_range = ((uint32_t)(ipc^target) >> (kImm26Bits+kImmFieldShift)) == 0; 1186589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1187589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (in_range) { 1188589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch jal(target); 1189589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 1190589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch jalr(t9); 1191589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 1192589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch} 1193589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1194589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 11953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//-------Data-processing-instructions--------- 11963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Arithmetic. 11983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::addu(Register rd, Register rs, Register rt) { 12003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU); 12013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::addiu(Register rd, Register rs, int32_t j) { 12053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrImmediate(ADDIU, rs, rd, j); 12063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::subu(Register rd, Register rs, Register rt) { 12103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU); 12113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::mul(Register rd, Register rs, Register rt) { 12153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL); 12163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::mult(Register rs, Register rt) { 12203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULT); 12213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::multu(Register rs, Register rt) { 12253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULTU); 12263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::div(Register rs, Register rt) { 12303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIV); 12313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::divu(Register rs, Register rt) { 12353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIVU); 12363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Logical. 12403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::and_(Register rd, Register rs, Register rt) { 12423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, rs, rt, rd, 0, AND); 12433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::andi(Register rt, Register rs, int32_t j) { 12473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(is_uint16(j)); 12483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrImmediate(ANDI, rs, rt, j); 12493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::or_(Register rd, Register rs, Register rt) { 12533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, rs, rt, rd, 0, OR); 12543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::ori(Register rt, Register rs, int32_t j) { 12583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(is_uint16(j)); 12593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrImmediate(ORI, rs, rt, j); 12603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::xor_(Register rd, Register rs, Register rt) { 12643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, rs, rt, rd, 0, XOR); 12653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::xori(Register rt, Register rs, int32_t j) { 12693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(is_uint16(j)); 12703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrImmediate(XORI, rs, rt, j); 12713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::nor(Register rd, Register rs, Register rt) { 12753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, rs, rt, rd, 0, NOR); 12763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Shifts. 128044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::sll(Register rd, 128144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register rt, 128244f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint16_t sa, 128344f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool coming_from_nop) { 128444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Don't allow nop instructions in the form sll zero_reg, zero_reg to be 128544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // generated using the sll instruction. They must be generated using 128644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // nop(int/NopMarkerTypes) or MarkCode(int/NopMarkerTypes) pseudo 128744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // instructions. 128844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(coming_from_nop || !(rd.is(zero_reg) && rt.is(zero_reg))); 12893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SLL); 12903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::sllv(Register rd, Register rt, Register rs) { 12943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLLV); 12953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::srl(Register rd, Register rt, uint16_t sa) { 12993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SRL); 13003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 13013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::srlv(Register rd, Register rt, Register rs) { 13043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRLV); 13053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 13063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::sra(Register rd, Register rt, uint16_t sa) { 13093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SRA); 13103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 13113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::srav(Register rd, Register rt, Register rs) { 13143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRAV); 13153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 13163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 131844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::rotr(Register rd, Register rt, uint16_t sa) { 131944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Should be called via MacroAssembler::Ror. 132044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(rd.is_valid() && rt.is_valid() && is_uint5(sa)); 13213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(kArchVariant == kMips32r2); 132244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift) 132344f0eee88ff00398ff7f715fab053374d808c90dSteve Block | (rd.code() << kRdShift) | (sa << kSaShift) | SRL; 132444f0eee88ff00398ff7f715fab053374d808c90dSteve Block emit(instr); 132544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 132644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 132744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 132844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::rotrv(Register rd, Register rt, Register rs) { 132944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Should be called via MacroAssembler::Ror. 133044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(rd.is_valid() && rt.is_valid() && rs.is_valid() ); 13313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(kArchVariant == kMips32r2); 133244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift) 133344f0eee88ff00398ff7f715fab053374d808c90dSteve Block | (rd.code() << kRdShift) | (1 << kSaShift) | SRLV; 133444f0eee88ff00398ff7f715fab053374d808c90dSteve Block emit(instr); 133544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 133644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 133744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 13383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//------------Memory-instructions------------- 13393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 134044f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Helper for base-reg + offset, when offset is larger than int16. 134144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::LoadRegPlusOffsetToAt(const MemOperand& src) { 134244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!src.rm().is(at)); 134344f0eee88ff00398ff7f715fab053374d808c90dSteve Block lui(at, src.offset_ >> kLuiShift); 134444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ori(at, at, src.offset_ & kImm16Mask); // Load 32-bit offset. 134544f0eee88ff00398ff7f715fab053374d808c90dSteve Block addu(at, at, src.rm()); // Add base register. 134644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 134744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 134844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 13493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::lb(Register rd, const MemOperand& rs) { 135044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_int16(rs.offset_)) { 135144f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(LB, rs.rm(), rd, rs.offset_); 135244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { // Offset > 16 bits, use multiple instructions to load. 135344f0eee88ff00398ff7f715fab053374d808c90dSteve Block LoadRegPlusOffsetToAt(rs); 135444f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(LB, at, rd, 0); // Equiv to lb(rd, MemOperand(at, 0)); 135544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 13563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 13573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::lbu(Register rd, const MemOperand& rs) { 136044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_int16(rs.offset_)) { 136144f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(LBU, rs.rm(), rd, rs.offset_); 136244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { // Offset > 16 bits, use multiple instructions to load. 136344f0eee88ff00398ff7f715fab053374d808c90dSteve Block LoadRegPlusOffsetToAt(rs); 136444f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(LBU, at, rd, 0); // Equiv to lbu(rd, MemOperand(at, 0)); 136544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 136644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 136744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 136844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 136944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::lh(Register rd, const MemOperand& rs) { 137044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_int16(rs.offset_)) { 137144f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(LH, rs.rm(), rd, rs.offset_); 137244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { // Offset > 16 bits, use multiple instructions to load. 137344f0eee88ff00398ff7f715fab053374d808c90dSteve Block LoadRegPlusOffsetToAt(rs); 137444f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(LH, at, rd, 0); // Equiv to lh(rd, MemOperand(at, 0)); 137544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 137644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 137744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 137844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 137944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::lhu(Register rd, const MemOperand& rs) { 138044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_int16(rs.offset_)) { 138144f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(LHU, rs.rm(), rd, rs.offset_); 138244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { // Offset > 16 bits, use multiple instructions to load. 138344f0eee88ff00398ff7f715fab053374d808c90dSteve Block LoadRegPlusOffsetToAt(rs); 138444f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(LHU, at, rd, 0); // Equiv to lhu(rd, MemOperand(at, 0)); 138544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 13863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 13873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::lw(Register rd, const MemOperand& rs) { 139044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_int16(rs.offset_)) { 139144f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(LW, rs.rm(), rd, rs.offset_); 139244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { // Offset > 16 bits, use multiple instructions to load. 139344f0eee88ff00398ff7f715fab053374d808c90dSteve Block LoadRegPlusOffsetToAt(rs); 139444f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(LW, at, rd, 0); // Equiv to lw(rd, MemOperand(at, 0)); 139544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 139644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 139744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 139844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 139944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::lwl(Register rd, const MemOperand& rs) { 140044f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_); 140144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 140244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 140344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 140444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::lwr(Register rd, const MemOperand& rs) { 140544f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_); 14063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 14073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 14083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 14093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::sb(Register rd, const MemOperand& rs) { 141044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_int16(rs.offset_)) { 141144f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(SB, rs.rm(), rd, rs.offset_); 141244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { // Offset > 16 bits, use multiple instructions to store. 141344f0eee88ff00398ff7f715fab053374d808c90dSteve Block LoadRegPlusOffsetToAt(rs); 141444f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(SB, at, rd, 0); // Equiv to sb(rd, MemOperand(at, 0)); 141544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 141644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 141744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 141844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 141944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::sh(Register rd, const MemOperand& rs) { 142044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_int16(rs.offset_)) { 142144f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(SH, rs.rm(), rd, rs.offset_); 142244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { // Offset > 16 bits, use multiple instructions to store. 142344f0eee88ff00398ff7f715fab053374d808c90dSteve Block LoadRegPlusOffsetToAt(rs); 142444f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(SH, at, rd, 0); // Equiv to sh(rd, MemOperand(at, 0)); 142544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 14263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 14273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 14283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 14293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::sw(Register rd, const MemOperand& rs) { 143044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_int16(rs.offset_)) { 143144f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(SW, rs.rm(), rd, rs.offset_); 143244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { // Offset > 16 bits, use multiple instructions to store. 143344f0eee88ff00398ff7f715fab053374d808c90dSteve Block LoadRegPlusOffsetToAt(rs); 143444f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(SW, at, rd, 0); // Equiv to sw(rd, MemOperand(at, 0)); 143544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 143644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 143744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 143844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 143944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::swl(Register rd, const MemOperand& rs) { 144044f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_); 144144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 144244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 144344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 144444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::swr(Register rd, const MemOperand& rs) { 144544f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_); 14463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 14473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 14483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 14493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::lui(Register rd, int32_t j) { 14503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(is_uint16(j)); 14513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrImmediate(LUI, zero_reg, rd, j); 14523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 14533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 14543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 14553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//-------------Misc-instructions-------------- 14563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 14573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Break / Trap instructions. 14583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Assembler::break_(uint32_t code, bool break_as_stop) { 14593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT((code & ~0xfffff) == 0); 14603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // We need to invalidate breaks that could be stops as well because the 14613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // simulator expects a char pointer after the stop instruction. 14623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // See constants-mips.h for explanation. 14633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT((break_as_stop && 14643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch code <= kMaxStopCode && 14653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch code > kMaxWatchpointCode) || 14663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch (!break_as_stop && 14673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch (code > kMaxStopCode || 14683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch code <= kMaxWatchpointCode))); 14693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr break_instr = SPECIAL | BREAK | (code << 6); 14703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu emit(break_instr); 14713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 14723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 14733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 14743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Assembler::stop(const char* msg, uint32_t code) { 14753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(code > kMaxWatchpointCode); 14763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(code <= kMaxStopCode); 14773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#if defined(V8_HOST_ARCH_MIPS) 14783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break_(0x54321); 14793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#else // V8_HOST_ARCH_MIPS 14803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch BlockTrampolinePoolFor(2); 14813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // The Simulator will handle the stop instruction and get the message address. 14823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // On MIPS stop() is just a special kind of break_(). 14833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break_(code, true); 14843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch emit(reinterpret_cast<Instr>(msg)); 14853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif 14863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 14873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 14883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 14893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::tge(Register rs, Register rt, uint16_t code) { 14903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(is_uint10(code)); 14913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr = SPECIAL | TGE | rs.code() << kRsShift 14923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu | rt.code() << kRtShift | code << 6; 14933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu emit(instr); 14943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 14953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 14963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 14973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::tgeu(Register rs, Register rt, uint16_t code) { 14983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(is_uint10(code)); 14993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr = SPECIAL | TGEU | rs.code() << kRsShift 15003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu | rt.code() << kRtShift | code << 6; 15013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu emit(instr); 15023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 15033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::tlt(Register rs, Register rt, uint16_t code) { 15063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(is_uint10(code)); 15073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr = 15083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SPECIAL | TLT | rs.code() << kRsShift | rt.code() << kRtShift | code << 6; 15093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu emit(instr); 15103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 15113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::tltu(Register rs, Register rt, uint16_t code) { 15143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(is_uint10(code)); 151544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Instr instr = 151644f0eee88ff00398ff7f715fab053374d808c90dSteve Block SPECIAL | TLTU | rs.code() << kRsShift 15173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu | rt.code() << kRtShift | code << 6; 15183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu emit(instr); 15193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 15203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::teq(Register rs, Register rt, uint16_t code) { 15233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(is_uint10(code)); 15243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr = 15253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SPECIAL | TEQ | rs.code() << kRsShift | rt.code() << kRtShift | code << 6; 15263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu emit(instr); 15273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 15283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::tne(Register rs, Register rt, uint16_t code) { 15313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(is_uint10(code)); 15323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr = 15333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SPECIAL | TNE | rs.code() << kRsShift | rt.code() << kRtShift | code << 6; 15343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu emit(instr); 15353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 15363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Move from HI/LO register. 15393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::mfhi(Register rd) { 15413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFHI); 15423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 15433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::mflo(Register rd) { 15463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFLO); 15473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 15483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Set on less than instructions. 15513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::slt(Register rd, Register rs, Register rt) { 15523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLT); 15533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 15543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::sltu(Register rd, Register rs, Register rt) { 15573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLTU); 15583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 15593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::slti(Register rt, Register rs, int32_t j) { 15623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrImmediate(SLTI, rs, rt, j); 15633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 15643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::sltiu(Register rt, Register rs, int32_t j) { 15673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrImmediate(SLTIU, rs, rt, j); 15683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 15693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 157144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Conditional move. 157244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::movz(Register rd, Register rs, Register rt) { 157344f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVZ); 157444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 157544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 157644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 157744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::movn(Register rd, Register rs, Register rt) { 157844f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVN); 157944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 158044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 158144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 158244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::movt(Register rd, Register rs, uint16_t cc) { 158344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register rt; 1584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch rt.code_ = (cc & 0x0007) << 2 | 1; 158544f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI); 158644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 158744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 158844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 158944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::movf(Register rd, Register rs, uint16_t cc) { 159044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register rt; 1591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch rt.code_ = (cc & 0x0007) << 2 | 0; 159244f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI); 159344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 159444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 159544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 159644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Bit twiddling. 159744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::clz(Register rd, Register rs) { 159844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Clz instr requires same GPR number in 'rd' and 'rt' fields. 159944f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(SPECIAL2, rs, rd, rd, 0, CLZ); 160044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 160144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 160244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 160344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::ins_(Register rt, Register rs, uint16_t pos, uint16_t size) { 160444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Should be called via MacroAssembler::Ins. 160544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Ins instr has 'rt' field as dest, and two uint5: msb, lsb. 16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(kArchVariant == kMips32r2); 160744f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, INS); 160844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 160944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 161044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 161144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::ext_(Register rt, Register rs, uint16_t pos, uint16_t size) { 161244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Should be called via MacroAssembler::Ext. 161344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Ext instr has 'rt' field as dest, and two uint5: msb, lsb. 16143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(kArchVariant == kMips32r2); 161544f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, EXT); 161644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 161744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 161844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 16193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//--------Coprocessor-instructions---------------- 16203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 16213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Load, store, move. 16223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::lwc1(FPURegister fd, const MemOperand& src) { 16233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrImmediate(LWC1, src.rm(), fd, src.offset_); 16243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 16253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 16263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 16273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::ldc1(FPURegister fd, const MemOperand& src) { 162844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit 162944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // load to two 32-bit loads. 163044f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(LWC1, src.rm(), fd, src.offset_); 163144f0eee88ff00398ff7f715fab053374d808c90dSteve Block FPURegister nextfpreg; 163244f0eee88ff00398ff7f715fab053374d808c90dSteve Block nextfpreg.setcode(fd.code() + 1); 163344f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(LWC1, src.rm(), nextfpreg, src.offset_ + 4); 16343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 16353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 16363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 16373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::swc1(FPURegister fd, const MemOperand& src) { 16383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrImmediate(SWC1, src.rm(), fd, src.offset_); 16393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 16403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 16413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 16423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::sdc1(FPURegister fd, const MemOperand& src) { 164344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit 164444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // store to two 32-bit stores. 164544f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(SWC1, src.rm(), fd, src.offset_); 164644f0eee88ff00398ff7f715fab053374d808c90dSteve Block FPURegister nextfpreg; 164744f0eee88ff00398ff7f715fab053374d808c90dSteve Block nextfpreg.setcode(fd.code() + 1); 164844f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrImmediate(SWC1, src.rm(), nextfpreg, src.offset_ + 4); 16493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 16503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 16513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 165244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::mtc1(Register rt, FPURegister fs) { 16533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(COP1, MTC1, rt, fs, f0); 16543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 16553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 16563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 165744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::mfc1(Register rt, FPURegister fs) { 165844f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, MFC1, rt, fs, f0); 16593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 16603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 16613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 166244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::ctc1(Register rt, FPUControlRegister fs) { 166344f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, CTC1, rt, fs); 166444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 166544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 166644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 166744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::cfc1(Register rt, FPUControlRegister fs) { 166844f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, CFC1, rt, fs); 166944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 167044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1671589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid Assembler::DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) { 1672589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint64_t i; 1673589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch memcpy(&i, &d, 8); 1674589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1675589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch *lo = i & 0xffffffff; 1676589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch *hi = i >> 32; 1677589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch} 167844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 167944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Arithmetic. 168044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 168144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::add_d(FPURegister fd, FPURegister fs, FPURegister ft) { 168244f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, D, ft, fs, fd, ADD_D); 168344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 168444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 168544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 168644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::sub_d(FPURegister fd, FPURegister fs, FPURegister ft) { 168744f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, D, ft, fs, fd, SUB_D); 168844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 168944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 169044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 169144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) { 169244f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, D, ft, fs, fd, MUL_D); 169344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 169444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 169544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 169644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::div_d(FPURegister fd, FPURegister fs, FPURegister ft) { 169744f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, D, ft, fs, fd, DIV_D); 169844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 169944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 170044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 170144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::abs_d(FPURegister fd, FPURegister fs) { 170244f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, D, f0, fs, fd, ABS_D); 17033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 17043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 17053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 170644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::mov_d(FPURegister fd, FPURegister fs) { 170744f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, D, f0, fs, fd, MOV_D); 170844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 170944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 171044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 171144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::neg_d(FPURegister fd, FPURegister fs) { 171244f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, D, f0, fs, fd, NEG_D); 171344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 171444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 171544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 171644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::sqrt_d(FPURegister fd, FPURegister fs) { 171744f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, D, f0, fs, fd, SQRT_D); 17183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 17193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 17203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 17213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Conversions. 17223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 17233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::cvt_w_s(FPURegister fd, FPURegister fs) { 17243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(COP1, S, f0, fs, fd, CVT_W_S); 17253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 17263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 17273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 17283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::cvt_w_d(FPURegister fd, FPURegister fs) { 17293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(COP1, D, f0, fs, fd, CVT_W_D); 17303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 17313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 17323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 173344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::trunc_w_s(FPURegister fd, FPURegister fs) { 173444f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_W_S); 173544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 173644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 173744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 173844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::trunc_w_d(FPURegister fd, FPURegister fs) { 173944f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_W_D); 174044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 174144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 174244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 174344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::round_w_s(FPURegister fd, FPURegister fs) { 174444f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, S, f0, fs, fd, ROUND_W_S); 174544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 174644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 174744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 174844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::round_w_d(FPURegister fd, FPURegister fs) { 174944f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, D, f0, fs, fd, ROUND_W_D); 175044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 175144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 175244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 175344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::floor_w_s(FPURegister fd, FPURegister fs) { 175444f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_W_S); 175544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 175644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 175744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 175844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::floor_w_d(FPURegister fd, FPURegister fs) { 175944f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_W_D); 176044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 176144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 176244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 176344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::ceil_w_s(FPURegister fd, FPURegister fs) { 176444f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, S, f0, fs, fd, CEIL_W_S); 176544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 176644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 176744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 176844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::ceil_w_d(FPURegister fd, FPURegister fs) { 176944f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, D, f0, fs, fd, CEIL_W_D); 177044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 177144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 177244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 17733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::cvt_l_s(FPURegister fd, FPURegister fs) { 17743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(kArchVariant == kMips32r2); 17753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S); 17763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 17773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 17783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 17793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::cvt_l_d(FPURegister fd, FPURegister fs) { 17803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(kArchVariant == kMips32r2); 17813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(COP1, D, f0, fs, fd, CVT_L_D); 17823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 17833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 17843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 178544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::trunc_l_s(FPURegister fd, FPURegister fs) { 17863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(kArchVariant == kMips32r2); 178744f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_L_S); 178844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 178944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 179044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 179144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::trunc_l_d(FPURegister fd, FPURegister fs) { 17923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(kArchVariant == kMips32r2); 179344f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_L_D); 179444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 179544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 179644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 179744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::round_l_s(FPURegister fd, FPURegister fs) { 179844f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, S, f0, fs, fd, ROUND_L_S); 179944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 180044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 180144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 180244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::round_l_d(FPURegister fd, FPURegister fs) { 180344f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, D, f0, fs, fd, ROUND_L_D); 180444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 180544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 180644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 180744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::floor_l_s(FPURegister fd, FPURegister fs) { 180844f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_L_S); 180944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 181044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 181144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 181244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::floor_l_d(FPURegister fd, FPURegister fs) { 181344f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_L_D); 181444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 181544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 181644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 181744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::ceil_l_s(FPURegister fd, FPURegister fs) { 181844f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, S, f0, fs, fd, CEIL_L_S); 181944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 182044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 182144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 182244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::ceil_l_d(FPURegister fd, FPURegister fs) { 182344f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenInstrRegister(COP1, D, f0, fs, fd, CEIL_L_D); 182444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 182544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 182644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 18273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::cvt_s_w(FPURegister fd, FPURegister fs) { 18283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W); 18293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 18303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::cvt_s_l(FPURegister fd, FPURegister fs) { 18333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(kArchVariant == kMips32r2); 18343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L); 18353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 18363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::cvt_s_d(FPURegister fd, FPURegister fs) { 18393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(COP1, D, f0, fs, fd, CVT_S_D); 18403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 18413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::cvt_d_w(FPURegister fd, FPURegister fs) { 18443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(COP1, W, f0, fs, fd, CVT_D_W); 18453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 18463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::cvt_d_l(FPURegister fd, FPURegister fs) { 18493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(kArchVariant == kMips32r2); 18503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L); 18513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 18523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::cvt_d_s(FPURegister fd, FPURegister fs) { 18553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S); 18563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 18573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Conditions. 18603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::c(FPUCondition cond, SecondaryField fmt, 186144f0eee88ff00398ff7f715fab053374d808c90dSteve Block FPURegister fs, FPURegister ft, uint16_t cc) { 1862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(CpuFeatures::IsEnabled(FPU)); 18633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(is_uint3(cc)); 18643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT((fmt & ~(31 << kRsShift)) == 0); 18653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift 18663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu | cc << 8 | 3 << 4 | cond; 18673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu emit(instr); 18683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 18693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 187144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::fcmp(FPURegister src1, const double src2, 187244f0eee88ff00398ff7f715fab053374d808c90dSteve Block FPUCondition cond) { 1873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(CpuFeatures::IsEnabled(FPU)); 187444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(src2 == 0.0); 187544f0eee88ff00398ff7f715fab053374d808c90dSteve Block mtc1(zero_reg, f14); 187644f0eee88ff00398ff7f715fab053374d808c90dSteve Block cvt_d_w(f14, f14); 187744f0eee88ff00398ff7f715fab053374d808c90dSteve Block c(cond, D, src1, f14, 0); 187844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 187944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 188044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 18813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bc1f(int16_t offset, uint16_t cc) { 1882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(CpuFeatures::IsEnabled(FPU)); 18833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(is_uint3(cc)); 18843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask); 18853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu emit(instr); 18863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 18873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bc1t(int16_t offset, uint16_t cc) { 1890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(CpuFeatures::IsEnabled(FPU)); 18913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(is_uint3(cc)); 18923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask); 18933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu emit(instr); 18943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 18953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Debugging. 18983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::RecordJSReturn() { 189944f0eee88ff00398ff7f715fab053374d808c90dSteve Block positions_recorder()->WriteRecordedPositions(); 19003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu CheckBuffer(); 19013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu RecordRelocInfo(RelocInfo::JS_RETURN); 19023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 19033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 19043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 190544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::RecordDebugBreakSlot() { 190644f0eee88ff00398ff7f715fab053374d808c90dSteve Block positions_recorder()->WriteRecordedPositions(); 190744f0eee88ff00398ff7f715fab053374d808c90dSteve Block CheckBuffer(); 190844f0eee88ff00398ff7f715fab053374d808c90dSteve Block RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT); 19093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 19103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 19113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 191244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::RecordComment(const char* msg) { 191344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (FLAG_code_comments) { 19143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu CheckBuffer(); 191544f0eee88ff00398ff7f715fab053374d808c90dSteve Block RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg)); 19163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 19173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 19183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 19193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 19203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochint Assembler::RelocateInternalReference(byte* pc, intptr_t pc_delta) { 19213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Instr instr = instr_at(pc); 19223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(IsJ(instr) || IsLui(instr)); 19233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (IsLui(instr)) { 19243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize); 19253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize); 19263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(IsOri(instr_ori)); 19273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; 19283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch imm |= (instr_ori & static_cast<int32_t>(kImm16Mask)); 19293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (imm == kEndOfJumpChain) { 19303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return 0; // Number of instructions patched. 19313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 19323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch imm += pc_delta; 19333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT((imm & 3) == 0); 19343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 19353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr_lui &= ~kImm16Mask; 19363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr_ori &= ~kImm16Mask; 19373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 19383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr_at_put(pc + 0 * Assembler::kInstrSize, 19393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr_lui | ((imm >> kLuiShift) & kImm16Mask)); 19403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr_at_put(pc + 1 * Assembler::kInstrSize, 19413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr_ori | (imm & kImm16Mask)); 19423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return 2; // Number of instructions patched. 19433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 19443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; 19453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if ((int32_t)imm28 == kEndOfJumpChain) { 19463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return 0; // Number of instructions patched. 19473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 19483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch imm28 += pc_delta; 19493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch imm28 &= kImm28Mask; 19503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT((imm28 & 3) == 0); 19513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 19523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr &= ~kImm26Mask; 19533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t imm26 = imm28 >> 2; 19543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(is_uint26(imm26)); 19553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 19563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr_at_put(pc, instr | (imm26 & kImm26Mask)); 19573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return 1; // Number of instructions patched. 19583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 19593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 19603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 19613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 19623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::GrowBuffer() { 19633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (!own_buffer_) FATAL("external code buffer is too small"); 19643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 19653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Compute new buffer size. 196644f0eee88ff00398ff7f715fab053374d808c90dSteve Block CodeDesc desc; // The new buffer. 19673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (buffer_size_ < 4*KB) { 19683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu desc.buffer_size = 4*KB; 19693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else if (buffer_size_ < 1*MB) { 19703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu desc.buffer_size = 2*buffer_size_; 19713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 19723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu desc.buffer_size = buffer_size_ + 1*MB; 19733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 197444f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_GT(desc.buffer_size, 0); // No overflow. 19753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 19763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up new buffer. 19773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu desc.buffer = NewArray<byte>(desc.buffer_size); 19783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 19793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu desc.instr_size = pc_offset(); 19803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 19813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 19823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Copy the data. 19833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int pc_delta = desc.buffer - buffer_; 19843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_); 19853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu memmove(desc.buffer, buffer_, desc.instr_size); 19863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu memmove(reloc_info_writer.pos() + rc_delta, 19873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu reloc_info_writer.pos(), desc.reloc_size); 19883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 19893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Switch buffers. 19903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu DeleteArray(buffer_); 19913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu buffer_ = desc.buffer; 19923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu buffer_size_ = desc.buffer_size; 19933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu pc_ += pc_delta; 19943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, 19953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu reloc_info_writer.last_pc() + pc_delta); 19963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 19973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Relocate runtime entries. 19983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (RelocIterator it(desc); !it.done(); it.next()) { 19993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RelocInfo::Mode rmode = it.rinfo()->rmode(); 20003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (rmode == RelocInfo::INTERNAL_REFERENCE) { 20013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch byte* p = reinterpret_cast<byte*>(it.rinfo()->pc()); 20023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RelocateInternalReference(p, pc_delta); 20033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 20043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 20053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 20063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(!overflow()); 20073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 20083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 20093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 201044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::db(uint8_t data) { 201144f0eee88ff00398ff7f715fab053374d808c90dSteve Block CheckBuffer(); 201244f0eee88ff00398ff7f715fab053374d808c90dSteve Block *reinterpret_cast<uint8_t*>(pc_) = data; 201344f0eee88ff00398ff7f715fab053374d808c90dSteve Block pc_ += sizeof(uint8_t); 201444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 201544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 201644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 201744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::dd(uint32_t data) { 201844f0eee88ff00398ff7f715fab053374d808c90dSteve Block CheckBuffer(); 201944f0eee88ff00398ff7f715fab053374d808c90dSteve Block *reinterpret_cast<uint32_t*>(pc_) = data; 202044f0eee88ff00398ff7f715fab053374d808c90dSteve Block pc_ += sizeof(uint32_t); 202144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 202244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 202344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 20243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { 20253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We do not try to reuse pool constants. 20263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RelocInfo rinfo(pc_, rmode, data, NULL); 202744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::DEBUG_BREAK_SLOT) { 20283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Adjust code for new modes. 202944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(RelocInfo::IsDebugBreakSlot(rmode) 203044f0eee88ff00398ff7f715fab053374d808c90dSteve Block || RelocInfo::IsJSReturn(rmode) 20313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu || RelocInfo::IsComment(rmode) 20323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu || RelocInfo::IsPosition(rmode)); 20333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // These modes do not need an entry in the constant pool. 20343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 20353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (rinfo.rmode() != RelocInfo::NONE) { 20363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Don't record external references unless the heap will be serialized. 2037589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (rmode == RelocInfo::EXTERNAL_REFERENCE) { 2038589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#ifdef DEBUG 2039589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (!Serializer::enabled()) { 2040589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Serializer::TooLateToEnableNow(); 2041589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 2042589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#endif 2043589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (!Serializer::enabled() && !emit_debug_code()) { 2044589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return; 2045589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 20463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 204744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(buffer_space() >= kMaxRelocSize); // Too late to grow buffer here. 2048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (rmode == RelocInfo::CODE_TARGET_WITH_ID) { 20493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RelocInfo reloc_info_with_ast_id(pc_, rmode, RecordedAstId(), NULL); 20503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ClearRecordedAstId(); 2051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reloc_info_writer.Write(&reloc_info_with_ast_id); 2052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reloc_info_writer.Write(&rinfo); 2054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 20553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 20563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 20573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 20583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 205944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::BlockTrampolinePoolFor(int instructions) { 206044f0eee88ff00398ff7f715fab053374d808c90dSteve Block BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize); 206144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 206244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 206344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 20643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Assembler::CheckTrampolinePool() { 206544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Some small sequences of instructions must not be broken up by the 206644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // insertion of a trampoline pool; such sequences are protected by setting 206744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_, 206844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // which are both checked here. Also, recursive calls to CheckTrampolinePool 206944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // are blocked by trampoline_pool_blocked_nesting_. 207044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if ((trampoline_pool_blocked_nesting_ > 0) || 207144f0eee88ff00398ff7f715fab053374d808c90dSteve Block (pc_offset() < no_trampoline_pool_before_)) { 207244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Emission is currently blocked; make sure we try again as soon as 207344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // possible. 207444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (trampoline_pool_blocked_nesting_ > 0) { 207544f0eee88ff00398ff7f715fab053374d808c90dSteve Block next_buffer_check_ = pc_offset() + kInstrSize; 207644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 207744f0eee88ff00398ff7f715fab053374d808c90dSteve Block next_buffer_check_ = no_trampoline_pool_before_; 207844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 207944f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 208044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 208144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 20823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(!trampoline_emitted_); 20833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(unbound_labels_count_ >= 0); 20843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (unbound_labels_count_ > 0) { 20853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // First we emit jump (2 instructions), then we emit trampoline pool. 20863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch { BlockTrampolinePoolScope block_trampoline_pool(this); 20873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label after_pool; 208844f0eee88ff00398ff7f715fab053374d808c90dSteve Block b(&after_pool); 208944f0eee88ff00398ff7f715fab053374d808c90dSteve Block nop(); 20903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 20913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int pool_start = pc_offset(); 20923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int i = 0; i < unbound_labels_count_; i++) { 20933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t imm32; 20943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch imm32 = jump_address(&after_pool); 20953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch { BlockGrowBufferScope block_buf_growth(this); 20963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Buffer growth (and relocation) must be blocked for internal 20973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // references until associated instructions are emitted and available 20983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // to be patched. 20993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); 21003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch lui(at, (imm32 & kHiMask) >> kLuiShift); 21013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ori(at, at, (imm32 & kImm16Mask)); 21023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 21033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch jr(at); 21043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch nop(); 21053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 21063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bind(&after_pool); 21073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch trampoline_ = Trampoline(pool_start, unbound_labels_count_); 21083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 21093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch trampoline_emitted_ = true; 21103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // As we are only going to emit trampoline once, we need to prevent any 21113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // further emission. 21123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch next_buffer_check_ = kMaxInt; 211344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 21143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 21153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Number of branches to unbound label at this point is zero, so we can 21163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // move next buffer check to maximum. 21173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch next_buffer_check_ = pc_offset() + 21183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch kMaxBranchOffset - kTrampolineSlotsSize * 16; 211944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 212044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 212144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 212244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 212344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 21243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuAddress Assembler::target_address_at(Address pc) { 21253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr1 = instr_at(pc); 21263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr2 = instr_at(pc + kInstrSize); 2127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Interpret 2 instructions generated by li: lui/ori 2128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if ((GetOpcodeField(instr1) == LUI) && (GetOpcodeField(instr2) == ORI)) { 2129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Assemble the 32 bit value. 21303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return reinterpret_cast<Address>( 2131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (GetImmediate16(instr1) << 16) | GetImmediate16(instr2)); 21323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 21333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We should never get here, force a bad address if we do. 21353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNREACHABLE(); 21363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return (Address)0x0; 21373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 21383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 21393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2140db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// MIPS and ia32 use opposite encoding for qNaN and sNaN, such that ia32 2141db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// qNaN is a MIPS sNaN, and ia32 sNaN is MIPS qNaN. If running from a heap 2142db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// snapshot generated on ia32, the resulting MIPS sNaN must be quieted. 2143db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// OS::nan_value() returns a qNaN. 2144db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdochvoid Assembler::QuietNaN(HeapObject* object) { 2145db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch HeapNumber::cast(object)->set_value(OS::nan_value()); 2146db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch} 2147db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch 2148db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch 2149589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// On Mips, a target address is stored in a lui/ori instruction pair, each 2150589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// of which load 16 bits of the 32-bit address to a register. 2151589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// Patching the address must replace both instr, and flush the i-cache. 2152589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// 2153589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// There is an optimization below, which emits a nop when the address 2154589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// fits in just 16 bits. This is unlikely to help, and should be benchmarked, 2155589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// and possibly removed. 21563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::set_target_address_at(Address pc, Address target) { 21573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr2 = instr_at(pc + kInstrSize); 2158589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint32_t rt_code = GetRtField(instr2); 2159589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint32_t* p = reinterpret_cast<uint32_t*>(pc); 2160589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint32_t itarget = reinterpret_cast<uint32_t>(target); 2161589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 21623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#ifdef DEBUG 2163589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Check we have the result from a li macro-instruction, using instr pair. 21643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr instr1 = instr_at(pc); 2165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK((GetOpcodeField(instr1) == LUI && GetOpcodeField(instr2) == ORI)); 21663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#endif 21673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2168589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Must use 2 instructions to insure patchable code => just use lui and ori. 2169589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // lui rt, upper-16. 2170589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // ori rt rt, lower-16. 2171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift); 2172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask); 21733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2174589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // The following code is an optimization for the common case of Call() 2175589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // or Jump() which is load to register, and jump through register: 2176589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // li(t9, address); jalr(t9) (or jr(t9)). 2177589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // If the destination address is in the same 256 MB page as the call, it 2178589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // is faster to do a direct jal, or j, rather than jump thru register, since 2179589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // that lets the cpu pipeline prefetch the target address. However each 2180589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // time the address above is patched, we have to patch the direct jal/j 2181589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // instruction, as well as possibly revert to jalr/jr if we now cross a 2182589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // 256 MB page. Note that with the jal/j instructions, we do not need to 2183589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // load the register, but that code is left, since it makes it easy to 2184589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // revert this process. A further optimization could try replacing the 2185589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // li sequence with nops. 2186589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // This optimization can only be applied if the rt-code from instr2 is the 2187589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // register used for the jalr/jr. Finally, we have to skip 'jr ra', which is 2188589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // mips return. Occasionally this lands after an li(). 2189589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 2190589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Instr instr3 = instr_at(pc + 2 * kInstrSize); 2191589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint32_t ipc = reinterpret_cast<uint32_t>(pc + 3 * kInstrSize); 2192589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch bool in_range = 2193589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ((uint32_t)(ipc ^ itarget) >> (kImm26Bits + kImmFieldShift)) == 0; 2194589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint32_t target_field = (uint32_t)(itarget & kJumpAddrMask) >> kImmFieldShift; 2195589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch bool patched_jump = false; 2196589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 2197589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#ifndef ALLOW_JAL_IN_BOUNDARY_REGION 2198589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // This is a workaround to the 24k core E156 bug (affect some 34k cores also). 2199589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Since the excluded space is only 64KB out of 256MB (0.02 %), we will just 2200589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // apply this workaround for all cores so we don't have to identify the core. 2201589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (in_range) { 2202589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // The 24k core E156 bug has some very specific requirements, we only check 2203589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // the most simple one: if the address of the delay slot instruction is in 2204589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // the first or last 32 KB of the 256 MB segment. 2205589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint32_t segment_mask = ((256 * MB) - 1) ^ ((32 * KB) - 1); 2206589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint32_t ipc_segment_addr = ipc & segment_mask; 2207589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (ipc_segment_addr == 0 || ipc_segment_addr == segment_mask) 2208589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch in_range = false; 2209589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 2210589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#endif 2211589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 2212589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (IsJalr(instr3)) { 2213589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Try to convert JALR to JAL. 2214589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (in_range && GetRt(instr2) == GetRs(instr3)) { 2215589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch *(p+2) = JAL | target_field; 2216589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch patched_jump = true; 2217589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 2218589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (IsJr(instr3)) { 2219589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Try to convert JR to J, skip returns (jr ra). 2220589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch bool is_ret = static_cast<int>(GetRs(instr3)) == ra.code(); 2221589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (in_range && !is_ret && GetRt(instr2) == GetRs(instr3)) { 2222589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch *(p+2) = J | target_field; 2223589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch patched_jump = true; 2224589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 2225589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (IsJal(instr3)) { 2226589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (in_range) { 2227589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // We are patching an already converted JAL. 2228589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch *(p+2) = JAL | target_field; 2229589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 2230589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Patch JAL, but out of range, revert to JALR. 2231589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // JALR rs reg is the rt reg specified in the ORI instruction. 2232589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint32_t rs_field = GetRt(instr2) << kRsShift; 2233589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint32_t rd_field = ra.code() << kRdShift; // Return-address (ra) reg. 2234589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch *(p+2) = SPECIAL | rs_field | rd_field | JALR; 2235589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 2236589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch patched_jump = true; 2237589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (IsJ(instr3)) { 2238589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (in_range) { 2239589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // We are patching an already converted J (jump). 2240589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch *(p+2) = J | target_field; 2241589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 2242589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Trying patch J, but out of range, just go back to JR. 2243589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // JR 'rs' reg is the 'rt' reg specified in the ORI instruction (instr2). 2244589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint32_t rs_field = GetRt(instr2) << kRsShift; 2245589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch *(p+2) = SPECIAL | rs_field | JR; 2246589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 2247589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch patched_jump = true; 2248589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 2249589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 2250589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch CPU::FlushICache(pc, (patched_jump ? 3 : 2) * sizeof(int32_t)); 22513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 22523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2253589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid Assembler::JumpLabelToJumpRegister(Address pc) { 2254589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Address pc points to lui/ori instructions. 2255589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Jump to label may follow at pc + 2 * kInstrSize. 2256589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint32_t* p = reinterpret_cast<uint32_t*>(pc); 2257589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#ifdef DEBUG 2258589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Instr instr1 = instr_at(pc); 2259589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#endif 2260589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Instr instr2 = instr_at(pc + 1 * kInstrSize); 2261589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Instr instr3 = instr_at(pc + 2 * kInstrSize); 2262589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch bool patched = false; 2263589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 2264589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (IsJal(instr3)) { 2265589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(GetOpcodeField(instr1) == LUI); 2266589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(GetOpcodeField(instr2) == ORI); 2267589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 2268589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint32_t rs_field = GetRt(instr2) << kRsShift; 2269589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint32_t rd_field = ra.code() << kRdShift; // Return-address (ra) reg. 2270589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch *(p+2) = SPECIAL | rs_field | rd_field | JALR; 2271589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch patched = true; 2272589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (IsJ(instr3)) { 2273589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(GetOpcodeField(instr1) == LUI); 2274589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(GetOpcodeField(instr2) == ORI); 2275589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 2276589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch uint32_t rs_field = GetRt(instr2) << kRsShift; 2277589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch *(p+2) = SPECIAL | rs_field | JR; 2278589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch patched = true; 2279589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 2280589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 2281589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (patched) { 2282589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch CPU::FlushICache(pc+2, sizeof(Address)); 2283589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 2284589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch} 22853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 22863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} } // namespace v8::internal 22873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2288f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_MIPS 2289