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
35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/mips/assembler-mips.h"
36f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_MIPS
38f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h"
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/cpu.h"
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/mips/assembler-mips-inl.h"
423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace v8 {
443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace internal {
453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
46589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// Get the CPU features enabled by the build. For cross compilation the
47589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// preprocessor symbols CAN_USE_FPU_INSTRUCTIONS
48589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// can be defined to enable FPU instructions when building the
49589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// snapshot.
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic unsigned CpuFeaturesImpliedByCompiler() {
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned answer = 0;
52589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#ifdef CAN_USE_FPU_INSTRUCTIONS
53589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  answer |= 1u << FPU;
54589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#endif  // def CAN_USE_FPU_INSTRUCTIONS
55589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
56589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // If the compiler is allowed to use FPU then we can use FPU too in our code
57589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // generation even when generating snapshots.  This won't work for cross
58589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // compilation.
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(__mips__) && defined(__mips_hard_float) && __mips_hard_float != 0
60589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  answer |= 1u << FPU;
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
62589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
63589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  return answer;
64589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
65589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
66589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CpuFeatures::ProbeImpl(bool cross_compile) {
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  supported_ |= CpuFeaturesImpliedByCompiler();
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Only use statically determined features for cross compile (snapshot).
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cross_compile) return;
72589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
7344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If the compiler is allowed to use fpu then we can use fpu too in our
7444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // code generation.
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef __mips__
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For the simulator build, use FPU.
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  supported_ |= 1u << FPU;
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(_MIPS_ARCH_MIPS32R6)
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // FP64 mode is implied on r6.
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  supported_ |= 1u << FP64FPU;
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(FPU_MODE_FP64)
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  supported_ |= 1u << FP64FPU;
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
8544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#else
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Probe for additional features at runtime.
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::CPU cpu;
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cpu.has_fpu()) supported_ |= 1u << FPU;
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(FPU_MODE_FPXX)
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cpu.is_fp64_mode()) supported_ |= 1u << FP64FPU;
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#elif defined(FPU_MODE_FP64)
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  supported_ |= 1u << FP64FPU;
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(_MIPS_ARCH_MIPS32RX)
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cpu.architecture() == 6) {
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    supported_ |= 1u << MIPSr6;
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (cpu.architecture() == 2) {
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    supported_ |= 1u << MIPSr1;
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    supported_ |= 1u << MIPSr2;
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    supported_ |= 1u << MIPSr1;
10244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
10344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
10544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
1063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CpuFeatures::PrintTarget() { }
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CpuFeatures::PrintFeatures() { }
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuint ToNumber(Register reg) {
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(reg.is_valid());
1143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  const int kNumbers[] = {
1153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    0,    // zero_reg
1163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    1,    // at
1173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    2,    // v0
1183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    3,    // v1
1193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    4,    // a0
1203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    5,    // a1
1213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    6,    // a2
1223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    7,    // a3
1233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    8,    // t0
1243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    9,    // t1
1253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    10,   // t2
1263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    11,   // t3
1273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    12,   // t4
1283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    13,   // t5
1293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    14,   // t6
1303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    15,   // t7
1313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    16,   // s0
1323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    17,   // s1
1333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    18,   // s2
1343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    19,   // s3
1353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    20,   // s4
1363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    21,   // s5
1373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    22,   // s6
1383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    23,   // s7
1393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    24,   // t8
1403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    25,   // t9
1413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    26,   // k0
1423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    27,   // k1
1433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    28,   // gp
1443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    29,   // sp
145db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch    30,   // fp
1463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    31,   // ra
1473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  };
1483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  return kNumbers[reg.code()];
1493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
1503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuRegister ToRegister(int num) {
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(num >= 0 && num < kNumRegisters);
1543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  const Register kRegisters[] = {
1553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    zero_reg,
1563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    at,
1573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    v0, v1,
1583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    a0, a1, a2, a3,
1593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    t0, t1, t2, t3, t4, t5, t6, t7,
1603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    s0, s1, s2, s3, s4, s5, s6, s7,
1613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    t8, t9,
1623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    k0, k1,
1633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    gp,
1643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    sp,
165db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch    fp,
1663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    ra
1673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  };
1683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  return kRegisters[num];
1693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
1703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// -----------------------------------------------------------------------------
1733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Implementation of RelocInfo.
1743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
175589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochconst int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask |
176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  1 << RelocInfo::INTERNAL_REFERENCE |
177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  1 << RelocInfo::INTERNAL_REFERENCE_ENCODED;
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
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool RelocInfo::IsInConstantPool() {
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return false;
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
192bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochAddress RelocInfo::wasm_memory_reference() {
193bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(IsWasmMemoryReference(rmode_));
194bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  return Assembler::target_address_at(pc_, host_);
195bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
196bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
19713e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochAddress RelocInfo::wasm_global_reference() {
19813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(IsWasmGlobalReference(rmode_));
19913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return Assembler::target_address_at(pc_, host_);
20013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
20113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
202bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochuint32_t RelocInfo::wasm_memory_size_reference() {
203bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(IsWasmMemorySizeReference(rmode_));
204bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  return reinterpret_cast<uint32_t>(Assembler::target_address_at(pc_, host_));
205bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
206bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
20762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochuint32_t RelocInfo::wasm_function_table_size_reference() {
20862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsWasmFunctionTableSizeReference(rmode_));
20962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return reinterpret_cast<uint32_t>(Assembler::target_address_at(pc_, host_));
21062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
21162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
21213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid RelocInfo::unchecked_update_wasm_memory_reference(
21313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Address address, ICacheFlushMode flush_mode) {
21413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Assembler::set_target_address_at(isolate_, pc_, host_, address, flush_mode);
21513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
21613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
21762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid RelocInfo::unchecked_update_wasm_size(uint32_t size,
21862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                           ICacheFlushMode flush_mode) {
21913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Assembler::set_target_address_at(isolate_, pc_, host_,
22013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                   reinterpret_cast<Address>(size), flush_mode);
221bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// -----------------------------------------------------------------------------
2243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Implementation of Operand and MemOperand.
2253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// See assembler-mips-inl.h for inlined constructors.
2263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuOperand::Operand(Handle<Object> handle) {
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference using_raw_address;
2293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  rm_ = no_reg;
2303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Verify all Objects referred by code are NOT in new space.
2313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Object* obj = *handle;
2323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (obj->IsHeapObject()) {
2333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    imm32_ = reinterpret_cast<intptr_t>(handle.location());
2343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    rmode_ = RelocInfo::EMBEDDED_OBJECT;
2353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
2363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // No relocation needed.
2373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    imm32_ = reinterpret_cast<intptr_t>(obj);
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    rmode_ = RelocInfo::NONE32;
2393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
2403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
2413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
24244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
24344f0eee88ff00398ff7f715fab053374d808c90dSteve BlockMemOperand::MemOperand(Register rm, int32_t offset) : Operand(rm) {
2443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  offset_ = offset;
2453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
2463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMemOperand::MemOperand(Register rm, int32_t unit, int32_t multiplier,
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       OffsetAddend offset_addend) : Operand(rm) {
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  offset_ = unit * multiplier + offset_addend;
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// -----------------------------------------------------------------------------
25544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Specific instructions, constants, and masks.
25644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
25744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const int kNegOffset = 0x00008000;
25844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// addiu(sp, sp, 4) aka Pop() operation or part of Pop(r)
25944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// operations as post-increment of sp.
260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Instr kPopInstruction = ADDIU | (Register::kCode_sp << kRsShift) |
261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              (Register::kCode_sp << kRtShift) |
262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              (kPointerSize & kImm16Mask);  // NOLINT
26344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// addiu(sp, sp, -4) part of Push(r) operation as pre-decrement of sp.
264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Instr kPushInstruction = ADDIU | (Register::kCode_sp << kRsShift) |
265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               (Register::kCode_sp << kRtShift) |
266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               (-kPointerSize & kImm16Mask);  // NOLINT
26744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// sw(r, MemOperand(sp, 0))
268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Instr kPushRegPattern =
269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SW | (Register::kCode_sp << kRsShift) | (0 & kImm16Mask);  // NOLINT
27044f0eee88ff00398ff7f715fab053374d808c90dSteve Block//  lw(r, MemOperand(sp, 0))
271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Instr kPopRegPattern =
272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LW | (Register::kCode_sp << kRsShift) | (0 & kImm16Mask);  // NOLINT
27344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Instr kLwRegFpOffsetPattern =
275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LW | (Register::kCode_fp << kRsShift) | (0 & kImm16Mask);  // NOLINT
27644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Instr kSwRegFpOffsetPattern =
278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SW | (Register::kCode_fp << kRsShift) | (0 & kImm16Mask);  // NOLINT
27944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Instr kLwRegFpNegOffsetPattern = LW | (Register::kCode_fp << kRsShift) |
281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       (kNegOffset & kImm16Mask);  // NOLINT
28244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Instr kSwRegFpNegOffsetPattern = SW | (Register::kCode_fp << kRsShift) |
284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       (kNegOffset & kImm16Mask);  // NOLINT
28544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// A mask for the Rt register for push, pop, lw, sw instructions.
28644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst Instr kRtMask = kRtFieldMask;
28744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst Instr kLwSwInstrTypeMask = 0xffe00000;
28844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst Instr kLwSwInstrArgumentMask  = ~kLwSwInstrTypeMask;
28944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst Instr kLwSwOffsetMask = kImm16Mask;
29044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAssembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : AssemblerBase(isolate, buffer, buffer_size),
293f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      recorded_ast_id_(TypeFeedbackId::None()) {
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
29544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
29644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  last_trampoline_pool_end_ = 0;
29744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  no_trampoline_pool_before_ = 0;
29844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  trampoline_pool_blocked_nesting_ = 0;
2993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // We leave space (16 * kTrampolineSlotsSize)
3003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // for BlockTrampolinePoolScope buffer.
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  next_buffer_check_ = FLAG_force_long_branches
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? kMaxInt : kMaxBranchOffset - kTrampolineSlotsSize * 16;
303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  internal_trampoline_exception_ = false;
304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  last_bound_pos_ = 0;
305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  trampoline_emitted_ = FLAG_force_long_branches;
3073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  unbound_labels_count_ = 0;
3083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  block_buffer_growth_ = false;
3093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ClearRecordedAstId();
3113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
3123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::GetCode(CodeDesc* desc) {
315109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  EmitForbiddenSlotInstruction();
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(pc_ <= reloc_info_writer.pos());  // No overlap.
3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up code descriptor.
3183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  desc->buffer = buffer_;
3193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  desc->buffer_size = buffer_size_;
3203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  desc->instr_size = pc_offset();
3213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  desc->origin = this;
323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  desc->constant_pool_size = 0;
32413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  desc->unwinding_info_size = 0;
32513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  desc->unwinding_info = nullptr;
3263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
3273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
32944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::Align(int m) {
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m));
331109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  EmitForbiddenSlotInstruction();
33244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  while ((pc_offset() & (m - 1)) != 0) {
33344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    nop();
33444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
33544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
33644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
33744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
33844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::CodeTargetAlign() {
33944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // No advantage to aligning branch/call targets to more than
34044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // single instruction, that I am aware of.
34144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Align(4);
34244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
34344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
34444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochRegister Assembler::GetRtReg(Instr instr) {
34644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register rt;
347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  rt.reg_code = (instr & kRtFieldMask) >> kRtShift;
34844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return rt;
34944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
35044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
35144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochRegister Assembler::GetRsReg(Instr instr) {
353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register rs;
354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  rs.reg_code = (instr & kRsFieldMask) >> kRsShift;
355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return rs;
356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochRegister Assembler::GetRdReg(Instr instr) {
360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register rd;
361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  rd.reg_code = (instr & kRdFieldMask) >> kRdShift;
362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return rd;
363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetRt(Instr instr) {
367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return (instr & kRtFieldMask) >> kRtShift;
368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetRtField(Instr instr) {
372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return instr & kRtFieldMask;
373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetRs(Instr instr) {
377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return (instr & kRsFieldMask) >> kRsShift;
378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetRsField(Instr instr) {
382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return instr & kRsFieldMask;
383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetRd(Instr instr) {
387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return  (instr & kRdFieldMask) >> kRdShift;
388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetRdField(Instr instr) {
392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return  instr & kRdFieldMask;
393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetSa(Instr instr) {
397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return (instr & kSaFieldMask) >> kSaShift;
398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetSaField(Instr instr) {
402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return instr & kSaFieldMask;
403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetOpcodeField(Instr instr) {
407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return instr & kOpcodeMask;
408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochuint32_t Assembler::GetFunction(Instr instr) {
4123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return (instr & kFunctionFieldMask) >> kFunctionShift;
4133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
4143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochuint32_t Assembler::GetFunctionField(Instr instr) {
4173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return instr & kFunctionFieldMask;
4183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
4193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetImmediate16(Instr instr) {
422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return instr & kImm16Mask;
423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochuint32_t Assembler::GetLabelConst(Instr instr) {
427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return instr & ~kImm16Mask;
428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
43144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsPop(Instr instr) {
43244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return (instr & ~kRtMask) == kPopRegPattern;
43344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
43444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
43544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
43644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsPush(Instr instr) {
43744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return (instr & ~kRtMask) == kPushRegPattern;
43844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
43944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
44044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
44144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsSwRegFpOffset(Instr instr) {
44244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return ((instr & kLwSwInstrTypeMask) == kSwRegFpOffsetPattern);
44344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
44444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
44544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
44644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsLwRegFpOffset(Instr instr) {
44744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return ((instr & kLwSwInstrTypeMask) == kLwRegFpOffsetPattern);
44844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
44944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
45044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
45144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsSwRegFpNegOffset(Instr instr) {
45244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return ((instr & (kLwSwInstrTypeMask | kNegOffset)) ==
45344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          kSwRegFpNegOffsetPattern);
45444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
45544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
45644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
45744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsLwRegFpNegOffset(Instr instr) {
45844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return ((instr & (kLwSwInstrTypeMask | kNegOffset)) ==
45944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          kLwRegFpNegOffsetPattern);
46044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
46144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
46244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Labels refer to positions in the (to be) generated code.
4643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// There are bound, linked, and unused labels.
4653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//
4663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Bound labels refer to known positions in the already
4673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// generated code. pos() is the position the label refers to.
4683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//
4693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Linked labels refer to unknown positions in the code
4703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// to be generated; pos() is the position of the last
4713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// instruction using the label.
4723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
47344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// The link chain is terminated by a value in the instruction of -1,
47444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// which is an otherwise illegal value (branch -1 is inf loop).
47544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// The instruction 16-bit offset field addresses 32-bit words, but in
47644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// code is conv to an 18-bit value addressing bytes, hence the -4 value.
4773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuconst int kEndOfChain = -4;
4793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// Determines the end of the Jump chain (a subset of the label link chain).
4803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochconst int kEndOfJumpChain = 0;
4813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
48244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
48344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsBranch(Instr instr) {
484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  uint32_t opcode   = GetOpcodeField(instr);
485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  uint32_t rt_field = GetRtField(instr);
486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  uint32_t rs_field = GetRsField(instr);
4873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Checks if the instruction is a branch.
488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool isBranch =
489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      opcode == BEQ || opcode == BNE || opcode == BLEZ || opcode == BGTZ ||
490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      opcode == BEQL || opcode == BNEL || opcode == BLEZL || opcode == BGTZL ||
4913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ ||
4923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                            rt_field == BLTZAL || rt_field == BGEZAL)) ||
49344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      (opcode == COP1 && rs_field == BC1) ||  // Coprocessor branch.
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (opcode == COP1 && rs_field == BC1EQZ) ||
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (opcode == COP1 && rs_field == BC1NEZ);
496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!isBranch && IsMipsArchVariant(kMips32r6)) {
497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // All the 3 variants of POP10 (BOVC, BEQC, BEQZALC) and
498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // POP30 (BNVC, BNEC, BNEZALC) are branch ops.
499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    isBranch |= opcode == POP10 || opcode == POP30 || opcode == BC ||
500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                opcode == BALC ||
501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                (opcode == POP66 && rs_field != 0) ||  // BEQZC
502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                (opcode == POP76 && rs_field != 0);    // BNEZC
503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return isBranch;
505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool Assembler::IsBc(Instr instr) {
509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t opcode = GetOpcodeField(instr);
510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Checks if the instruction is a BC or BALC.
511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return opcode == BC || opcode == BALC;
512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool Assembler::IsBzc(Instr instr) {
516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t opcode = GetOpcodeField(instr);
517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Checks if the instruction is BEQZC or BNEZC.
518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return (opcode == POP66 && GetRsField(instr) != 0) ||
519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         (opcode == POP76 && GetRsField(instr) != 0);
520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsEmittedConstant(Instr instr) {
524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint32_t label_constant = GetLabelConst(instr);
525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return label_constant == 0;  // Emitted label const in reg-exp engine.
52644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
52744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
52844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochbool Assembler::IsBeq(Instr instr) {
530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetOpcodeField(instr) == BEQ;
531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochbool Assembler::IsBne(Instr instr) {
535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetOpcodeField(instr) == BNE;
536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
539014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool Assembler::IsBeqzc(Instr instr) {
540014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t opcode = GetOpcodeField(instr);
541014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return opcode == POP66 && GetRsField(instr) != 0;
542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
544014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool Assembler::IsBnezc(Instr instr) {
546014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t opcode = GetOpcodeField(instr);
547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return opcode == POP76 && GetRsField(instr) != 0;
548014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
550014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool Assembler::IsBeqc(Instr instr) {
552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t opcode = GetOpcodeField(instr);
553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t rs = GetRsField(instr);
554014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t rt = GetRtField(instr);
555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return opcode == POP10 && rs != 0 && rs < rt;  // && rt != 0
556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool Assembler::IsBnec(Instr instr) {
560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t opcode = GetOpcodeField(instr);
561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t rs = GetRsField(instr);
562014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t rt = GetRtField(instr);
563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return opcode == POP30 && rs != 0 && rs < rt;  // && rt != 0
564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochbool Assembler::IsJicOrJialc(Instr instr) {
5673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  uint32_t opcode = GetOpcodeField(instr);
5683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  uint32_t rs = GetRsField(instr);
5693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return (opcode == POP66 || opcode == POP76) && rs == 0;
5703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochbool Assembler::IsJump(Instr instr) {
5733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t opcode   = GetOpcodeField(instr);
5743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t rt_field = GetRtField(instr);
5753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t rd_field = GetRdField(instr);
5763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t function_field = GetFunctionField(instr);
5773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Checks if the instruction is a jump.
5783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return opcode == J || opcode == JAL ||
5793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      (opcode == SPECIAL && rt_field == 0 &&
5803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ((function_field == JALR) || (rd_field == 0 && (function_field == JR))));
5813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
5823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochbool Assembler::IsJ(Instr instr) {
5843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t opcode = GetOpcodeField(instr);
5853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Checks if the instruction is a jump.
5863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return opcode == J;
5873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
5883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
590589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochbool Assembler::IsJal(Instr instr) {
591589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  return GetOpcodeField(instr) == JAL;
592589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
593589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
595589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochbool Assembler::IsJr(Instr instr) {
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!IsMipsArchVariant(kMips32r6))  {
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JR;
598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return GetOpcodeField(instr) == SPECIAL &&
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        GetRdField(instr) == 0  && GetFunctionField(instr) == JALR;
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
602589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
603589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
605589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochbool Assembler::IsJalr(Instr instr) {
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return GetOpcodeField(instr) == SPECIAL &&
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         GetRdField(instr) != 0  && GetFunctionField(instr) == JALR;
608589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
609589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
610589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
6113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochbool Assembler::IsLui(Instr instr) {
6123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t opcode = GetOpcodeField(instr);
6133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Checks if the instruction is a load upper immediate.
6143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return opcode == LUI;
6153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
6163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochbool Assembler::IsOri(Instr instr) {
6193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t opcode = GetOpcodeField(instr);
6203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Checks if the instruction is a load upper immediate.
6213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return opcode == ORI;
6223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
6233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
62544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsNop(Instr instr, unsigned int type) {
62644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // See Assembler::nop(type).
627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(type < 32);
628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  uint32_t opcode = GetOpcodeField(instr);
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint32_t function = GetFunctionField(instr);
630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  uint32_t rt = GetRt(instr);
631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint32_t rd = GetRd(instr);
632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  uint32_t sa = GetSa(instr);
63344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Traditional mips nop == sll(zero_reg, zero_reg, 0)
635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // When marking non-zero type, use sll(zero_reg, at, type)
636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to avoid use of mips ssnop and ehb special encodings
637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // of the sll instruction.
63844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register nop_rt_reg = (type == 0) ? zero_reg : at;
640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool ret = (opcode == SPECIAL && function == SLL &&
641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              rd == static_cast<uint32_t>(ToNumber(zero_reg)) &&
642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              rt == static_cast<uint32_t>(ToNumber(nop_rt_reg)) &&
64344f0eee88ff00398ff7f715fab053374d808c90dSteve Block              sa == type);
64444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
64544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return ret;
64644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
64744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
64844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
64944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint32_t Assembler::GetBranchOffset(Instr instr) {
650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsBranch(instr));
651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return (static_cast<int16_t>(instr & kImm16Mask)) << 2;
65244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
65344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
65444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
65544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsLw(Instr instr) {
656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return (static_cast<uint32_t>(instr & kOpcodeMask) == LW);
65744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
65844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
65944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
66044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint16_t Assembler::GetLwOffset(Instr instr) {
661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsLw(instr));
66244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return ((instr & kImm16Mask));
66344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
66444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
66544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
66644f0eee88ff00398ff7f715fab053374d808c90dSteve BlockInstr Assembler::SetLwOffset(Instr instr, int16_t offset) {
667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsLw(instr));
66844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
66944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // We actually create a new lw instruction based on the original one.
67044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Instr temp_instr = LW | (instr & kRsFieldMask) | (instr & kRtFieldMask)
67144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      | (offset & kImm16Mask);
67244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
67344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return temp_instr;
67444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
67544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
67644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
67744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsSw(Instr instr) {
678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return (static_cast<uint32_t>(instr & kOpcodeMask) == SW);
67944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
68044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
68144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
68244f0eee88ff00398ff7f715fab053374d808c90dSteve BlockInstr Assembler::SetSwOffset(Instr instr, int16_t offset) {
683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsSw(instr));
68444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
68544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
68644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
68744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
68844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::IsAddImmediate(Instr instr) {
68944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return ((instr & kOpcodeMask) == ADDIU);
69044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
69144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
69244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
69344f0eee88ff00398ff7f715fab053374d808c90dSteve BlockInstr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) {
694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsAddImmediate(instr));
69544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
6963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
6973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochbool Assembler::IsAndImmediate(Instr instr) {
700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetOpcodeField(instr) == ANDI;
701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic Assembler::OffsetSize OffsetSizeInBits(Instr instr) {
705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (IsMipsArchVariant(kMips32r6)) {
706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (Assembler::IsBc(instr)) {
707014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return Assembler::OffsetSize::kOffset26;
708014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (Assembler::IsBzc(instr)) {
709014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return Assembler::OffsetSize::kOffset21;
710014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
711014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
712014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return Assembler::OffsetSize::kOffset16;
713014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
714014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
715014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
716014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic inline int32_t AddBranchOffset(int pos, Instr instr) {
717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int bits = OffsetSizeInBits(instr);
718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const int32_t mask = (1 << bits) - 1;
719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bits = 32 - bits;
720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming
722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // the compiler uses arithmetic shifts for signed integers.
723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int32_t imm = ((instr & mask) << bits) >> (bits - 2);
724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (imm == kEndOfChain) {
726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // EndOfChain sentinel is returned directly, not relative to pc or pos.
727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return kEndOfChain;
728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return pos + Assembler::kBranchPCOffset + imm;
730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
7333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochuint32_t Assembler::CreateTargetAddress(Instr instr_lui, Instr instr_jic) {
7343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(IsLui(instr_lui) && IsJicOrJialc(instr_jic));
7353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  int16_t jic_offset = GetImmediate16(instr_jic);
7363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  int16_t lui_offset = GetImmediate16(instr_lui);
7373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (jic_offset < 0) {
7393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    lui_offset += kImm16Mask;
7403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
7413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  uint32_t lui_offset_u = (static_cast<uint32_t>(lui_offset)) << kLuiShift;
7423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  uint32_t jic_offset_u = static_cast<uint32_t>(jic_offset) & kImm16Mask;
7433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return lui_offset_u | jic_offset_u;
7453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// Use just lui and jic instructions. Insert lower part of the target address in
7483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// jic offset part. Since jic sign-extends offset and then add it with register,
7493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// before that addition, difference between upper part of the target address and
7503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// upper part of the sign-extended offset (0xffff or 0x0000), will be inserted
7513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// in jic register with lui instruction.
7523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid Assembler::UnpackTargetAddress(uint32_t address, int16_t& lui_offset,
7533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                    int16_t& jic_offset) {
7543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  lui_offset = (address & kHiMask) >> kLuiShift;
7553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  jic_offset = address & kLoMask;
7563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (jic_offset < 0) {
7583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    lui_offset -= kImm16Mask;
7593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
7603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
7613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid Assembler::UnpackTargetAddressUnsigned(uint32_t address,
7633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                            uint32_t& lui_offset,
7643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                            uint32_t& jic_offset) {
7653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  int16_t lui_offset16 = (address & kHiMask) >> kLuiShift;
7663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  int16_t jic_offset16 = address & kLoMask;
7673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
7683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (jic_offset16 < 0) {
7693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    lui_offset16 -= kImm16Mask;
7703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
7713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  lui_offset = static_cast<uint32_t>(lui_offset16) & kImm16Mask;
7723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  jic_offset = static_cast<uint32_t>(jic_offset16) & kImm16Mask;
7733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
774014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
775014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochint Assembler::target_at(int pos, bool is_internal) {
7763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr instr = instr_at(pos);
777014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (is_internal) {
778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (instr == 0) {
779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return kEndOfChain;
780014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
781014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos);
782014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int delta = static_cast<int>(instr_address - instr);
783014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(pos > delta);
784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return pos - delta;
785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
7873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if ((instr & ~kImm16Mask) == 0) {
7883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Emitted label constant, not part of a branch.
78944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (instr == 0) {
79044f0eee88ff00398ff7f715fab053374d808c90dSteve Block       return kEndOfChain;
79144f0eee88ff00398ff7f715fab053374d808c90dSteve Block     } else {
79244f0eee88ff00398ff7f715fab053374d808c90dSteve Block       int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
79344f0eee88ff00398ff7f715fab053374d808c90dSteve Block       return (imm18 + pos);
79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block     }
7953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
7963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check we have a branch or jump instruction.
797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsBranch(instr) || IsLui(instr));
7983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (IsBranch(instr)) {
799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return AddBranchOffset(pos, instr);
800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
8013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Instr instr1 = instr_at(pos + 0 * Assembler::kInstrSize);
8023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Instr instr2 = instr_at(pos + 1 * Assembler::kInstrSize);
8033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(IsOri(instr2) || IsJicOrJialc(instr2));
8043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    int32_t imm;
8053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (IsJicOrJialc(instr2)) {
8063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      imm = CreateTargetAddress(instr1, instr2);
8073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else {
8083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      imm = (instr1 & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
8093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      imm |= (instr2 & static_cast<int32_t>(kImm16Mask));
8103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
8113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (imm == kEndOfJumpChain) {
8133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // EndOfChain sentinel is returned directly, not relative to pc or pos.
8143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return kEndOfChain;
8153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
8163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos);
8173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int32_t delta = instr_address - imm;
818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(pos > delta);
8193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return pos - delta;
8203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
82144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return 0;
823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic inline Instr SetBranchOffset(int32_t pos, int32_t target_pos,
827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                    Instr instr) {
828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int32_t bits = OffsetSizeInBits(instr);
829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int32_t imm = target_pos - (pos + Assembler::kBranchPCOffset);
830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((imm & 3) == 0);
831014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  imm >>= 2;
832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const int32_t mask = (1 << bits) - 1;
834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  instr &= ~mask;
835014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(is_intn(imm, bits));
836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
837014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return instr | (imm & mask);
8383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
8393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::target_at_put(int32_t pos, int32_t target_pos,
842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              bool is_internal) {
8433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr instr = instr_at(pos);
844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (is_internal) {
846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    instr_at_put(pos, imm);
848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
849014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
8503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if ((instr & ~kImm16Mask) == 0) {
851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(target_pos == kEndOfChain || target_pos >= 0);
8523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Emitted label constant, not part of a branch.
8533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Make label relative to Code* of generated Code object.
8543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
8553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    return;
8563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
8573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsBranch(instr) || IsLui(instr));
8593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (IsBranch(instr)) {
860014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    instr = SetBranchOffset(pos, target_pos, instr);
861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    instr_at_put(pos, instr);
862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
8633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Instr instr1 = instr_at(pos + 0 * Assembler::kInstrSize);
8643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Instr instr2 = instr_at(pos + 1 * Assembler::kInstrSize);
8653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(IsOri(instr2) || IsJicOrJialc(instr2));
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK((imm & 3) == 0);
8683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(IsLui(instr1) && (IsJicOrJialc(instr2) || IsOri(instr2)));
8693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    instr1 &= ~kImm16Mask;
8703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    instr2 &= ~kImm16Mask;
8713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
8723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (IsJicOrJialc(instr2)) {
8733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      uint32_t lui_offset_u, jic_offset_u;
8743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      UnpackTargetAddressUnsigned(imm, lui_offset_u, jic_offset_u);
8753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      instr_at_put(pos + 0 * Assembler::kInstrSize, instr1 | lui_offset_u);
8763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      instr_at_put(pos + 1 * Assembler::kInstrSize, instr2 | jic_offset_u);
8773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else {
8783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      instr_at_put(pos + 0 * Assembler::kInstrSize,
8793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                   instr1 | ((imm & kHiMask) >> kLuiShift));
8803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      instr_at_put(pos + 1 * Assembler::kInstrSize,
8813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                   instr2 | (imm & kImm16Mask));
8823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
8833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
8843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
8853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::print(Label* L) {
8883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (L->is_unused()) {
8893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    PrintF("unused label\n");
8903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else if (L->is_bound()) {
8913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    PrintF("bound label to %d\n", L->pos());
8923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else if (L->is_linked()) {
8933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    Label l = *L;
8943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    PrintF("unbound label");
8953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    while (l.is_linked()) {
8963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      PrintF("@ %d ", l.pos());
8973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      Instr instr = instr_at(l.pos());
8983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      if ((instr & ~kImm16Mask) == 0) {
8993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        PrintF("value\n");
9003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      } else {
9013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu        PrintF("%d\n", instr);
9023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      }
90362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      next(&l, is_internal_reference(&l));
9043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
9053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
9063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
9073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
9083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
9093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bind_to(Label* L, int pos) {
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(0 <= pos && pos <= pc_offset());  // Must have valid binding position.
9133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int32_t trampoline_pos = kInvalidSlotPos;
914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is_internal = false;
9153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (L->is_linked() && !trampoline_emitted_) {
9163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    unbound_labels_count_--;
91762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (!is_internal_reference(L)) {
91862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      next_buffer_check_ += kTrampolineSlotsSize;
91962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
9203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
9213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
9223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  while (L->is_linked()) {
9233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    int32_t fixup_pos = L->pos();
92444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int32_t dist = pos - fixup_pos;
92562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    is_internal = is_internal_reference(L);
926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    next(L, is_internal);  // Call next before overwriting link with target at
927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                           // fixup_pos.
9283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Instr instr = instr_at(fixup_pos);
929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (is_internal) {
930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      target_at_put(fixup_pos, pos, is_internal);
931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (IsBranch(instr)) {
933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        int branch_offset = BranchOffset(instr);
934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (dist > branch_offset) {
935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (trampoline_pos == kInvalidSlotPos) {
936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            trampoline_pos = get_trampoline_entry(fixup_pos);
937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            CHECK(trampoline_pos != kInvalidSlotPos);
938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          CHECK((trampoline_pos - fixup_pos) <= branch_offset);
940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          target_at_put(fixup_pos, trampoline_pos, false);
941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          fixup_pos = trampoline_pos;
942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        }
943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        target_at_put(fixup_pos, pos, false);
944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        target_at_put(fixup_pos, pos, false);
9463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
9473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
9483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
9493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  L->bind_to(pos);
9503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Keep track of the last bound label so we don't eliminate any instructions
9523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // before a bound label.
9533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (pos > last_bound_pos_)
9543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    last_bound_pos_ = pos;
9553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
9563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bind(Label* L) {
959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!L->is_bound());  // Label can only be bound once.
9603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  bind_to(L, pc_offset());
9613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
9623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::next(Label* L, bool is_internal) {
965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(L->is_linked());
966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int link = target_at(L->pos(), is_internal);
96744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (link == kEndOfChain) {
9683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    L->Unuse();
96969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  } else {
970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(link >= 0);
97144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    L->link_to(link);
9723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
9733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
9743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochbool Assembler::is_near(Label* L) {
977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(L->is_bound());
978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return pc_offset() - L->pos() < kMaxBranchOffset - 4 * kInstrSize;
979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool Assembler::is_near(Label* L, OffsetSize bits) {
983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (L == nullptr || !L->is_bound()) return true;
984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return pc_offset() - L->pos() < (1 << (bits + 2 - 1)) - 1 - 5 * kInstrSize;
985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool Assembler::is_near_branch(Label* L) {
989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(L->is_bound());
990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return IsMipsArchVariant(kMips32r6) ? is_near_r6(L) : is_near_pre_r6(L);
991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochint Assembler::BranchOffset(Instr instr) {
995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // At pre-R6 and for other R6 branches the offset is 16 bits.
996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int bits = OffsetSize::kOffset16;
997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (IsMipsArchVariant(kMips32r6)) {
999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    uint32_t opcode = GetOpcodeField(instr);
1000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    switch (opcode) {
1001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Checks BC or BALC.
1002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case BC:
1003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case BALC:
1004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bits = OffsetSize::kOffset26;
1005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
1006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Checks BEQZC or BNEZC.
1008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case POP66:
1009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case POP76:
1010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (GetRsField(instr) != 0) bits = OffsetSize::kOffset21;
1011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
1012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      default:
1013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
1014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
10153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return (1 << (bits + 2 - 1)) - 1;
10183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
10193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
10213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// We have to use a temporary register for things that can be relocated even
10223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// if they can be encoded in the MIPS's 16 bits of immediate-offset instruction
10233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// space.  There is no guarantee that the relocated location can be similarly
10243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// encoded.
102544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Assembler::MustUseReg(RelocInfo::Mode rmode) {
1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return !RelocInfo::IsNone(rmode);
10273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
10283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::GenInstrRegister(Opcode opcode,
10303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 Register rs,
10313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 Register rt,
10323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 Register rd,
10333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 uint16_t sa,
10343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 SecondaryField func) {
1035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rd.is_valid() && rs.is_valid() && rt.is_valid() && is_uint5(sa));
10363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
10373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      | (rd.code() << kRdShift) | (sa << kSaShift) | func;
10383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  emit(instr);
10393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
10403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::GenInstrRegister(Opcode opcode,
104344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 Register rs,
104444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 Register rt,
104544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 uint16_t msb,
104644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 uint16_t lsb,
104744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 SecondaryField func) {
1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rs.is_valid() && rt.is_valid() && is_uint5(msb) && is_uint5(lsb));
104944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
105044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      | (msb << kRdShift) | (lsb << kSaShift) | func;
105144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  emit(instr);
105244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
105344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
105444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
105544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::GenInstrRegister(Opcode opcode,
10563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 SecondaryField fmt,
10573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 FPURegister ft,
10583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 FPURegister fs,
10593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 FPURegister fd,
10603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 SecondaryField func) {
1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(fd.is_valid() && fs.is_valid() && ft.is_valid());
106244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Instr instr = opcode | fmt | (ft.code() << kFtShift) | (fs.code() << kFsShift)
106344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      | (fd.code() << kFdShift) | func;
10643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  emit(instr);
10653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
10663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::GenInstrRegister(Opcode opcode,
1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 FPURegister fr,
1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 FPURegister ft,
1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 FPURegister fs,
1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 FPURegister fd,
1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 SecondaryField func) {
1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(fd.is_valid() && fr.is_valid() && fs.is_valid() && ft.is_valid());
1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Instr instr = opcode | (fr.code() << kFrShift) | (ft.code() << kFtShift)
1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(instr);
1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::GenInstrRegister(Opcode opcode,
10823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 SecondaryField fmt,
10833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 Register rt,
10843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 FPURegister fs,
10853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 FPURegister fd,
10863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 SecondaryField func) {
1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(fd.is_valid() && fs.is_valid() && rt.is_valid());
10883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr instr = opcode | fmt | (rt.code() << kRtShift)
108944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
109044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  emit(instr);
109144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
109244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
109344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
109444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::GenInstrRegister(Opcode opcode,
109544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 SecondaryField fmt,
109644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 Register rt,
109744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 FPUControlRegister fs,
109844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 SecondaryField func) {
1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(fs.is_valid() && rt.is_valid());
110044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Instr instr =
110144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func;
11023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  emit(instr);
11033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
11043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Instructions with immediate value.
11073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Registers are in the order of the instruction encoding, from left to right.
1108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::GenInstrImmediate(Opcode opcode, Register rs, Register rt,
1109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  int32_t j,
1110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  CompactBranchType is_compact_branch) {
1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j)));
11123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
11133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      | (j & kImm16Mask);
1114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(instr, is_compact_branch);
11153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
11163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::GenInstrImmediate(Opcode opcode, Register rs, SecondaryField SF,
1119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  int32_t j,
1120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  CompactBranchType is_compact_branch) {
1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rs.is_valid() && (is_int16(j) || is_uint16(j)));
11223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask);
1123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(instr, is_compact_branch);
11243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
11253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::GenInstrImmediate(Opcode opcode, Register rs, FPURegister ft,
1128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  int32_t j,
1129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  CompactBranchType is_compact_branch) {
1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j)));
11313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift)
11323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      | (j & kImm16Mask);
1133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(instr, is_compact_branch);
1134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::GenInstrImmediate(Opcode opcode, Register rs, int32_t offset21,
1138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  CompactBranchType is_compact_branch) {
1139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(rs.is_valid() && (is_int21(offset21)));
1140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Instr instr = opcode | (rs.code() << kRsShift) | (offset21 & kImm21Mask);
1141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(instr, is_compact_branch);
1142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::GenInstrImmediate(Opcode opcode, Register rs,
1146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  uint32_t offset21) {
1147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(rs.is_valid() && (is_uint21(offset21)));
1148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Instr instr = opcode | (rs.code() << kRsShift) | (offset21 & kImm21Mask);
11493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  emit(instr);
11503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
11513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::GenInstrImmediate(Opcode opcode, int32_t offset26,
1154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  CompactBranchType is_compact_branch) {
1155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(is_int26(offset26));
1156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Instr instr = opcode | (offset26 & kImm26Mask);
1157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(instr, is_compact_branch);
1158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
11613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::GenInstrJump(Opcode opcode,
1162589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                             uint32_t address) {
116344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolScope block_trampoline_pool(this);
1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint26(address));
11653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr instr = opcode | address;
11663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  emit(instr);
116744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolFor(1);  // For associated delay slot.
116844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
116944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
117044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
11713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// Returns the next free trampoline entry.
11723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochint32_t Assembler::get_trampoline_entry(int32_t pos) {
11733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int32_t trampoline_entry = kInvalidSlotPos;
117444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
11753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!internal_trampoline_exception_) {
11763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (trampoline_.start() > pos) {
11773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch     trampoline_entry = trampoline_.take_slot();
117844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
11793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
11803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (kInvalidSlotPos == trampoline_entry) {
11813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      internal_trampoline_exception_ = true;
118244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
118344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
11843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return trampoline_entry;
118544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
118644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
118744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
11883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochuint32_t Assembler::jump_address(Label* L) {
11893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int32_t target_pos;
119044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
11913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (L->is_bound()) {
11923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    target_pos = L->pos();
11933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
11943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (L->is_linked()) {
11953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      target_pos = L->pos();  // L's link.
11963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      L->link_to(pc_offset());
11973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
11983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      L->link_to(pc_offset());
11993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return kEndOfJumpChain;
1200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
120144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
12023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((imm & 3) == 0);
12053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
12063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return imm;
12073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
12083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochint32_t Assembler::branch_offset_helper(Label* L, OffsetSize bits) {
1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t target_pos;
1212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int32_t pad = IsPrevInstrCompactBranch() ? kInstrSize : 0;
1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (L->is_bound()) {
1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    target_pos = L->pos();
1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (L->is_linked()) {
1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      target_pos = L->pos();
1219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      L->link_to(pc_offset() + pad);
1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      L->link_to(pc_offset() + pad);
1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!trampoline_emitted_) {
1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        unbound_labels_count_++;
1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        next_buffer_check_ -= kTrampolineSlotsSize;
1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return kEndOfChain;
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int32_t offset = target_pos - (pc_offset() + kBranchPCOffset + pad);
1231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(is_intn(offset, bits + 2));
1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((offset & 3) == 0);
123344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
12343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  return offset;
12353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
12363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::label_at_put(Label* L, int at_offset) {
12393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  int target_pos;
12403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (L->is_bound()) {
12413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    target_pos = L->pos();
124244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
12433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
12443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    if (L->is_linked()) {
124544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      target_pos = L->pos();  // L's link.
124644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      int32_t imm18 = target_pos - at_offset;
1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK((imm18 & 3) == 0);
124844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      int32_t imm16 = imm18 >> 2;
1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(is_int16(imm16));
125044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      instr_at_put(at_offset, (imm16 & kImm16Mask));
12513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    } else {
12523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      target_pos = kEndOfChain;
125344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      instr_at_put(at_offset, 0);
12543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (!trampoline_emitted_) {
12553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        unbound_labels_count_++;
12563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        next_buffer_check_ -= kTrampolineSlotsSize;
12573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
12583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
12593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    L->link_to(at_offset);
12603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
12613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
12623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//------- Branch and jump instructions --------
12653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::b(int16_t offset) {
12673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  beq(zero_reg, zero_reg, offset);
12683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
12693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bal(int16_t offset) {
12723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  bgezal(zero_reg, offset);
12733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
12743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::bc(int32_t offset) {
1277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(BC, offset, CompactBranchType::COMPACT_BRANCH);
1279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::balc(int32_t offset) {
1283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(BALC, offset, CompactBranchType::COMPACT_BRANCH);
1285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
12883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::beq(Register rs, Register rt, int16_t offset) {
128944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolScope block_trampoline_pool(this);
12903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrImmediate(BEQ, rs, rt, offset);
129144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolFor(1);  // For associated delay slot.
12923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
12933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bgez(Register rs, int16_t offset) {
129644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolScope block_trampoline_pool(this);
12973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrImmediate(REGIMM, rs, BGEZ, offset);
129844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolFor(1);  // For associated delay slot.
12993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
13003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bgezc(Register rt, int16_t offset) {
1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(rt.is(zero_reg)));
1305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(BLEZL, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bgeuc(Register rs, Register rt, int16_t offset) {
1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(rs.is(zero_reg)));
1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(rt.is(zero_reg)));
1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rs.code() != rt.code());
1314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(BLEZ, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bgec(Register rs, Register rt, int16_t offset) {
1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(rs.is(zero_reg)));
1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(rt.is(zero_reg)));
1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rs.code() != rt.code());
1323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(BLEZL, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bgezal(Register rs, int16_t offset) {
1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!IsMipsArchVariant(kMips32r6) || rs.is(zero_reg));
132944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolScope block_trampoline_pool(this);
13303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrImmediate(REGIMM, rs, BGEZAL, offset);
133144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolFor(1);  // For associated delay slot.
13323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
13333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bgtz(Register rs, int16_t offset) {
133644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolScope block_trampoline_pool(this);
13373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrImmediate(BGTZ, rs, zero_reg, offset);
133844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolFor(1);  // For associated delay slot.
13393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
13403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bgtzc(Register rt, int16_t offset) {
1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(rt.is(zero_reg)));
1345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(BGTZL, zero_reg, rt, offset,
1346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    CompactBranchType::COMPACT_BRANCH);
1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::blez(Register rs, int16_t offset) {
135144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolScope block_trampoline_pool(this);
13523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrImmediate(BLEZ, rs, zero_reg, offset);
135344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolFor(1);  // For associated delay slot.
13543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
13553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::blezc(Register rt, int16_t offset) {
1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(rt.is(zero_reg)));
1360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(BLEZL, zero_reg, rt, offset,
1361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    CompactBranchType::COMPACT_BRANCH);
1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bltzc(Register rt, int16_t offset) {
1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1367014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!rt.is(zero_reg));
1368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(BGTZL, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bltuc(Register rs, Register rt, int16_t offset) {
1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(rs.is(zero_reg)));
1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(rt.is(zero_reg)));
1376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rs.code() != rt.code());
1377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(BGTZ, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bltc(Register rs, Register rt, int16_t offset) {
1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!rs.is(zero_reg));
1384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!rt.is(zero_reg));
1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rs.code() != rt.code());
1386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(BGTZL, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bltz(Register rs, int16_t offset) {
139144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolScope block_trampoline_pool(this);
13923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrImmediate(REGIMM, rs, BLTZ, offset);
139344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolFor(1);  // For associated delay slot.
13943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
13953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bltzal(Register rs, int16_t offset) {
1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!IsMipsArchVariant(kMips32r6) || rs.is(zero_reg));
139944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolScope block_trampoline_pool(this);
14003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrImmediate(REGIMM, rs, BLTZAL, offset);
140144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolFor(1);  // For associated delay slot.
14023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
14033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
14043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
14053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bne(Register rs, Register rt, int16_t offset) {
140644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolScope block_trampoline_pool(this);
14073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrImmediate(BNE, rs, rt, offset);
140844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolFor(1);  // For associated delay slot.
14093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
14103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
14113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bovc(Register rs, Register rt, int16_t offset) {
1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (rs.code() >= rt.code()) {
1415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GenInstrImmediate(ADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GenInstrImmediate(ADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH);
1418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bnvc(Register rs, Register rt, int16_t offset) {
1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (rs.code() >= rt.code()) {
1425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GenInstrImmediate(DADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GenInstrImmediate(DADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH);
1428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::blezalc(Register rt, int16_t offset) {
1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(rt.is(zero_reg)));
1435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(BLEZ, zero_reg, rt, offset,
1436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    CompactBranchType::COMPACT_BRANCH);
1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bgezalc(Register rt, int16_t offset) {
1441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(rt.is(zero_reg)));
1443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(BLEZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bgezall(Register rs, int16_t offset) {
1448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!IsMipsArchVariant(kMips32r6));
1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(rs.is(zero_reg)));
1450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BlockTrampolinePoolScope block_trampoline_pool(this);
1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenInstrImmediate(REGIMM, rs, BGEZALL, offset);
1452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BlockTrampolinePoolFor(1);  // For associated delay slot.
1453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bltzalc(Register rt, int16_t offset) {
1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(rt.is(zero_reg)));
1459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(BGTZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bgtzalc(Register rt, int16_t offset) {
1464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(rt.is(zero_reg)));
1466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(BGTZ, zero_reg, rt, offset,
1467014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    CompactBranchType::COMPACT_BRANCH);
1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::beqzalc(Register rt, int16_t offset) {
1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(rt.is(zero_reg)));
1474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(ADDI, zero_reg, rt, offset,
1475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    CompactBranchType::COMPACT_BRANCH);
1476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bnezalc(Register rt, int16_t offset) {
1480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(rt.is(zero_reg)));
1482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(DADDI, zero_reg, rt, offset,
1483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    CompactBranchType::COMPACT_BRANCH);
1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::beqc(Register rs, Register rt, int16_t offset) {
1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0);
1490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (rs.code() < rt.code()) {
1491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GenInstrImmediate(ADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GenInstrImmediate(ADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH);
1494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::beqzc(Register rs, int32_t offset) {
1499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(rs.is(zero_reg)));
1501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(POP66, rs, offset, CompactBranchType::COMPACT_BRANCH);
1502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bnec(Register rs, Register rt, int16_t offset) {
1506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0);
1508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (rs.code() < rt.code()) {
1509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GenInstrImmediate(DADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GenInstrImmediate(DADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH);
1512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bnezc(Register rs, int32_t offset) {
1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!(rs.is(zero_reg)));
1519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(POP76, rs, offset, CompactBranchType::COMPACT_BRANCH);
1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::j(int32_t target) {
1524589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#if DEBUG
1525589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Get pc of delay slot.
1526589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize);
1527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool in_range = ((ipc ^ static_cast<uint32_t>(target)) >>
1528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   (kImm26Bits + kImmFieldShift)) == 0;
1529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(in_range && ((target & 3) == 0));
1530589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#endif
1531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BlockTrampolinePoolScope block_trampoline_pool(this);
1532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrJump(J, (target >> 2) & kImm26Mask);
1533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BlockTrampolinePoolFor(1);  // For associated delay slot.
15343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
15353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::jr(Register rs) {
1538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!IsMipsArchVariant(kMips32r6)) {
1539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    BlockTrampolinePoolScope block_trampoline_pool(this);
1540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR);
1541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    BlockTrampolinePoolFor(1);  // For associated delay slot.
1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    jalr(rs, zero_reg);
154444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
15453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
15463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::jal(int32_t target) {
1549589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#ifdef DEBUG
1550589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Get pc of delay slot.
1551589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize);
1552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool in_range = ((ipc ^ static_cast<uint32_t>(target)) >>
1553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   (kImm26Bits + kImmFieldShift)) == 0;
1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(in_range && ((target & 3) == 0));
1555589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#endif
1556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BlockTrampolinePoolScope block_trampoline_pool(this);
1557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrJump(JAL, (target >> 2) & kImm26Mask);
1558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  BlockTrampolinePoolFor(1);  // For associated delay slot.
15593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
15603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::jalr(Register rs, Register rd) {
1563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(rs.code() != rd.code());
156444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolScope block_trampoline_pool(this);
15653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR);
156644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolFor(1);  // For associated delay slot.
15673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
15683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::jic(Register rt, int16_t offset) {
1571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(POP66, zero_reg, rt, offset);
1573589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
1574589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1575589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::jialc(Register rt, int16_t offset) {
1577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(POP76, zero_reg, rt, offset);
1579589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
1580589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1581589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// -------Data-processing-instructions---------
15833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Arithmetic.
15853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::addu(Register rd, Register rs, Register rt) {
15873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU);
15883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
15893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::addiu(Register rd, Register rs, int32_t j) {
15923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrImmediate(ADDIU, rs, rd, j);
15933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
15943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::subu(Register rd, Register rs, Register rt) {
15973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU);
15983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
15993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::mul(Register rd, Register rs, Register rt) {
1602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!IsMipsArchVariant(kMips32r6)) {
1603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL);
1604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, MUL_MUH);
1606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::mulu(Register rd, Register rs, Register rt) {
1611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, MUL_MUH_U);
1613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::muh(Register rd, Register rs, Register rt) {
1617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, MUL_MUH);
1619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::muhu(Register rd, Register rs, Register rt) {
1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, MUL_MUH_U);
1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::mod(Register rd, Register rs, Register rt) {
1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, DIV_MOD);
1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::modu(Register rd, Register rs, Register rt) {
1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, DIV_MOD_U);
16373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
16383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::mult(Register rs, Register rt) {
16413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULT);
16423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
16433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::multu(Register rs, Register rt) {
16463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULTU);
16473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
16483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::div(Register rs, Register rt) {
16513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIV);
16523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
16533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::div(Register rd, Register rs, Register rt) {
1656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, DIV_MOD);
1658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::divu(Register rs, Register rt) {
16623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIVU);
16633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
16643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::divu(Register rd, Register rs, Register rt) {
1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, DIV_MOD_U);
1669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Logical.
16733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::and_(Register rd, Register rs, Register rt) {
16753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(SPECIAL, rs, rt, rd, 0, AND);
16763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
16773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::andi(Register rt, Register rs, int32_t j) {
1680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint16(j));
16813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrImmediate(ANDI, rs, rt, j);
16823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
16833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::or_(Register rd, Register rs, Register rt) {
16863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(SPECIAL, rs, rt, rd, 0, OR);
16873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
16883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::ori(Register rt, Register rs, int32_t j) {
1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint16(j));
16923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrImmediate(ORI, rs, rt, j);
16933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
16943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::xor_(Register rd, Register rs, Register rt) {
16973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(SPECIAL, rs, rt, rd, 0, XOR);
16983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
16993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::xori(Register rt, Register rs, int32_t j) {
1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint16(j));
17033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrImmediate(XORI, rs, rt, j);
17043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
17053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::nor(Register rd, Register rs, Register rt) {
17083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(SPECIAL, rs, rt, rd, 0, NOR);
17093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
17103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Shifts.
171344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::sll(Register rd,
171444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    Register rt,
171544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    uint16_t sa,
171644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    bool coming_from_nop) {
171744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Don't allow nop instructions in the form sll zero_reg, zero_reg to be
171844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // generated using the sll instruction. They must be generated using
171944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // nop(int/NopMarkerTypes) or MarkCode(int/NopMarkerTypes) pseudo
172044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // instructions.
1721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(coming_from_nop || !(rd.is(zero_reg) && rt.is(zero_reg)));
1722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SLL);
17233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
17243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::sllv(Register rd, Register rt, Register rs) {
17273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLLV);
17283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
17293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::srl(Register rd, Register rt, uint16_t sa) {
1732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SRL);
17333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
17343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::srlv(Register rd, Register rt, Register rs) {
17373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRLV);
17383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
17393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::sra(Register rd, Register rt, uint16_t sa) {
1742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SRA);
17433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
17443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::srav(Register rd, Register rt, Register rs) {
17473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRAV);
17483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
17493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
175144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::rotr(Register rd, Register rt, uint16_t sa) {
175244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Should be called via MacroAssembler::Ror.
1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rd.is_valid() && rt.is_valid() && is_uint5(sa));
1754014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
175544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift)
175644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      | (rd.code() << kRdShift) | (sa << kSaShift) | SRL;
175744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  emit(instr);
175844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
175944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
176044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
176144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::rotrv(Register rd, Register rt, Register rs) {
176244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Should be called via MacroAssembler::Ror.
1763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid());
1764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
176544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift)
176644f0eee88ff00398ff7f715fab053374d808c90dSteve Block     | (rd.code() << kRdShift) | (1 << kSaShift) | SRLV;
176744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  emit(instr);
176844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
176944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
177044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1771014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::lsa(Register rd, Register rt, Register rs, uint8_t sa) {
1772014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid());
17733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(sa <= 3);
1774014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
17753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Instr instr = SPECIAL | rs.code() << kRsShift | rt.code() << kRtShift |
17763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                rd.code() << kRdShift | sa << kSaShift | LSA;
1777014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit(instr);
1778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1780014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ------------Memory-instructions-------------
17823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
178344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Helper for base-reg + offset, when offset is larger than int16.
178444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::LoadRegPlusOffsetToAt(const MemOperand& src) {
1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src.rm().is(at));
178662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (IsMipsArchVariant(kMips32r6)) {
178762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    int32_t hi = (src.offset_ >> kLuiShift) & kImm16Mask;
178862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (src.offset_ & kNegOffset) {
178962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      hi += 1;
179062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
179162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    aui(at, src.rm(), hi);
179262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    addiu(at, at, src.offset_ & kImm16Mask);
179362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  } else {
179462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    lui(at, (src.offset_ >> kLuiShift) & kImm16Mask);
179562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    ori(at, at, src.offset_ & kImm16Mask);  // Load 32-bit offset.
179662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    addu(at, at, src.rm());                 // Add base register.
179762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
179844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
179944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1800c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// Helper for base-reg + upper part of offset, when offset is larger than int16.
1801c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// Loads higher part of the offset to AT register.
1802c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// Returns lower part of the offset to be used as offset
1803c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// in Load/Store instructions
1804c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochint32_t Assembler::LoadRegPlusUpperOffsetPartToAt(const MemOperand& src) {
1805c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  DCHECK(!src.rm().is(at));
1806c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  int32_t hi = (src.offset_ >> kLuiShift) & kImm16Mask;
1807c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // If the highest bit of the lower part of the offset is 1, this would make
1808c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // the offset in the load/store instruction negative. We need to compensate
1809c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // for this by adding 1 to the upper part of the offset.
1810c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (src.offset_ & kNegOffset) {
1811c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    hi += 1;
1812c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
181362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
181462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (IsMipsArchVariant(kMips32r6)) {
181562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    aui(at, src.rm(), hi);
181662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  } else {
181762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    lui(at, hi);
181862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    addu(at, at, src.rm());
181962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
1820c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return (src.offset_ & kImm16Mask);
1821c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1822c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1823c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// Helper for loading base-reg + upper offset's part to AT reg when we are using
1824c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// two 32-bit loads/stores instead of one 64-bit
1825c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochint32_t Assembler::LoadUpperOffsetForTwoMemoryAccesses(const MemOperand& src) {
1826c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  DCHECK(!src.rm().is(at));
1827c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (is_int16((src.offset_ & kImm16Mask) + kIntSize)) {
1828c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // Only if lower part of offset + kIntSize fits in 16bits
1829c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return LoadRegPlusUpperOffsetPartToAt(src);
1830c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1831c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // In case offset's lower part + kIntSize doesn't fit in 16bits,
1832c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // load reg + hole offset to AT
1833c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  LoadRegPlusOffsetToAt(src);
1834c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return 0;
1835c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
183644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
18373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::lb(Register rd, const MemOperand& rs) {
183844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (is_int16(rs.offset_)) {
183944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    GenInstrImmediate(LB, rs.rm(), rd, rs.offset_);
184044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {  // Offset > 16 bits, use multiple instructions to load.
1841c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
1842c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    GenInstrImmediate(LB, at, rd, off16);
184344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
18443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
18453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
18463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
18473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::lbu(Register rd, const MemOperand& rs) {
184844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (is_int16(rs.offset_)) {
184944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    GenInstrImmediate(LBU, rs.rm(), rd, rs.offset_);
185044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {  // Offset > 16 bits, use multiple instructions to load.
1851c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
1852c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    GenInstrImmediate(LBU, at, rd, off16);
185344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
185444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
185544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
185644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
185744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::lh(Register rd, const MemOperand& rs) {
185844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (is_int16(rs.offset_)) {
185944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    GenInstrImmediate(LH, rs.rm(), rd, rs.offset_);
186044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {  // Offset > 16 bits, use multiple instructions to load.
1861c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
1862c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    GenInstrImmediate(LH, at, rd, off16);
186344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
186444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
186544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
186644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
186744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::lhu(Register rd, const MemOperand& rs) {
186844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (is_int16(rs.offset_)) {
186944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    GenInstrImmediate(LHU, rs.rm(), rd, rs.offset_);
187044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {  // Offset > 16 bits, use multiple instructions to load.
1871c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
1872c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    GenInstrImmediate(LHU, at, rd, off16);
187344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
18743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
18753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
18763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
18773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::lw(Register rd, const MemOperand& rs) {
187844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (is_int16(rs.offset_)) {
187944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    GenInstrImmediate(LW, rs.rm(), rd, rs.offset_);
188044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {  // Offset > 16 bits, use multiple instructions to load.
1881c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
1882c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    GenInstrImmediate(LW, at, rd, off16);
188344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
188444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
188544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
188644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
188744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::lwl(Register rd, const MemOperand& rs) {
1888bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(is_int16(rs.offset_));
1889bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r1) ||
1890bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch         IsMipsArchVariant(kMips32r2));
189144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_);
189244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
189344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
189444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
189544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::lwr(Register rd, const MemOperand& rs) {
1896bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(is_int16(rs.offset_));
1897bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r1) ||
1898bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch         IsMipsArchVariant(kMips32r2));
189944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_);
19003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
19013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
19023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
19033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::sb(Register rd, const MemOperand& rs) {
190444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (is_int16(rs.offset_)) {
190544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    GenInstrImmediate(SB, rs.rm(), rd, rs.offset_);
190644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {  // Offset > 16 bits, use multiple instructions to store.
1907c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
1908c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    GenInstrImmediate(SB, at, rd, off16);
190944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
191044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
191144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
191244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
191344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::sh(Register rd, const MemOperand& rs) {
191444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (is_int16(rs.offset_)) {
191544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    GenInstrImmediate(SH, rs.rm(), rd, rs.offset_);
191644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {  // Offset > 16 bits, use multiple instructions to store.
1917c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
1918c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    GenInstrImmediate(SH, at, rd, off16);
191944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
19203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
19213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
19223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
19233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::sw(Register rd, const MemOperand& rs) {
192444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (is_int16(rs.offset_)) {
192544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    GenInstrImmediate(SW, rs.rm(), rd, rs.offset_);
192644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {  // Offset > 16 bits, use multiple instructions to store.
1927c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
1928c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    GenInstrImmediate(SW, at, rd, off16);
192944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
193044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
193144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
193244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
193344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::swl(Register rd, const MemOperand& rs) {
1934bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(is_int16(rs.offset_));
1935bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r1) ||
1936bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch         IsMipsArchVariant(kMips32r2));
193744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_);
193844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
193944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
194044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
194144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::swr(Register rd, const MemOperand& rs) {
1942bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(is_int16(rs.offset_));
1943bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r1) ||
1944bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch         IsMipsArchVariant(kMips32r2));
194544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_);
19463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
19473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
19483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
19493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::lui(Register rd, int32_t j) {
1950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint16(j));
19513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrImmediate(LUI, zero_reg, rd, j);
19523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
19533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
19543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::aui(Register rt, Register rs, int32_t j) {
1956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This instruction uses same opcode as 'lui'. The difference in encoding is
1957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // 'lui' has zero reg. for rs field.
1958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!(rs.is(zero_reg)));
1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint16(j));
1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenInstrImmediate(LUI, rs, rt, j);
1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// ---------PC-Relative instructions-----------
19643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::addiupc(Register rs, int32_t imm19) {
1966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(rs.is_valid() && is_int19(imm19));
1968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t imm21 = ADDIUPC << kImm19Bits | (imm19 & kImm19Mask);
1969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(PCREL, rs, imm21);
1970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::lwpc(Register rs, int32_t offset19) {
1974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(rs.is_valid() && is_int19(offset19));
1976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t imm21 = LWPC << kImm19Bits | (offset19 & kImm19Mask);
1977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(PCREL, rs, imm21);
1978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::auipc(Register rs, int16_t imm16) {
1982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(rs.is_valid());
1984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t imm21 = AUIPC << kImm16Bits | (imm16 & kImm16Mask);
1985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(PCREL, rs, imm21);
1986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::aluipc(Register rs, int16_t imm16) {
1990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
1991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(rs.is_valid());
1992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t imm21 = ALUIPC << kImm16Bits | (imm16 & kImm16Mask);
1993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrImmediate(PCREL, rs, imm21);
1994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// -------------Misc-instructions--------------
1998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Break / Trap instructions.
20003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Assembler::break_(uint32_t code, bool break_as_stop) {
2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((code & ~0xfffff) == 0);
20023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // We need to invalidate breaks that could be stops as well because the
20033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // simulator expects a char pointer after the stop instruction.
20043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // See constants-mips.h for explanation.
2005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((break_as_stop &&
20063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          code <= kMaxStopCode &&
20073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          code > kMaxWatchpointCode) ||
20083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch         (!break_as_stop &&
20093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          (code > kMaxStopCode ||
20103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch           code <= kMaxWatchpointCode)));
20113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr break_instr = SPECIAL | BREAK | (code << 6);
20123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  emit(break_instr);
20133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
20143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
20153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
20163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Assembler::stop(const char* msg, uint32_t code) {
2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(code > kMaxWatchpointCode);
2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(code <= kMaxStopCode);
2019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_HOST_ARCH_MIPS
20203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  break_(0x54321);
20213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#else  // V8_HOST_ARCH_MIPS
20223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BlockTrampolinePoolFor(2);
20233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // The Simulator will handle the stop instruction and get the message address.
20243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // On MIPS stop() is just a special kind of break_().
20253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  break_(code, true);
2026f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Do not embed the message string address! We used to do this, but that
2027f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // made snapshots created from position-independent executable builds
2028f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // non-deterministic.
2029f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // TODO(yangguo): remove this field entirely.
2030f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  nop();
20313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif
20323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
20333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
20343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
20353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::tge(Register rs, Register rt, uint16_t code) {
2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint10(code));
20373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr instr = SPECIAL | TGE | rs.code() << kRsShift
20383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      | rt.code() << kRtShift | code << 6;
20393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  emit(instr);
20403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
20413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
20423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
20433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::tgeu(Register rs, Register rt, uint16_t code) {
2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint10(code));
20453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr instr = SPECIAL | TGEU | rs.code() << kRsShift
20463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      | rt.code() << kRtShift | code << 6;
20473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  emit(instr);
20483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
20493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
20503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
20513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::tlt(Register rs, Register rt, uint16_t code) {
2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint10(code));
20533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr instr =
20543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      SPECIAL | TLT | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
20553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  emit(instr);
20563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
20573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
20583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
20593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::tltu(Register rs, Register rt, uint16_t code) {
2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint10(code));
206144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Instr instr =
206244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      SPECIAL | TLTU | rs.code() << kRsShift
20633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      | rt.code() << kRtShift | code << 6;
20643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  emit(instr);
20653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
20663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
20673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
20683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::teq(Register rs, Register rt, uint16_t code) {
2069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint10(code));
20703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr instr =
20713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      SPECIAL | TEQ | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
20723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  emit(instr);
20733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
20743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
20753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
20763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::tne(Register rs, Register rt, uint16_t code) {
2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint10(code));
20783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr instr =
20793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      SPECIAL | TNE | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
20803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  emit(instr);
20813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
20823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2083bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid Assembler::sync() {
2084bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Instr sync_instr = SPECIAL | SYNC;
2085bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  emit(sync_instr);
2086bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
20873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
20883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Move from HI/LO register.
20893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
20903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::mfhi(Register rd) {
20913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFHI);
20923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
20933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
20943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
20953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::mflo(Register rd) {
20963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFLO);
20973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
20983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
20993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
21003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Set on less than instructions.
21013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::slt(Register rd, Register rs, Register rt) {
21023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLT);
21033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
21043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
21053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
21063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::sltu(Register rd, Register rs, Register rt) {
21073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLTU);
21083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
21093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
21103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
21113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::slti(Register rt, Register rs, int32_t j) {
21123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrImmediate(SLTI, rs, rt, j);
21133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
21143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
21153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
21163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::sltiu(Register rt, Register rs, int32_t j) {
21173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrImmediate(SLTIU, rs, rt, j);
21183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
21193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
21203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
212144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Conditional move.
212244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::movz(Register rd, Register rs, Register rt) {
212344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVZ);
212444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
212544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
212644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
212744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::movn(Register rd, Register rs, Register rt) {
212844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVN);
212944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
213044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
213144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
213244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::movt(Register rd, Register rs, uint16_t cc) {
213344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register rt;
2134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  rt.reg_code = (cc & 0x0007) << 2 | 1;
213544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
213644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
213744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
213844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
213944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::movf(Register rd, Register rs, uint16_t cc) {
214044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register rt;
2141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  rt.reg_code = (cc & 0x0007) << 2 | 0;
214244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
214344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
214444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
214544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::seleqz(Register rd, Register rs, Register rt) {
2147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SELEQZ_S);
2149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
215244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Bit twiddling.
215344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::clz(Register rd, Register rs) {
2154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!IsMipsArchVariant(kMips32r6)) {
2155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Clz instr requires same GPR number in 'rd' and 'rt' fields.
2156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    GenInstrRegister(SPECIAL2, rs, rd, rd, 0, CLZ);
2157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    GenInstrRegister(SPECIAL, rs, zero_reg, rd, 1, CLZ_R6);
2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
216044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
216144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
216244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
216344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::ins_(Register rt, Register rs, uint16_t pos, uint16_t size) {
216444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Should be called via MacroAssembler::Ins.
216544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Ins instr has 'rt' field as dest, and two uint5: msb, lsb.
2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
216744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, INS);
216844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
216944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
217044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
217144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::ext_(Register rt, Register rs, uint16_t pos, uint16_t size) {
217244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Should be called via MacroAssembler::Ext.
217344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Ext instr has 'rt' field as dest, and two uint5: msb, lsb.
2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
217544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, EXT);
217644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
217744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
217844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::bitswap(Register rd, Register rt) {
2180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(SPECIAL3, zero_reg, rt, rd, 0, BSHFL);
2182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::pref(int32_t hint, const MemOperand& rs) {
2186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!IsMipsArchVariant(kLoongson));
2187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint5(hint) && is_uint16(rs.offset_));
2188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Instr instr = PREF | (rs.rm().code() << kRsShift) | (hint << kRtShift)
2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      | (rs.offset_);
2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(instr);
2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::align(Register rd, Register rs, Register rt, uint8_t bp) {
2195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(is_uint3(bp));
2197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint16_t sa = (ALIGN << kBp2Bits) | bp;
2198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(SPECIAL3, rs, rt, rd, sa, BSHFL);
2199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
220113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// Byte swap.
220213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::wsbh(Register rd, Register rt) {
220313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
220413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  GenInstrRegister(SPECIAL3, zero_reg, rt, rd, WSBH, BSHFL);
220513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
220613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
220713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::seh(Register rd, Register rt) {
220813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
220913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEH, BSHFL);
221013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
221113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
221213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::seb(Register rd, Register rt) {
221313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
221413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEB, BSHFL);
221513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
2216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// --------Coprocessor-instructions----------------
22183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
22193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Load, store, move.
22203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::lwc1(FPURegister fd, const MemOperand& src) {
2221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (is_int16(src.offset_)) {
2222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GenInstrImmediate(LWC1, src.rm(), fd, src.offset_);
2223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {  // Offset > 16 bits, use multiple instructions to load.
2224c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    int32_t off16 = LoadRegPlusUpperOffsetPartToAt(src);
2225c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    GenInstrImmediate(LWC1, at, fd, off16);
2226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
22273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
22283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
22293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
22303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::ldc1(FPURegister fd, const MemOperand& src) {
223144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit
223244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // load to two 32-bit loads.
2233109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (IsFp32Mode()) {  // fp32 mode.
2234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (is_int16(src.offset_) && is_int16(src.offset_ + kIntSize)) {
2235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      GenInstrImmediate(LWC1, src.rm(), fd,
2236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        src.offset_ + Register::kMantissaOffset);
2237109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      FPURegister nextfpreg;
2238109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      nextfpreg.setcode(fd.code() + 1);
2239109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      GenInstrImmediate(LWC1, src.rm(), nextfpreg,
2240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        src.offset_ + Register::kExponentOffset);
2241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {  // Offset > 16 bits, use multiple instructions to load.
2242c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      int32_t off16 = LoadUpperOffsetForTwoMemoryAccesses(src);
2243c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      GenInstrImmediate(LWC1, at, fd, off16 + Register::kMantissaOffset);
2244109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      FPURegister nextfpreg;
2245109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      nextfpreg.setcode(fd.code() + 1);
2246c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      GenInstrImmediate(LWC1, at, nextfpreg, off16 + Register::kExponentOffset);
2247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2248109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
2249109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(IsFp64Mode() || IsFpxxMode());
2250109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Currently we support FPXX and FP64 on Mips32r2 and Mips32r6
2251109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (is_int16(src.offset_) && is_int16(src.offset_ + kIntSize)) {
2253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      GenInstrImmediate(LWC1, src.rm(), fd,
2254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        src.offset_ + Register::kMantissaOffset);
2255109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      GenInstrImmediate(LW, src.rm(), at,
2256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        src.offset_ + Register::kExponentOffset);
2257109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      mthc1(at, fd);
2258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {  // Offset > 16 bits, use multiple instructions to load.
2259c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      int32_t off16 = LoadUpperOffsetForTwoMemoryAccesses(src);
2260c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      GenInstrImmediate(LWC1, at, fd, off16 + Register::kMantissaOffset);
2261c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      GenInstrImmediate(LW, at, at, off16 + Register::kExponentOffset);
2262109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      mthc1(at, fd);
2263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
22663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
22673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
22683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::swc1(FPURegister fd, const MemOperand& src) {
2269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (is_int16(src.offset_)) {
2270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GenInstrImmediate(SWC1, src.rm(), fd, src.offset_);
2271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {  // Offset > 16 bits, use multiple instructions to load.
2272c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    int32_t off16 = LoadRegPlusUpperOffsetPartToAt(src);
2273c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    GenInstrImmediate(SWC1, at, fd, off16);
2274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
22753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
22763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
22773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
22783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::sdc1(FPURegister fd, const MemOperand& src) {
227944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit
228044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // store to two 32-bit stores.
2281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!src.rm().is(at));
2282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!src.rm().is(t8));
2283109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (IsFp32Mode()) {  // fp32 mode.
2284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (is_int16(src.offset_) && is_int16(src.offset_ + kIntSize)) {
2285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      GenInstrImmediate(SWC1, src.rm(), fd,
2286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        src.offset_ + Register::kMantissaOffset);
2287109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      FPURegister nextfpreg;
2288109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      nextfpreg.setcode(fd.code() + 1);
2289109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      GenInstrImmediate(SWC1, src.rm(), nextfpreg,
2290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        src.offset_ + Register::kExponentOffset);
2291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {  // Offset > 16 bits, use multiple instructions to load.
2292c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      int32_t off16 = LoadUpperOffsetForTwoMemoryAccesses(src);
2293c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      GenInstrImmediate(SWC1, at, fd, off16 + Register::kMantissaOffset);
2294109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      FPURegister nextfpreg;
2295109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      nextfpreg.setcode(fd.code() + 1);
2296c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      GenInstrImmediate(SWC1, at, nextfpreg, off16 + Register::kExponentOffset);
2297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2298109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
2299109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(IsFp64Mode() || IsFpxxMode());
2300109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Currently we support FPXX and FP64 on Mips32r2 and Mips32r6
2301109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (is_int16(src.offset_) && is_int16(src.offset_ + kIntSize)) {
2303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      GenInstrImmediate(SWC1, src.rm(), fd,
2304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        src.offset_ + Register::kMantissaOffset);
2305109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      mfhc1(at, fd);
2306109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      GenInstrImmediate(SW, src.rm(), at,
2307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        src.offset_ + Register::kExponentOffset);
2308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {  // Offset > 16 bits, use multiple instructions to load.
2309c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      int32_t off16 = LoadUpperOffsetForTwoMemoryAccesses(src);
2310c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      GenInstrImmediate(SWC1, at, fd, off16 + Register::kMantissaOffset);
2311109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      mfhc1(t8, fd);
2312c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      GenInstrImmediate(SW, at, t8, off16 + Register::kExponentOffset);
2313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
23153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
23163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
23173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
231844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::mtc1(Register rt, FPURegister fs) {
23193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(COP1, MTC1, rt, fs, f0);
23203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
23213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
23223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::mthc1(Register rt, FPURegister fs) {
2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenInstrRegister(COP1, MTHC1, rt, fs, f0);
2325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
232844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::mfc1(Register rt, FPURegister fs) {
232944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, MFC1, rt, fs, f0);
23303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
23313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
23323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::mfhc1(Register rt, FPURegister fs) {
2334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenInstrRegister(COP1, MFHC1, rt, fs, f0);
2335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
233844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::ctc1(Register rt, FPUControlRegister fs) {
233944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, CTC1, rt, fs);
234044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
234144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
234244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
234344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::cfc1(Register rt, FPUControlRegister fs) {
234444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, CFC1, rt, fs);
234544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
234644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2348589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid Assembler::DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) {
2349589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  uint64_t i;
2350589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  memcpy(&i, &d, 8);
2351589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
2352589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  *lo = i & 0xffffffff;
2353589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  *hi = i >> 32;
2354589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
235544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::movn_s(FPURegister fd, FPURegister fs, Register rt) {
2358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!IsMipsArchVariant(kMips32r6));
2359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, S, rt, fs, fd, MOVN_C);
2360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::movn_d(FPURegister fd, FPURegister fs, Register rt) {
2364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!IsMipsArchVariant(kMips32r6));
2365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, D, rt, fs, fd, MOVN_C);
2366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2367014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::sel(SecondaryField fmt, FPURegister fd, FPURegister fs,
2370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    FPURegister ft) {
2371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((fmt == D) || (fmt == S));
2373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, fmt, ft, fs, fd, SEL);
2375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::sel_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  sel(S, fd, fs, ft);
2380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::sel_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  sel(D, fd, fs, ft);
2385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::seleqz(SecondaryField fmt, FPURegister fd, FPURegister fs,
2389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       FPURegister ft) {
2390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((fmt == D) || (fmt == S));
2392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, fmt, ft, fs, fd, SELEQZ_C);
2393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::selnez(Register rd, Register rs, Register rt) {
2397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SELNEZ_S);
2399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::selnez(SecondaryField fmt, FPURegister fd, FPURegister fs,
2403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       FPURegister ft) {
2404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((fmt == D) || (fmt == S));
2406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, fmt, ft, fs, fd, SELNEZ_C);
2407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::seleqz_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  seleqz(D, fd, fs, ft);
2412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::seleqz_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  seleqz(S, fd, fs, ft);
2417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::selnez_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  selnez(D, fd, fs, ft);
2422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::selnez_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  selnez(S, fd, fs, ft);
2427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::movz_s(FPURegister fd, FPURegister fs, Register rt) {
2431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!IsMipsArchVariant(kMips32r6));
2432014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, S, rt, fs, fd, MOVZ_C);
2433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::movz_d(FPURegister fd, FPURegister fs, Register rt) {
2437014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!IsMipsArchVariant(kMips32r6));
2438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, D, rt, fs, fd, MOVZ_C);
2439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2442014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::movt_s(FPURegister fd, FPURegister fs, uint16_t cc) {
2443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!IsMipsArchVariant(kMips32r6));
2444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FPURegister ft;
2445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ft.reg_code = (cc & 0x0007) << 2 | 1;
2446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, S, ft, fs, fd, MOVF);
2447014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::movt_d(FPURegister fd, FPURegister fs, uint16_t cc) {
2451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!IsMipsArchVariant(kMips32r6));
2452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FPURegister ft;
2453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ft.reg_code = (cc & 0x0007) << 2 | 1;
2454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, D, ft, fs, fd, MOVF);
2455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::movf_s(FPURegister fd, FPURegister fs, uint16_t cc) {
2459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!IsMipsArchVariant(kMips32r6));
2460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FPURegister ft;
2461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ft.reg_code = (cc & 0x0007) << 2 | 0;
2462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, S, ft, fs, fd, MOVF);
2463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::movf_d(FPURegister fd, FPURegister fs, uint16_t cc) {
2467014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!IsMipsArchVariant(kMips32r6));
2468014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FPURegister ft;
2469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ft.reg_code = (cc & 0x0007) << 2 | 0;
2470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, D, ft, fs, fd, MOVF);
2471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
247444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Arithmetic.
247544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::add_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, S, ft, fs, fd, ADD_S);
2478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2479014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2480014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
248144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::add_d(FPURegister fd, FPURegister fs, FPURegister ft) {
248244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, D, ft, fs, fd, ADD_D);
248344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
248444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
248544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::sub_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, S, ft, fs, fd, SUB_S);
2488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
249144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::sub_d(FPURegister fd, FPURegister fs, FPURegister ft) {
249244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, D, ft, fs, fd, SUB_D);
249344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
249444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
249544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::mul_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, S, ft, fs, fd, MUL_S);
2498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
250144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) {
250244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, D, ft, fs, fd, MUL_D);
250344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
250444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2505f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::madd_s(FPURegister fd, FPURegister fr, FPURegister fs,
2506f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                       FPURegister ft) {
2507f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r2));
2508f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  GenInstrRegister(COP1X, fr, ft, fs, fd, MADD_S);
2509f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
251044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::madd_d(FPURegister fd, FPURegister fr, FPURegister fs,
2512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FPURegister ft) {
2513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(IsMipsArchVariant(kMips32r2));
2514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenInstrRegister(COP1X, fr, ft, fs, fd, MADD_D);
2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2517f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::msub_s(FPURegister fd, FPURegister fr, FPURegister fs,
2518f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                       FPURegister ft) {
2519f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r2));
2520f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  GenInstrRegister(COP1X, fr, ft, fs, fd, MSUB_S);
2521f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
2522f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
2523f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::msub_d(FPURegister fd, FPURegister fr, FPURegister fs,
2524f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                       FPURegister ft) {
2525f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r2));
2526f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  GenInstrRegister(COP1X, fr, ft, fs, fd, MSUB_D);
2527f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
2528f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
2529f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::maddf_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2530f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2531f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  GenInstrRegister(COP1, S, ft, fs, fd, MADDF_S);
2532f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
2533f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
2534f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::maddf_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2535f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2536f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  GenInstrRegister(COP1, D, ft, fs, fd, MADDF_D);
2537f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
2538f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
2539f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::msubf_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2540f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2541f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  GenInstrRegister(COP1, S, ft, fs, fd, MSUBF_S);
2542f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
2543f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
2544f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Assembler::msubf_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2545f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2546f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  GenInstrRegister(COP1, D, ft, fs, fd, MSUBF_D);
2547f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
2548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::div_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2550014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, S, ft, fs, fd, DIV_S);
2551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
255444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::div_d(FPURegister fd, FPURegister fs, FPURegister ft) {
255544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, D, ft, fs, fd, DIV_D);
255644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
255744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
255844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::abs_s(FPURegister fd, FPURegister fs) {
2560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, S, f0, fs, fd, ABS_S);
2561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2562014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
256444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::abs_d(FPURegister fd, FPURegister fs) {
256544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, D, f0, fs, fd, ABS_D);
25663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
25673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
25683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
256944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::mov_d(FPURegister fd, FPURegister fs) {
257044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, D, f0, fs, fd, MOV_D);
257144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
257244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
257344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::mov_s(FPURegister fd, FPURegister fs) {
2575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, S, f0, fs, fd, MOV_S);
2576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::neg_s(FPURegister fd, FPURegister fs) {
2580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, S, f0, fs, fd, NEG_S);
2581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
258444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::neg_d(FPURegister fd, FPURegister fs) {
258544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, D, f0, fs, fd, NEG_D);
258644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
258744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
258844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::sqrt_s(FPURegister fd, FPURegister fs) {
2590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, S, f0, fs, fd, SQRT_S);
2591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
259444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::sqrt_d(FPURegister fd, FPURegister fs) {
259544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, D, f0, fs, fd, SQRT_D);
25963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
25973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
25983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::rsqrt_s(FPURegister fd, FPURegister fs) {
2600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, S, f0, fs, fd, RSQRT_S);
2602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2605014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::rsqrt_d(FPURegister fd, FPURegister fs) {
2606014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2607014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, D, f0, fs, fd, RSQRT_D);
2608014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2609014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2610014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2611014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::recip_d(FPURegister fd, FPURegister fs) {
2612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, D, f0, fs, fd, RECIP_D);
2614014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2615014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2616014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::recip_s(FPURegister fd, FPURegister fs) {
2618014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, S, f0, fs, fd, RECIP_S);
2620014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2621014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2622014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
26233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Conversions.
26243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
26253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::cvt_w_s(FPURegister fd, FPURegister fs) {
26263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(COP1, S, f0, fs, fd, CVT_W_S);
26273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
26283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
26293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
26303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::cvt_w_d(FPURegister fd, FPURegister fs) {
26313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(COP1, D, f0, fs, fd, CVT_W_D);
26323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
26333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
26343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
263544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::trunc_w_s(FPURegister fd, FPURegister fs) {
263644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_W_S);
263744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
263844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
263944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
264044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::trunc_w_d(FPURegister fd, FPURegister fs) {
264144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_W_D);
264244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
264344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
264444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
264544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::round_w_s(FPURegister fd, FPURegister fs) {
264644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, S, f0, fs, fd, ROUND_W_S);
264744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
264844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
264944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
265044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::round_w_d(FPURegister fd, FPURegister fs) {
265144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, D, f0, fs, fd, ROUND_W_D);
265244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
265344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
265444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
265544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::floor_w_s(FPURegister fd, FPURegister fs) {
265644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_W_S);
265744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
265844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
265944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
266044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::floor_w_d(FPURegister fd, FPURegister fs) {
266144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_W_D);
266244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
266344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
266444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
266544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::ceil_w_s(FPURegister fd, FPURegister fs) {
266644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, S, f0, fs, fd, CEIL_W_S);
266744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
266844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
266944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
267044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::ceil_w_d(FPURegister fd, FPURegister fs) {
267144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, D, f0, fs, fd, CEIL_W_D);
267244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
267344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
267444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::rint_s(FPURegister fd, FPURegister fs) { rint(S, fd, fs); }
2676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::rint(SecondaryField fmt, FPURegister fd, FPURegister fs) {
2679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((fmt == D) || (fmt == S));
2681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, fmt, f0, fs, fd, RINT);
2682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::rint_d(FPURegister fd, FPURegister fs) { rint(D, fd, fs); }
2686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
26883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::cvt_l_s(FPURegister fd, FPURegister fs) {
2689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
2690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         IsFp64Mode());
26913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S);
26923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
26933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
26943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
26953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::cvt_l_d(FPURegister fd, FPURegister fs) {
2696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
2697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         IsFp64Mode());
26983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(COP1, D, f0, fs, fd, CVT_L_D);
26993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
27003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
27013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
270244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::trunc_l_s(FPURegister fd, FPURegister fs) {
2703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
2704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         IsFp64Mode());
270544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_L_S);
270644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
270744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
270844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
270944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::trunc_l_d(FPURegister fd, FPURegister fs) {
2710014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
2711014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         IsFp64Mode());
271244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_L_D);
271344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
271444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
271544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
271644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::round_l_s(FPURegister fd, FPURegister fs) {
2717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
2718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         IsFp64Mode());
271944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, S, f0, fs, fd, ROUND_L_S);
272044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
272144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
272244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
272344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::round_l_d(FPURegister fd, FPURegister fs) {
2724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
2725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         IsFp64Mode());
272644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, D, f0, fs, fd, ROUND_L_D);
272744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
272844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
272944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
273044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::floor_l_s(FPURegister fd, FPURegister fs) {
2731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
2732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         IsFp64Mode());
273344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_L_S);
273444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
273544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
273644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
273744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::floor_l_d(FPURegister fd, FPURegister fs) {
2738014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
2739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         IsFp64Mode());
274044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_L_D);
274144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
274244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
274344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
274444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::ceil_l_s(FPURegister fd, FPURegister fs) {
2745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
2746014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         IsFp64Mode());
274744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, S, f0, fs, fd, CEIL_L_S);
274844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
274944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
275044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
275144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::ceil_l_d(FPURegister fd, FPURegister fs) {
2752014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
2753014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         IsFp64Mode());
275444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenInstrRegister(COP1, D, f0, fs, fd, CEIL_L_D);
275544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
275644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
275744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2758014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::class_s(FPURegister fd, FPURegister fs) {
2759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2760014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, S, f0, fs, fd, CLASS_S);
2761014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2762014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::class_d(FPURegister fd, FPURegister fs) {
2765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenInstrRegister(COP1, D, f0, fs, fd, CLASS_D);
2767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2769014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2770014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::min(SecondaryField fmt, FPURegister fd, FPURegister fs,
2771014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    FPURegister ft) {
2772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((fmt == D) || (fmt == S));
2774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenInstrRegister(COP1, fmt, ft, fs, fd, MIN);
2775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::mina(SecondaryField fmt, FPURegister fd, FPURegister fs,
2779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     FPURegister ft) {
2780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((fmt == D) || (fmt == S));
2782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenInstrRegister(COP1, fmt, ft, fs, fd, MINA);
2783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::max(SecondaryField fmt, FPURegister fd, FPURegister fs,
2787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    FPURegister ft) {
2788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((fmt == D) || (fmt == S));
2790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenInstrRegister(COP1, fmt, ft, fs, fd, MAX);
2791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::maxa(SecondaryField fmt, FPURegister fd, FPURegister fs,
2795014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     FPURegister ft) {
2796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((fmt == D) || (fmt == S));
2798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenInstrRegister(COP1, fmt, ft, fs, fd, MAXA);
2799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2802014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::min_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  min(S, fd, fs, ft);
2804014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2806014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2807014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::min_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2808014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  min(D, fd, fs, ft);
2809014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2810014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2811014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2812014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::max_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2813014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  max(S, fd, fs, ft);
2814014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::max_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  max(D, fd, fs, ft);
2819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::mina_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mina(S, fd, fs, ft);
2824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::mina_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  mina(D, fd, fs, ft);
2829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2831014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::maxa_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  maxa(S, fd, fs, ft);
2834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2835014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2837014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::maxa_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2838014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  maxa(D, fd, fs, ft);
2839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
28423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::cvt_s_w(FPURegister fd, FPURegister fs) {
28433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W);
28443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
28453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::cvt_s_l(FPURegister fd, FPURegister fs) {
2848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
2849014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         IsFp64Mode());
28503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L);
28513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
28523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::cvt_s_d(FPURegister fd, FPURegister fs) {
28553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(COP1, D, f0, fs, fd, CVT_S_D);
28563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
28573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::cvt_d_w(FPURegister fd, FPURegister fs) {
28603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(COP1, W, f0, fs, fd, CVT_D_W);
28613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
28623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::cvt_d_l(FPURegister fd, FPURegister fs) {
2865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
2866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         IsFp64Mode());
28673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L);
28683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
28693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::cvt_d_s(FPURegister fd, FPURegister fs) {
28723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S);
28733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
28743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Conditions for >= MIPSr6.
2877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::cmp(FPUCondition cond, SecondaryField fmt,
2878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FPURegister fd, FPURegister fs, FPURegister ft) {
2879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((fmt & ~(31 << kRsShift)) == 0);
2881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Instr instr = COP1 | fmt | ft.code() << kFtShift |
2882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      fs.code() << kFsShift | fd.code() << kFdShift | (0 << 5) | cond;
2883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(instr);
2884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::cmp_s(FPUCondition cond, FPURegister fd, FPURegister fs,
2888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      FPURegister ft) {
2889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(cond, W, fd, fs, ft);
2890014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::cmp_d(FPUCondition cond, FPURegister fd, FPURegister fs,
2893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      FPURegister ft) {
2894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cmp(cond, L, fd, fs, ft);
2895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bc1eqz(int16_t offset, FPURegister ft) {
2899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Instr instr = COP1 | BC1EQZ | ft.code() << kFtShift | (offset & kImm16Mask);
2901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(instr);
2902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bc1nez(int16_t offset, FPURegister ft) {
2906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsMipsArchVariant(kMips32r6));
2907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Instr instr = COP1 | BC1NEZ | ft.code() << kFtShift | (offset & kImm16Mask);
2908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emit(instr);
2909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Conditions for < MIPSr6.
29133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::c(FPUCondition cond, SecondaryField fmt,
291444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    FPURegister fs, FPURegister ft, uint16_t cc) {
2915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint3(cc));
2916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(fmt == S || fmt == D);
2917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((fmt & ~(31 << kRsShift)) == 0);
29183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift
29193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      | cc << 8 | 3 << 4 | cond;
29203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  emit(instr);
29213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
29223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
29233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::c_s(FPUCondition cond, FPURegister fs, FPURegister ft,
2925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    uint16_t cc) {
2926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  c(cond, S, fs, ft, cc);
2927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::c_d(FPUCondition cond, FPURegister fs, FPURegister ft,
2931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    uint16_t cc) {
2932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  c(cond, D, fs, ft, cc);
2933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
293644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::fcmp(FPURegister src1, const double src2,
293744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      FPUCondition cond) {
2938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(src2 == 0.0);
293944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mtc1(zero_reg, f14);
294044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  cvt_d_w(f14, f14);
294144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  c(cond, D, src1, f14, 0);
294244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
294344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
294444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
29453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bc1f(int16_t offset, uint16_t cc) {
2946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint3(cc));
29473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask);
29483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  emit(instr);
29493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
29503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
29513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
29523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::bc1t(int16_t offset, uint16_t cc) {
2953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint3(cc));
29543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask);
29553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  emit(instr);
29563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
29573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
29583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochint Assembler::RelocateInternalReference(RelocInfo::Mode rmode, byte* pc,
2960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                         intptr_t pc_delta) {
29613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Instr instr = instr_at(pc);
29623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (RelocInfo::IsInternalReference(rmode)) {
2964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int32_t* p = reinterpret_cast<int32_t*>(pc);
2965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (*p == 0) {
29663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return 0;  // Number of instructions patched.
29673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    *p += pc_delta;
2969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return 1;  // Number of instructions patched.
2970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(RelocInfo::IsInternalReferenceEncoded(rmode));
2972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (IsLui(instr)) {
29733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Instr instr1 = instr_at(pc + 0 * Assembler::kInstrSize);
29743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Instr instr2 = instr_at(pc + 1 * Assembler::kInstrSize);
29753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      DCHECK(IsOri(instr2) || IsJicOrJialc(instr2));
29763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      int32_t imm;
29773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (IsJicOrJialc(instr2)) {
29783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        imm = CreateTargetAddress(instr1, instr2);
29793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      } else {
29803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        imm = (instr1 & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
29813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        imm |= (instr2 & static_cast<int32_t>(kImm16Mask));
29823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
29833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (imm == kEndOfJumpChain) {
2985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return 0;  // Number of instructions patched.
2986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
2987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      imm += pc_delta;
2988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK((imm & 3) == 0);
29893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      instr1 &= ~kImm16Mask;
29903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      instr2 &= ~kImm16Mask;
29913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
29923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (IsJicOrJialc(instr2)) {
29933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        uint32_t lui_offset_u, jic_offset_u;
29943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Assembler::UnpackTargetAddressUnsigned(imm, lui_offset_u, jic_offset_u);
29953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        instr_at_put(pc + 0 * Assembler::kInstrSize, instr1 | lui_offset_u);
29963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        instr_at_put(pc + 1 * Assembler::kInstrSize, instr2 | jic_offset_u);
29973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      } else {
29983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        instr_at_put(pc + 0 * Assembler::kInstrSize,
29993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                     instr1 | ((imm >> kLuiShift) & kImm16Mask));
30003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        instr_at_put(pc + 1 * Assembler::kInstrSize,
30013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                     instr2 | (imm & kImm16Mask));
30023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
3003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return 2;  // Number of instructions patched.
3004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
3005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      UNREACHABLE();
3006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return 0;
3007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
30083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
30093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
30103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
30113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
30123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::GrowBuffer() {
30133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (!own_buffer_) FATAL("external code buffer is too small");
30143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
30153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Compute new buffer size.
301644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CodeDesc desc;  // The new buffer.
3017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (buffer_size_ < 1 * MB) {
30183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    desc.buffer_size = 2*buffer_size_;
30193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
30203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    desc.buffer_size = buffer_size_ + 1*MB;
30213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
302244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_GT(desc.buffer_size, 0);  // No overflow.
30233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
30243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up new buffer.
30253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  desc.buffer = NewArray<byte>(desc.buffer_size);
3026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  desc.origin = this;
30273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
30283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  desc.instr_size = pc_offset();
30293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
30303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
30313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Copy the data.
30323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  int pc_delta = desc.buffer - buffer_;
30333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
3034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemMove(desc.buffer, buffer_, desc.instr_size);
3035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemMove(reloc_info_writer.pos() + rc_delta, reloc_info_writer.pos(),
3036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          desc.reloc_size);
30373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
30383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Switch buffers.
30393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  DeleteArray(buffer_);
30403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  buffer_ = desc.buffer;
30413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  buffer_size_ = desc.buffer_size;
30423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  pc_ += pc_delta;
30433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
30443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                               reloc_info_writer.last_pc() + pc_delta);
30453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
30463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Relocate runtime entries.
30473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (RelocIterator it(desc); !it.done(); it.next()) {
30483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    RelocInfo::Mode rmode = it.rinfo()->rmode();
3049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (rmode == RelocInfo::INTERNAL_REFERENCE_ENCODED ||
3050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        rmode == RelocInfo::INTERNAL_REFERENCE) {
30513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      byte* p = reinterpret_cast<byte*>(it.rinfo()->pc());
3052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      RelocateInternalReference(rmode, p, pc_delta);
30533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
30543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
3055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!overflow());
30563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
30573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
30583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
305944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::db(uint8_t data) {
3060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CheckForEmitInForbiddenSlot();
3061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EmitHelper(data);
306244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
306344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
306444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
306544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::dd(uint32_t data) {
3066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CheckForEmitInForbiddenSlot();
3067014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EmitHelper(data);
306844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
306944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
307044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3071014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::dq(uint64_t data) {
3072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CheckForEmitInForbiddenSlot();
3073014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EmitHelper(data);
3074014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3075014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3077014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::dd(Label* label) {
3078014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t data;
3079014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CheckForEmitInForbiddenSlot();
3080014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (label->is_bound()) {
3081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    data = reinterpret_cast<uint32_t>(buffer_ + label->pos());
3082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    data = jump_address(label);
3084bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    unbound_labels_count_++;
3085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    internal_reference_positions_.insert(label->pos());
3086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
3088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EmitHelper(data);
3089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
30923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
30933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We do not try to reuse pool constants.
3094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  RelocInfo rinfo(isolate(), pc_, rmode, data, NULL);
3095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (rmode >= RelocInfo::COMMENT &&
30963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      rmode <= RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL) {
30973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Adjust code for new modes.
3098f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK(RelocInfo::IsDebugBreakSlot(rmode) || RelocInfo::IsComment(rmode));
30993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // These modes do not need an entry in the constant pool.
31003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
3101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!RelocInfo::IsNone(rinfo.rmode())) {
31023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Don't record external references unless the heap will be serialized.
3103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
3104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        !serializer_enabled() && !emit_debug_code()) {
3105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
31063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
3107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(buffer_space() >= kMaxRelocSize);  // Too late to grow buffer here.
3108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
3109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      RelocInfo reloc_info_with_ast_id(isolate(), pc_, rmode,
3110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       RecordedAstId().ToInt(), NULL);
31113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ClearRecordedAstId();
3112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      reloc_info_writer.Write(&reloc_info_with_ast_id);
3113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
3114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      reloc_info_writer.Write(&rinfo);
3115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
31163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
31173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
31183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
31193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
312044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::BlockTrampolinePoolFor(int instructions) {
3121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CheckTrampolinePoolQuick(instructions);
312244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize);
312344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
312444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
312544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
31263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Assembler::CheckTrampolinePool() {
312744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Some small sequences of instructions must not be broken up by the
312844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // insertion of a trampoline pool; such sequences are protected by setting
312944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_,
313044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // which are both checked here. Also, recursive calls to CheckTrampolinePool
313144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // are blocked by trampoline_pool_blocked_nesting_.
313244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if ((trampoline_pool_blocked_nesting_ > 0) ||
313344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      (pc_offset() < no_trampoline_pool_before_)) {
313444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Emission is currently blocked; make sure we try again as soon as
313544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // possible.
313644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (trampoline_pool_blocked_nesting_ > 0) {
313744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      next_buffer_check_ = pc_offset() + kInstrSize;
313844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else {
313944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      next_buffer_check_ = no_trampoline_pool_before_;
314044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
314144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return;
314244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
314344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!trampoline_emitted_);
3145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(unbound_labels_count_ >= 0);
31463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (unbound_labels_count_ > 0) {
31473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // First we emit jump (2 instructions), then we emit trampoline pool.
31483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    { BlockTrampolinePoolScope block_trampoline_pool(this);
31493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Label after_pool;
3150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (IsMipsArchVariant(kMips32r6)) {
3151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bc(&after_pool);
3152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
3153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        b(&after_pool);
3154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        nop();
3155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
31563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
31573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int pool_start = pc_offset();
31583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (IsMipsArchVariant(kMips32r6)) {
31593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        for (int i = 0; i < unbound_labels_count_; i++) {
31603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          uint32_t imm32;
31613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          imm32 = jump_address(&after_pool);
31623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          uint32_t lui_offset, jic_offset;
31633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          UnpackTargetAddressUnsigned(imm32, lui_offset, jic_offset);
31643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          {
31653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            BlockGrowBufferScope block_buf_growth(this);
31663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            // Buffer growth (and relocation) must be blocked for internal
31673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            // references until associated instructions are emitted and
31683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            // available to be patched.
31693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
31703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            lui(at, lui_offset);
31713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            jic(at, jic_offset);
31723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          }
31733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          CheckBuffer();
31743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        }
31753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      } else {
31763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        for (int i = 0; i < unbound_labels_count_; i++) {
31773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          uint32_t imm32;
31783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          imm32 = jump_address(&after_pool);
31793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          {
31803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            BlockGrowBufferScope block_buf_growth(this);
31813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            // Buffer growth (and relocation) must be blocked for internal
31823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            // references until associated instructions are emitted and
31833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            // available to be patched.
31843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
31853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            lui(at, (imm32 & kHiMask) >> kLuiShift);
31863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            ori(at, at, (imm32 & kImm16Mask));
31873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          }
31883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          CheckBuffer();
31893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          jr(at);
31903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          nop();
31913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
31923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
31933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      bind(&after_pool);
31943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      trampoline_ = Trampoline(pool_start, unbound_labels_count_);
31953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
31963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      trampoline_emitted_ = true;
31973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // As we are only going to emit trampoline once, we need to prevent any
31983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // further emission.
31993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      next_buffer_check_ = kMaxInt;
320044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
32013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
32023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Number of branches to unbound label at this point is zero, so we can
32033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // move next buffer check to maximum.
32043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    next_buffer_check_ = pc_offset() +
32053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        kMaxBranchOffset - kTrampolineSlotsSize * 16;
320644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
320744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return;
320844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
320944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
321044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
32113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuAddress Assembler::target_address_at(Address pc) {
32123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr instr1 = instr_at(pc);
32133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr instr2 = instr_at(pc + kInstrSize);
3214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Interpret 2 instructions generated by li: lui/ori
32153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (IsLui(instr1) && IsOri(instr2)) {
3216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Assemble the 32 bit value.
32173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    return reinterpret_cast<Address>((GetImmediate16(instr1) << kLuiShift) |
32183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                     GetImmediate16(instr2));
32193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
32203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We should never get here, force a bad address if we do.
32223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  UNREACHABLE();
32233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  return (Address)0x0;
32243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
32253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
32263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3227db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// MIPS and ia32 use opposite encoding for qNaN and sNaN, such that ia32
3228db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// qNaN is a MIPS sNaN, and ia32 sNaN is MIPS qNaN. If running from a heap
3229db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// snapshot generated on ia32, the resulting MIPS sNaN must be quieted.
3230db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch// OS::nan_value() returns a qNaN.
3231db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdochvoid Assembler::QuietNaN(HeapObject* object) {
3232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HeapNumber::cast(object)->set_value(std::numeric_limits<double>::quiet_NaN());
3233db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch}
3234db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch
3235db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch
3236589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// On Mips, a target address is stored in a lui/ori instruction pair, each
3237589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// of which load 16 bits of the 32-bit address to a register.
3238589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// Patching the address must replace both instr, and flush the i-cache.
32393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// On r6, target address is stored in a lui/jic pair, and both instr have to be
32403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// patched.
3241589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch//
3242589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// There is an optimization below, which emits a nop when the address
3243589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// fits in just 16 bits. This is unlikely to help, and should be benchmarked,
3244589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// and possibly removed.
3245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::set_target_address_at(Isolate* isolate, Address pc,
3246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Address target,
3247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      ICacheFlushMode icache_flush_mode) {
32483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr instr2 = instr_at(pc + kInstrSize);
3249589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  uint32_t rt_code = GetRtField(instr2);
3250589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  uint32_t* p = reinterpret_cast<uint32_t*>(pc);
3251589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  uint32_t itarget = reinterpret_cast<uint32_t>(target);
3252589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
32533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#ifdef DEBUG
3254589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Check we have the result from a li macro-instruction, using instr pair.
32553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Instr instr1 = instr_at(pc);
32563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  CHECK(IsLui(instr1) && (IsOri(instr2) || IsJicOrJialc(instr2)));
32573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#endif
32583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
32593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (IsJicOrJialc(instr2)) {
32603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // Must use 2 instructions to insure patchable code => use lui and jic
32613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    uint32_t lui_offset, jic_offset;
32623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Assembler::UnpackTargetAddressUnsigned(itarget, lui_offset, jic_offset);
32633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
32643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    *p &= ~kImm16Mask;
32653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    *(p + 1) &= ~kImm16Mask;
32663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
32673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    *p |= lui_offset;
32683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    *(p + 1) |= jic_offset;
32693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
32703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
32713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // Must use 2 instructions to insure patchable code => just use lui and ori.
32723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // lui rt, upper-16.
32733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // ori rt rt, lower-16.
32743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift);
32753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    *(p + 1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask);
32763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
3277589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
3278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
3279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Assembler::FlushICache(isolate, pc, 2 * sizeof(int32_t));
3280589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
3281589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
32823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
3284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
32853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_MIPS
3287