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