1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright (c) 1994-2006 Sun Microsystems Inc.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// All Rights Reserved.
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Redistribution and use in source and binary forms, with or without
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// modification, are permitted provided that the following conditions are
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// met:
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// - Redistributions of source code must retain the above copyright notice,
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// this list of conditions and the following disclaimer.
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// - Redistribution in binary form must reproduce the above copyright
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// notice, this list of conditions and the following disclaimer in the
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// documentation and/or other materials provided with the distribution.
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// - Neither the name of Sun Microsystems or the names of contributors may
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// be used to endorse or promote products derived from this software without
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// specific prior written permission.
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The original source code covered by the above license above has been
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// modified significantly by Google Inc.
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_MIPS_ASSEMBLER_MIPS_H_
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define V8_MIPS_ASSEMBLER_MIPS_H_
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <stdio.h>
40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include <set>
42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/assembler.h"
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/mips64/constants-mips64.h"
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// clang-format off
50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define GENERAL_REGISTERS(V)                              \
51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(zero_reg)  V(at)  V(v0)  V(v1)  V(a0)  V(a1)  V(a2)  V(a3)  \
52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(a4)  V(a5)  V(a6)  V(a7)  V(t0)  V(t1)  V(t2)  V(t3)  \
53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(s0)  V(s1)  V(s2)  V(s3)  V(s4)  V(s5)  V(s6)  V(s7)  V(t8)  V(t9) \
54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(k0)  V(k1)  V(gp)  V(sp)  V(fp)  V(ra)
55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define ALLOCATABLE_GENERAL_REGISTERS(V) \
57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(v0)  V(v1)  V(a0)  V(a1)  V(a2)  V(a3) \
58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(a4)  V(a5)  V(a6)  V(a7)  V(t0)  V(t1)  V(t2) V(s7)
59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define DOUBLE_REGISTERS(V)                               \
61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(f0)  V(f1)  V(f2)  V(f3)  V(f4)  V(f5)  V(f6)  V(f7)  \
62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(f8)  V(f9)  V(f10) V(f11) V(f12) V(f13) V(f14) V(f15) \
63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(f16) V(f17) V(f18) V(f19) V(f20) V(f21) V(f22) V(f23) \
64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(f24) V(f25) V(f26) V(f27) V(f28) V(f29) V(f30) V(f31)
65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define ALLOCATABLE_DOUBLE_REGISTERS(V)                   \
67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(f0)  V(f2)  V(f4)  V(f6)  V(f8)  V(f10) V(f12) V(f14) \
68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V(f16) V(f18) V(f20) V(f22) V(f24) V(f26)
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// clang-format on
70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// CPU Registers.
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 1) We would prefer to use an enum, but enum values are assignment-
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// compatible with int, which has caused code-generation bugs.
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 2) We would prefer to use a class instead of a struct but we don't like
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the register initialization to depend on the particular initialization
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// order (which appears to be different on OS X, Linux, and Windows for the
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// installed versions of C++ we tried). Using a struct permits C-style
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// "initialization". Also, the Register objects cannot be const as this
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// forces initialization stubs in MSVC, making us dependent on initialization
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// order.
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 3) By not using an enum, we are possibly preventing the compiler from
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// doing certain constant folds, which may significantly reduce the
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// code generated for some assembly instructions (because they boil down
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// to a few constants). If this is a problem, we could change the code
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// such that we use an enum in optimized mode, and the struct in debug
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// mode. This way we get the compile-time error checking in debug mode
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// and best performance in optimized code.
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// -----------------------------------------------------------------------------
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Implementation of Register and FPURegister.
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct Register {
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kCpRegister = 23;  // cp (s7) is the 23rd register.
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#if defined(V8_TARGET_LITTLE_ENDIAN)
100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kMantissaOffset = 0;
101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kExponentOffset = 4;
102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#elif defined(V8_TARGET_BIG_ENDIAN)
103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kMantissaOffset = 4;
104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kExponentOffset = 0;
105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#else
106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#error Unknown endianness
107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif
108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  enum Code {
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define REGISTER_CODE(R) kCode_##R,
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    GENERAL_REGISTERS(REGISTER_CODE)
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef REGISTER_CODE
113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        kAfterLast,
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    kCode_no_reg = -1
115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  };
116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kNumRegisters = Code::kAfterLast;
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static Register from_code(int code) {
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(code >= 0);
121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(code < kNumRegisters);
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register r = { code };
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return r;
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const char* ToString();
127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool IsAllocatable() const;
128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is(Register reg) const { return reg_code == reg.reg_code; }
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int code() const {
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(is_valid());
132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return reg_code;
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int bit() const {
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(is_valid());
136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return 1 << reg_code;
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Unfortunately we can't make this private in a struct.
140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int reg_code;
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// s7: context register
144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// s3: lithium scratch
145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// s4: lithium scratch2
146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochGENERAL_REGISTERS(DECLARE_REGISTER)
148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef DECLARE_REGISTER
149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register no_reg = {Register::kCode_no_reg};
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint ToNumber(Register reg);
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister ToRegister(int num);
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Coprocessor register.
157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstruct DoubleRegister {
158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  enum Code {
159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define REGISTER_CODE(R) kCode_##R,
160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DOUBLE_REGISTERS(REGISTER_CODE)
161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef REGISTER_CODE
162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        kAfterLast,
163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    kCode_no_reg = -1
164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  };
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kMaxNumRegisters = Code::kAfterLast;
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline static int NumRegisters();
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // TODO(plind): Warning, inconsistent numbering here. kNumFPURegisters refers
171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to
172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // number of Double regs (64-bit regs, or FPU-reg-pairs).
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const char* ToString();
175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool IsAllocatable() const;
176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DoubleRegister low() const {
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // TODO(plind): Create DCHECK for FR=0 mode. This usage suspect for FR=1.
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Find low reg of a Double-reg pair, which is the reg itself.
181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(reg_code % 2 == 0);  // Specified Double reg must be even.
182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DoubleRegister reg;
183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    reg.reg_code = reg_code;
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(reg.is_valid());
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return reg;
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DoubleRegister high() const {
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // TODO(plind): Create DCHECK for FR=0 mode. This usage illegal in FR=1.
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Find high reg of a Doubel-reg pair, which is reg + 1.
190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(reg_code % 2 == 0);  // Specified Double reg must be even.
191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DoubleRegister reg;
192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    reg.reg_code = reg_code + 1;
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(reg.is_valid());
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return reg;
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int code() const {
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(is_valid());
199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return reg_code;
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int bit() const {
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(is_valid());
203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return 1 << reg_code;
204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static DoubleRegister from_code(int code) {
207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DoubleRegister r = {code};
208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return r;
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void setcode(int f) {
211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    reg_code = f;
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(is_valid());
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Unfortunately we can't make this private in a struct.
215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int reg_code;
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// A few double registers are reserved: one as a scratch register and one to
219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// hold 0.0.
220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//  f28: 0.0
221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//  f30: scratch register.
222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// V8 now supports the O32 ABI, and the FPU Registers are organized as 32
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 32-bit registers, f0 through f31. When used as 'double' they are used
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// in pairs, starting with the even numbered register. So a double operation
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// on f0 really uses f0 and f1.
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// (Modern mips hardware also supports 32 64-bit registers, via setting
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// (privileged) Status Register FR bit to 1. This is used by the N32 ABI,
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// but it is not in common use. Someday we will want to support this in v8.)
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// For O32 ABI, Floats and Doubles refer to same set of 32 32-bit registers.
232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtypedef DoubleRegister FPURegister;
233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtypedef DoubleRegister FloatRegister;
234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister no_freg = {-1};
236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f0 = {0};  // Return value in hard float mode.
238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f1 = {1};
239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f2 = {2};
240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f3 = {3};
241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f4 = {4};
242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f5 = {5};
243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f6 = {6};
244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f7 = {7};
245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f8 = {8};
246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f9 = {9};
247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f10 = {10};
248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f11 = {11};
249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f12 = {12};  // Arg 0 in hard float mode.
250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f13 = {13};
251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f14 = {14};  // Arg 1 in hard float mode.
252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f15 = {15};
253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f16 = {16};
254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f17 = {17};
255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f18 = {18};
256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f19 = {19};
257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f20 = {20};
258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f21 = {21};
259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f22 = {22};
260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f23 = {23};
261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f24 = {24};
262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f25 = {25};
263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f26 = {26};
264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f27 = {27};
265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f28 = {28};
266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f29 = {29};
267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f30 = {30};
268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst DoubleRegister f31 = {31};
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Register aliases.
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// cp is assumed to be a callee saved register.
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Defined using #define instead of "static const Register&" because Clang
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// complains otherwise when a compilation unit that includes this header
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// doesn't use the variables.
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define kRootRegister s6
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define cp s7
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define kLithiumScratchReg s3
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define kLithiumScratchReg2 s4
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define kLithiumScratchDouble f30
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define kDoubleRegZero f28
281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Used on mips64r6 for compare operations.
282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// We use the last non-callee saved odd register for N64 ABI
283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define kDoubleCompareReg f23
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// FPU (coprocessor 1) control registers.
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Currently only FCSR (#31) is implemented.
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct FPUControlRegister {
288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is_valid() const { return reg_code == kFCSRRegister; }
289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is(FPUControlRegister creg) const { return reg_code == creg.reg_code; }
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int code() const {
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(is_valid());
292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return reg_code;
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int bit() const {
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(is_valid());
296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return 1 << reg_code;
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void setcode(int f) {
299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    reg_code = f;
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(is_valid());
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Unfortunately we can't make this private in a struct.
303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int reg_code;
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPUControlRegister no_fpucreg = { kInvalidFPUControlRegister };
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst FPUControlRegister FCSR = { kFCSRRegister };
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// -----------------------------------------------------------------------------
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Machine instruction Operands.
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst int kSmiShift = kSmiTagSize + kSmiShiftSize;
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst uint64_t kSmiShiftMask = (1UL << kSmiShift) - 1;
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Class Operand represents a shifter operand in data processing instructions.
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass Operand BASE_EMBEDDED {
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Immediate.
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(explicit Operand(int64_t immediate,
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         RelocInfo::Mode rmode = RelocInfo::NONE64));
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(explicit Operand(const ExternalReference& f));
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(explicit Operand(const char* s));
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(explicit Operand(Object** opp));
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(explicit Operand(Context** cpp));
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit Operand(Handle<Object> handle);
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(explicit Operand(Smi* value));
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Register.
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(explicit Operand(Register rm));
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Return true if this is a register operand.
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(bool is_reg() const);
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline int64_t immediate() const {
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!is_reg());
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return imm64_;
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register rm() const { return rm_; }
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register rm_;
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int64_t imm64_;  // Valid if rm_ == no_reg.
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RelocInfo::Mode rmode_;
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class Assembler;
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class MacroAssembler;
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// On MIPS we have only one adressing mode with base_reg + offset.
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Class MemOperand represents a memory operand in load and store instructions.
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass MemOperand : public Operand {
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Immediate value attached to offset.
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum OffsetAddend {
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    offset_minus_one = -1,
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    offset_zero = 0
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit MemOperand(Register rn, int32_t offset = 0);
361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit MemOperand(Register rn, int32_t unit, int32_t multiplier,
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      OffsetAddend offset_addend = offset_zero);
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t offset() const { return offset_; }
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool OffsetIsInt16Encodable() const {
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return is_int16(offset_);
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t offset_;
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class Assembler;
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass Assembler : public AssemblerBase {
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create an assembler. Instructions and relocation information are emitted
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // into a buffer, with the instructions starting from the beginning and the
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // relocation information starting from the end of the buffer. See CodeDesc
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // for a detailed comment on the layout (globals.h).
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the provided buffer is NULL, the assembler allocates and grows its own
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // buffer, and buffer_size determines the initial buffer size. The buffer is
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // owned by the assembler and deallocated upon destruction of the assembler.
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the provided buffer is not NULL, the assembler uses the provided buffer
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // for code generation and assumes its size to be buffer_size. If the buffer
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // is too small, a fatal error occurs. No deallocation of the buffer is done
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // upon destruction of the assembler.
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler(Isolate* isolate, void* buffer, int buffer_size);
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual ~Assembler() { }
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // GetCode emits any pending (non-emitted) code and fills the descriptor
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // desc. GetCode() is idempotent; it returns the same result if no other
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Assembler functions are invoked in between GetCode() calls.
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void GetCode(CodeDesc* desc);
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Label operations & relative jumps (PPUM Appendix D).
400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Takes a branch opcode (cc) and a label (L) and generates
402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // either a backward branch or a forward branch and links it
403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to the label fixup chain. Usage:
404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Label L;    // unbound label
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // j(cc, &L);  // forward branch to unbound label
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // bind(&L);   // bind label to the current pc
408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // j(cc, &L);  // backward branch to bound label
409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // bind(&L);   // illegal: a label may be bound only once
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Note: The same Label can be used for forward and backward branches
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // but it may be bound only once.
413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bind(Label* L);  // Binds an unbound label L to current code position.
414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  enum OffsetSize : int { kOffset26 = 26, kOffset21 = 21, kOffset16 = 16 };
416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Determines if Label is bound and near enough so that branch instruction
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // can be used to reach it, instead of jump instruction.
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool is_near(Label* L);
420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is_near(Label* L, OffsetSize bits);
421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is_near_branch(Label* L);
422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline bool is_near_pre_r6(Label* L) {
423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!(kArchVariant == kMips64r6));
424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return pc_offset() - L->pos() < kMaxBranchOffset - 4 * kInstrSize;
425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline bool is_near_r6(Label* L) {
427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(kArchVariant == kMips64r6);
428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return pc_offset() - L->pos() < kMaxCompactBranchOffset - 4 * kInstrSize;
429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int BranchOffset(Instr instr);
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Returns the branch offset to the given label from the current code
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // position. Links the label to the current position if it is still unbound.
435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Manages the jump elimination optimization if the second parameter is true.
436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int32_t branch_offset_helper(Label* L, OffsetSize bits);
437014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline int32_t branch_offset(Label* L) {
438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return branch_offset_helper(L, OffsetSize::kOffset16);
439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline int32_t branch_offset21(Label* L) {
441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return branch_offset_helper(L, OffsetSize::kOffset21);
442014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline int32_t branch_offset26(Label* L) {
444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return branch_offset_helper(L, OffsetSize::kOffset26);
445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline int32_t shifted_branch_offset(Label* L) {
447014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return branch_offset(L) >> 2;
448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline int32_t shifted_branch_offset21(Label* L) {
450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return branch_offset21(L) >> 2;
451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline int32_t shifted_branch_offset26(Label* L) {
453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return branch_offset26(L) >> 2;
454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint64_t jump_address(Label* L);
456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint64_t jump_offset(Label* L);
457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Puts a labels target address at the given position.
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The high 8 bits are set to zero.
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void label_at_put(Label* L, int at_offset);
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Read/Modify the code target address in the branch/call instruction at pc.
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static Address target_address_at(Address pc);
464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static void set_target_address_at(
465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Isolate* isolate, Address pc, Address target,
466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // On MIPS there is no Constant Pool so we skip that parameter.
468014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  INLINE(static Address target_address_at(Address pc, Address constant_pool)) {
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return target_address_at(pc);
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  INLINE(static void set_target_address_at(
472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Isolate* isolate, Address pc, Address constant_pool, Address target,
473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)) {
474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    set_target_address_at(isolate, pc, target, icache_flush_mode);
475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static Address target_address_at(Address pc, Code* code)) {
477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Address constant_pool = code ? code->constant_pool() : NULL;
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return target_address_at(pc, constant_pool);
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
480014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  INLINE(static void set_target_address_at(
481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Isolate* isolate, Address pc, Code* code, Address target,
482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)) {
483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Address constant_pool = code ? code->constant_pool() : NULL;
484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    set_target_address_at(isolate, pc, constant_pool, target,
485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                          icache_flush_mode);
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Return the code target address at a call site from the return address
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // of that call in the instruction stream.
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline static Address target_address_from_return_address(Address pc);
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void JumpLabelToJumpRegister(Address pc);
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void QuietNaN(HeapObject* nan);
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This sets the branch destination (which gets loaded at the call address).
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This is for calls and branches within generated code.  The serializer
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // has already deserialized the lui/ori instructions etc.
499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline static void deserialization_set_special_target_at(
500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Isolate* isolate, Address instruction_payload, Code* code,
501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Address target) {
502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_target_address_at(
503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        isolate,
504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        instruction_payload - kInstructionsFor64BitConstant * kInstrSize, code,
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        target);
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // This sets the internal reference at the pc.
509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline static void deserialization_set_target_internal_reference_at(
510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Isolate* isolate, Address pc, Address target,
511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Size of an instruction.
514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kInstrSize = sizeof(Instr);
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Difference between address of current opcode and target address offset.
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kBranchPCOffset = 4;
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Here we are patching the address in the LUI/ORI instruction pair.
520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // These values are used in the serialization process and must be zero for
521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // MIPS platform, as Code, Embedded Object or External-reference pointers
522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // are split across two consecutive instructions and don't exist separately
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // in the code, so the serializer should not step forwards in memory after
524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // a target is resolved and written.
525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kSpecialTargetSize = 0;
526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Number of consecutive instructions used to store 32bit/64bit constant.
528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // This constant was used in RelocInfo::target_address_address() function
529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // to tell serializer address of the instruction that follows
530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // LUI/ORI instruction pair.
531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kInstructionsFor32BitConstant = 2;
532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kInstructionsFor64BitConstant = 4;
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Distance between the instruction referring to the address of the call
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // target and the return address.
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kCallTargetAddressOffset = 6 * kInstrSize;
537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Distance between start of patched debug break slot and the emitted address
539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to jump to.
540014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kPatchDebugBreakSlotAddressOffset = 6 * kInstrSize;
541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Difference between address of current opcode and value read from pc
543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // register.
544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kPcLoadDelta = 4;
545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kDebugBreakSlotInstructions = 6;
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kDebugBreakSlotLength =
548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kDebugBreakSlotInstructions * kInstrSize;
549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ---------------------------------------------------------------------------
552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Code generation.
553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Insert the smallest number of nop instructions
555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // possible to align the pc offset to a multiple
556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // of m. m must be a power of 2 (>= 4).
557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Align(int m);
558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Insert the smallest number of zero bytes possible to align the pc offset
559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // to a mulitple of m. m must be a power of 2 (>= 2).
560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void DataAlign(int m);
561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Aligns code to something that's optimal for a jump target for the platform.
562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CodeTargetAlign();
563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Different nop operations are used by the code generator to detect certain
565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // states of the generated code.
566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum NopMarkerTypes {
567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    NON_MARKING_NOP = 0,
568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DEBUG_BREAK_NOP,
569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // IC markers.
570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PROPERTY_ACCESS_INLINED,
571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PROPERTY_ACCESS_INLINED_CONTEXT,
572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Helper values.
574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LAST_CODE_MARKER,
575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED,
576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Code aging
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CODE_AGE_MARKER_NOP = 6,
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CODE_AGE_SEQUENCE_NOP
579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Type == 0 is the default non-marking nop. For mips this is a
582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // sll(zero_reg, zero_reg, 0). We use rt_reg == at for non-zero
583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // marking, to avoid conflict with ssnop and ehb instructions.
584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void nop(unsigned int type = 0) {
585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(type < 32);
586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register nop_rt_reg = (type == 0) ? zero_reg : at;
587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sll(zero_reg, nop_rt_reg, type, true);
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // --------Branch-and-jump-instructions----------
592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We don't use likely variant of instructions.
593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void b(int16_t offset);
594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void b(Label* L) { b(shifted_branch_offset(L)); }
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bal(int16_t offset);
596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bal(Label* L) { bal(shifted_branch_offset(L)); }
597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bc(int32_t offset);
598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bc(Label* L) { bc(shifted_branch_offset26(L)); }
599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void balc(int32_t offset);
600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void balc(Label* L) { balc(shifted_branch_offset26(L)); }
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void beq(Register rs, Register rt, int16_t offset);
603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void beq(Register rs, Register rt, Label* L) {
604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    beq(rs, rt, shifted_branch_offset(L));
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bgez(Register rs, int16_t offset);
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bgezc(Register rt, int16_t offset);
608014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bgezc(Register rt, Label* L) {
609014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bgezc(rt, shifted_branch_offset(L));
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bgeuc(Register rs, Register rt, int16_t offset);
612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bgeuc(Register rs, Register rt, Label* L) {
613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bgeuc(rs, rt, shifted_branch_offset(L));
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bgec(Register rs, Register rt, int16_t offset);
616014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bgec(Register rs, Register rt, Label* L) {
617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bgec(rs, rt, shifted_branch_offset(L));
618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bgezal(Register rs, int16_t offset);
620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bgezalc(Register rt, int16_t offset);
621014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bgezalc(Register rt, Label* L) {
622014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bgezalc(rt, shifted_branch_offset(L));
623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bgezall(Register rs, int16_t offset);
625014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bgezall(Register rs, Label* L) {
626014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bgezall(rs, branch_offset(L) >> 2);
627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bgtz(Register rs, int16_t offset);
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bgtzc(Register rt, int16_t offset);
630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bgtzc(Register rt, Label* L) {
631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bgtzc(rt, shifted_branch_offset(L));
632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void blez(Register rs, int16_t offset);
634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void blezc(Register rt, int16_t offset);
635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void blezc(Register rt, Label* L) {
636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    blezc(rt, shifted_branch_offset(L));
637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bltz(Register rs, int16_t offset);
639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bltzc(Register rt, int16_t offset);
640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bltzc(Register rt, Label* L) {
641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bltzc(rt, shifted_branch_offset(L));
642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bltuc(Register rs, Register rt, int16_t offset);
644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bltuc(Register rs, Register rt, Label* L) {
645014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bltuc(rs, rt, shifted_branch_offset(L));
646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bltc(Register rs, Register rt, int16_t offset);
648014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bltc(Register rs, Register rt, Label* L) {
649014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bltc(rs, rt, shifted_branch_offset(L));
650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bltzal(Register rs, int16_t offset);
652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void blezalc(Register rt, int16_t offset);
653014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void blezalc(Register rt, Label* L) {
654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    blezalc(rt, shifted_branch_offset(L));
655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bltzalc(Register rt, int16_t offset);
657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bltzalc(Register rt, Label* L) {
658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bltzalc(rt, shifted_branch_offset(L));
659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bgtzalc(Register rt, int16_t offset);
661014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bgtzalc(Register rt, Label* L) {
662014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bgtzalc(rt, shifted_branch_offset(L));
663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void beqzalc(Register rt, int16_t offset);
665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void beqzalc(Register rt, Label* L) {
666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    beqzalc(rt, shifted_branch_offset(L));
667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void beqc(Register rs, Register rt, int16_t offset);
669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void beqc(Register rs, Register rt, Label* L) {
670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    beqc(rs, rt, shifted_branch_offset(L));
671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void beqzc(Register rs, int32_t offset);
673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void beqzc(Register rs, Label* L) {
674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    beqzc(rs, shifted_branch_offset21(L));
675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bnezalc(Register rt, int16_t offset);
677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bnezalc(Register rt, Label* L) {
678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bnezalc(rt, shifted_branch_offset(L));
679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bnec(Register rs, Register rt, int16_t offset);
681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bnec(Register rs, Register rt, Label* L) {
682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bnec(rs, rt, shifted_branch_offset(L));
683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bnezc(Register rt, int32_t offset);
685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bnezc(Register rt, Label* L) {
686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bnezc(rt, shifted_branch_offset21(L));
687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bne(Register rs, Register rt, int16_t offset);
689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bne(Register rs, Register rt, Label* L) {
690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bne(rs, rt, shifted_branch_offset(L));
691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bovc(Register rs, Register rt, int16_t offset);
693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bovc(Register rs, Register rt, Label* L) {
694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bovc(rs, rt, shifted_branch_offset(L));
695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bnvc(Register rs, Register rt, int16_t offset);
697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bnvc(Register rs, Register rt, Label* L) {
698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bnvc(rs, rt, shifted_branch_offset(L));
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Never use the int16_t b(l)cond version with a branch offset
702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // instead of using the Label* version.
703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Jump targets must be in the current 256 MB-aligned region. i.e. 28 bits.
705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void j(int64_t target);
706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void jal(int64_t target);
707014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void j(Label* target);
708014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void jal(Label* target);
709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void jalr(Register rs, Register rd = ra);
710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void jr(Register target);
711014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void jic(Register rt, int16_t offset);
712014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void jialc(Register rt, int16_t offset);
713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -------Data-processing-instructions---------
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Arithmetic.
718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void addu(Register rd, Register rs, Register rt);
719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void subu(Register rd, Register rs, Register rt);
720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void div(Register rs, Register rt);
722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void divu(Register rs, Register rt);
723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ddiv(Register rs, Register rt);
724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ddivu(Register rs, Register rt);
725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void div(Register rd, Register rs, Register rt);
726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void divu(Register rd, Register rs, Register rt);
727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ddiv(Register rd, Register rs, Register rt);
728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ddivu(Register rd, Register rs, Register rt);
729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void mod(Register rd, Register rs, Register rt);
730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void modu(Register rd, Register rs, Register rt);
731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dmod(Register rd, Register rs, Register rt);
732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dmodu(Register rd, Register rs, Register rt);
733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void mul(Register rd, Register rs, Register rt);
735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void muh(Register rd, Register rs, Register rt);
736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void mulu(Register rd, Register rs, Register rt);
737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void muhu(Register rd, Register rs, Register rt);
738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void mult(Register rs, Register rt);
739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void multu(Register rs, Register rt);
740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dmul(Register rd, Register rs, Register rt);
741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dmuh(Register rd, Register rs, Register rt);
742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dmulu(Register rd, Register rs, Register rt);
743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dmuhu(Register rd, Register rs, Register rt);
744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void daddu(Register rd, Register rs, Register rt);
745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dsubu(Register rd, Register rs, Register rt);
746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dmult(Register rs, Register rt);
747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dmultu(Register rs, Register rt);
748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void addiu(Register rd, Register rs, int32_t j);
750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void daddiu(Register rd, Register rs, int32_t j);
751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Logical.
753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void and_(Register rd, Register rs, Register rt);
754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void or_(Register rd, Register rs, Register rt);
755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void xor_(Register rd, Register rs, Register rt);
756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void nor(Register rd, Register rs, Register rt);
757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void andi(Register rd, Register rs, int32_t j);
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ori(Register rd, Register rs, int32_t j);
760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void xori(Register rd, Register rs, int32_t j);
761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void lui(Register rd, int32_t j);
762014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void aui(Register rt, Register rs, int32_t j);
763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void daui(Register rt, Register rs, int32_t j);
764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dahi(Register rs, int32_t j);
765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dati(Register rs, int32_t j);
766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Shifts.
768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Please note: sll(zero_reg, zero_reg, x) instructions are reserved as nop
769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // and may cause problems in normal code. coming_from_nop makes sure this
770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // doesn't happen.
771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void sll(Register rd, Register rt, uint16_t sa, bool coming_from_nop = false);
772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void sllv(Register rd, Register rt, Register rs);
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void srl(Register rd, Register rt, uint16_t sa);
774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void srlv(Register rd, Register rt, Register rs);
775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void sra(Register rt, Register rd, uint16_t sa);
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void srav(Register rt, Register rd, Register rs);
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void rotr(Register rd, Register rt, uint16_t sa);
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void rotrv(Register rd, Register rt, Register rs);
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dsll(Register rd, Register rt, uint16_t sa);
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dsllv(Register rd, Register rt, Register rs);
781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dsrl(Register rd, Register rt, uint16_t sa);
782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dsrlv(Register rd, Register rt, Register rs);
783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void drotr(Register rd, Register rt, uint16_t sa);
784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void drotrv(Register rd, Register rt, Register rs);
785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dsra(Register rt, Register rd, uint16_t sa);
786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dsrav(Register rd, Register rt, Register rs);
787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dsll32(Register rt, Register rd, uint16_t sa);
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dsrl32(Register rt, Register rd, uint16_t sa);
789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dsra32(Register rt, Register rd, uint16_t sa);
790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
791014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Address computing instructions with shift.
792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void lsa(Register rd, Register rt, Register rs, uint8_t sa);
793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void dlsa(Register rd, Register rt, Register rs, uint8_t sa);
794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ------------Memory-instructions-------------
796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void lb(Register rd, const MemOperand& rs);
798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void lbu(Register rd, const MemOperand& rs);
799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void lh(Register rd, const MemOperand& rs);
800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void lhu(Register rd, const MemOperand& rs);
801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void lw(Register rd, const MemOperand& rs);
802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void lwu(Register rd, const MemOperand& rs);
803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void lwl(Register rd, const MemOperand& rs);
804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void lwr(Register rd, const MemOperand& rs);
805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void sb(Register rd, const MemOperand& rs);
806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void sh(Register rd, const MemOperand& rs);
807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void sw(Register rd, const MemOperand& rs);
808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void swl(Register rd, const MemOperand& rs);
809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void swr(Register rd, const MemOperand& rs);
810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ldl(Register rd, const MemOperand& rs);
811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ldr(Register rd, const MemOperand& rs);
812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void sdl(Register rd, const MemOperand& rs);
813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void sdr(Register rd, const MemOperand& rs);
814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ld(Register rd, const MemOperand& rs);
815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void sd(Register rd, const MemOperand& rs);
816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // ---------PC-Relative-instructions-----------
819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void addiupc(Register rs, int32_t imm19);
821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void lwpc(Register rs, int32_t offset19);
822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void lwupc(Register rs, int32_t offset19);
823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void ldpc(Register rs, int32_t offset18);
824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void auipc(Register rs, int16_t imm16);
825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void aluipc(Register rs, int16_t imm16);
826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ----------------Prefetch--------------------
829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void pref(int32_t hint, const MemOperand& rs);
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -------------Misc-instructions--------------
834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Break / Trap instructions.
836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void break_(uint32_t code, bool break_as_stop = false);
837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void stop(const char* msg, uint32_t code = kMaxStopCode);
838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void tge(Register rs, Register rt, uint16_t code);
839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void tgeu(Register rs, Register rt, uint16_t code);
840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void tlt(Register rs, Register rt, uint16_t code);
841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void tltu(Register rs, Register rt, uint16_t code);
842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void teq(Register rs, Register rt, uint16_t code);
843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void tne(Register rs, Register rt, uint16_t code);
844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Move from HI/LO register.
846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void mfhi(Register rd);
847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void mflo(Register rd);
848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set on less than.
850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void slt(Register rd, Register rs, Register rt);
851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void sltu(Register rd, Register rs, Register rt);
852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void slti(Register rd, Register rs, int32_t j);
853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void sltiu(Register rd, Register rs, int32_t j);
854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Conditional move.
856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void movz(Register rd, Register rs, Register rt);
857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void movn(Register rd, Register rs, Register rt);
858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void movt(Register rd, Register rs, uint16_t cc = 0);
859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void movf(Register rd, Register rs, uint16_t cc = 0);
860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void sel(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void sel_s(FPURegister fd, FPURegister fs, FPURegister ft);
863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void sel_d(FPURegister fd, FPURegister fs, FPURegister ft);
864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void seleqz(Register rd, Register rs, Register rt);
865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void seleqz(SecondaryField fmt, FPURegister fd, FPURegister fs,
866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              FPURegister ft);
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void selnez(Register rs, Register rt, Register rd);
868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void selnez(SecondaryField fmt, FPURegister fd, FPURegister fs,
869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              FPURegister ft);
870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void seleqz_d(FPURegister fd, FPURegister fs, FPURegister ft);
871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void seleqz_s(FPURegister fd, FPURegister fs, FPURegister ft);
872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void selnez_d(FPURegister fd, FPURegister fs, FPURegister ft);
873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void selnez_s(FPURegister fd, FPURegister fs, FPURegister ft);
874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void movz_s(FPURegister fd, FPURegister fs, Register rt);
876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void movz_d(FPURegister fd, FPURegister fs, Register rt);
877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void movt_s(FPURegister fd, FPURegister fs, uint16_t cc = 0);
878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void movt_d(FPURegister fd, FPURegister fs, uint16_t cc = 0);
879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void movf_s(FPURegister fd, FPURegister fs, uint16_t cc = 0);
880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void movf_d(FPURegister fd, FPURegister fs, uint16_t cc = 0);
881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void movn_s(FPURegister fd, FPURegister fs, Register rt);
882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void movn_d(FPURegister fd, FPURegister fs, Register rt);
883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Bit twiddling.
884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void clz(Register rd, Register rs);
885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void dclz(Register rd, Register rs);
886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ins_(Register rt, Register rs, uint16_t pos, uint16_t size);
887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ext_(Register rt, Register rs, uint16_t pos, uint16_t size);
888958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void dext_(Register rt, Register rs, uint16_t pos, uint16_t size);
889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void dextm(Register rt, Register rs, uint16_t pos, uint16_t size);
890014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void dextu(Register rt, Register rs, uint16_t pos, uint16_t size);
891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void dins_(Register rt, Register rs, uint16_t pos, uint16_t size);
892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void bitswap(Register rd, Register rt);
893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void dbitswap(Register rd, Register rt);
894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void align(Register rd, Register rs, Register rt, uint8_t bp);
895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void dalign(Register rd, Register rs, Register rt, uint8_t bp);
896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // --------Coprocessor-instructions----------------
898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load, store, and move.
900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void lwc1(FPURegister fd, const MemOperand& src);
901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ldc1(FPURegister fd, const MemOperand& src);
902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void swc1(FPURegister fs, const MemOperand& dst);
904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void sdc1(FPURegister fs, const MemOperand& dst);
905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void mtc1(Register rt, FPURegister fs);
907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void mthc1(Register rt, FPURegister fs);
908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dmtc1(Register rt, FPURegister fs);
909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void mfc1(Register rt, FPURegister fs);
911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void mfhc1(Register rt, FPURegister fs);
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dmfc1(Register rt, FPURegister fs);
913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ctc1(Register rt, FPUControlRegister fs);
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void cfc1(Register rt, FPUControlRegister fs);
916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Arithmetic.
918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void add_s(FPURegister fd, FPURegister fs, FPURegister ft);
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void add_d(FPURegister fd, FPURegister fs, FPURegister ft);
920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void sub_s(FPURegister fd, FPURegister fs, FPURegister ft);
921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void sub_d(FPURegister fd, FPURegister fs, FPURegister ft);
922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void mul_s(FPURegister fd, FPURegister fs, FPURegister ft);
923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void mul_d(FPURegister fd, FPURegister fs, FPURegister ft);
924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void madd_d(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft);
925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void div_s(FPURegister fd, FPURegister fs, FPURegister ft);
926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void div_d(FPURegister fd, FPURegister fs, FPURegister ft);
927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void abs_s(FPURegister fd, FPURegister fs);
928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void abs_d(FPURegister fd, FPURegister fs);
929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void mov_d(FPURegister fd, FPURegister fs);
930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void mov_s(FPURegister fd, FPURegister fs);
931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void neg_s(FPURegister fd, FPURegister fs);
932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void neg_d(FPURegister fd, FPURegister fs);
933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void sqrt_s(FPURegister fd, FPURegister fs);
934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void sqrt_d(FPURegister fd, FPURegister fs);
935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void rsqrt_s(FPURegister fd, FPURegister fs);
936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void rsqrt_d(FPURegister fd, FPURegister fs);
937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void recip_d(FPURegister fd, FPURegister fs);
938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void recip_s(FPURegister fd, FPURegister fs);
939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Conversion.
941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void cvt_w_s(FPURegister fd, FPURegister fs);
942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void cvt_w_d(FPURegister fd, FPURegister fs);
943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void trunc_w_s(FPURegister fd, FPURegister fs);
944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void trunc_w_d(FPURegister fd, FPURegister fs);
945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void round_w_s(FPURegister fd, FPURegister fs);
946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void round_w_d(FPURegister fd, FPURegister fs);
947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void floor_w_s(FPURegister fd, FPURegister fs);
948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void floor_w_d(FPURegister fd, FPURegister fs);
949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ceil_w_s(FPURegister fd, FPURegister fs);
950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ceil_w_d(FPURegister fd, FPURegister fs);
951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void rint_s(FPURegister fd, FPURegister fs);
952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void rint_d(FPURegister fd, FPURegister fs);
953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void rint(SecondaryField fmt, FPURegister fd, FPURegister fs);
954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void cvt_l_s(FPURegister fd, FPURegister fs);
957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void cvt_l_d(FPURegister fd, FPURegister fs);
958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void trunc_l_s(FPURegister fd, FPURegister fs);
959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void trunc_l_d(FPURegister fd, FPURegister fs);
960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void round_l_s(FPURegister fd, FPURegister fs);
961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void round_l_d(FPURegister fd, FPURegister fs);
962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void floor_l_s(FPURegister fd, FPURegister fs);
963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void floor_l_d(FPURegister fd, FPURegister fs);
964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ceil_l_s(FPURegister fd, FPURegister fs);
965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ceil_l_d(FPURegister fd, FPURegister fs);
966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void class_s(FPURegister fd, FPURegister fs);
968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void class_d(FPURegister fd, FPURegister fs);
969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void min(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void mina(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void max(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void maxa(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void min_s(FPURegister fd, FPURegister fs, FPURegister ft);
975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void min_d(FPURegister fd, FPURegister fs, FPURegister ft);
976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void max_s(FPURegister fd, FPURegister fs, FPURegister ft);
977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void max_d(FPURegister fd, FPURegister fs, FPURegister ft);
978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void mina_s(FPURegister fd, FPURegister fs, FPURegister ft);
979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void mina_d(FPURegister fd, FPURegister fs, FPURegister ft);
980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void maxa_s(FPURegister fd, FPURegister fs, FPURegister ft);
981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void maxa_d(FPURegister fd, FPURegister fs, FPURegister ft);
982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void cvt_s_w(FPURegister fd, FPURegister fs);
984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void cvt_s_l(FPURegister fd, FPURegister fs);
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void cvt_s_d(FPURegister fd, FPURegister fs);
986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void cvt_d_w(FPURegister fd, FPURegister fs);
988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void cvt_d_l(FPURegister fd, FPURegister fs);
989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void cvt_d_s(FPURegister fd, FPURegister fs);
990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Conditions and branches for MIPSr6.
992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void cmp(FPUCondition cond, SecondaryField fmt,
993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FPURegister fd, FPURegister ft, FPURegister fs);
994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void cmp_s(FPUCondition cond, FPURegister fd, FPURegister fs, FPURegister ft);
995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void cmp_d(FPUCondition cond, FPURegister fd, FPURegister fs, FPURegister ft);
996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bc1eqz(int16_t offset, FPURegister ft);
998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bc1eqz(Label* L, FPURegister ft) {
999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bc1eqz(shifted_branch_offset(L), ft);
1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bc1nez(int16_t offset, FPURegister ft);
1002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bc1nez(Label* L, FPURegister ft) {
1003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bc1nez(shifted_branch_offset(L), ft);
1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Conditions and branches for non MIPSr6.
1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void c(FPUCondition cond, SecondaryField fmt,
1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FPURegister ft, FPURegister fs, uint16_t cc = 0);
1009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void c_s(FPUCondition cond, FPURegister ft, FPURegister fs, uint16_t cc = 0);
1010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void c_d(FPUCondition cond, FPURegister ft, FPURegister fs, uint16_t cc = 0);
1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bc1f(int16_t offset, uint16_t cc = 0);
1013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bc1f(Label* L, uint16_t cc = 0) {
1014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bc1f(shifted_branch_offset(L), cc);
1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bc1t(int16_t offset, uint16_t cc = 0);
1017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void bc1t(Label* L, uint16_t cc = 0) {
1018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bc1t(shifted_branch_offset(L), cc);
1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void fcmp(FPURegister src1, const double src2, FPUCondition cond);
1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check the code size generated from label to here.
1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int SizeOfCodeGeneratedSince(Label* label) {
1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return pc_offset() - label->pos();
1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check the number of instructions generated from label to here.
1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int InstructionsGeneratedSince(Label* label) {
1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return SizeOfCodeGeneratedSince(label) / kInstrSize;
1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Class for scoping postponing the trampoline pool generation.
1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  class BlockTrampolinePoolScope {
1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
1035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) {
1036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      assem_->StartBlockTrampolinePool();
1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ~BlockTrampolinePoolScope() {
1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      assem_->EndBlockTrampolinePool();
1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assembler* assem_;
1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope);
1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Class for postponing the assembly buffer growth. Typically used for
1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // sequences of instructions that must be emitted as a unit, before
1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // buffer growth (and relocation) can occur.
1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This blocking scope is not nestable.
1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  class BlockGrowBufferScope {
1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    explicit BlockGrowBufferScope(Assembler* assem) : assem_(assem) {
1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      assem_->StartBlockGrowBuffer();
1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ~BlockGrowBufferScope() {
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      assem_->EndBlockGrowBuffer();
1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Assembler* assem_;
1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DISALLOW_IMPLICIT_CONSTRUCTORS(BlockGrowBufferScope);
1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Debugging.
1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1069014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Mark generator continuation.
1070014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void RecordGeneratorContinuation();
1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mark address of a debug break slot.
1073014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void RecordDebugBreakSlot(RelocInfo::Mode mode);
1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Record the AST id of the CallIC being compiled, so that it can be placed
1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // in the relocation information.
1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SetRecordedAstId(TypeFeedbackId ast_id) {
1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(recorded_ast_id_.IsNone());
1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    recorded_ast_id_ = ast_id;
1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TypeFeedbackId RecordedAstId() {
1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!recorded_ast_id_.IsNone());
1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return recorded_ast_id_;
1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Record a comment relocation entry that can be used by a disassembler.
1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Use --code-comments to enable.
1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RecordComment(const char* msg);
1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Record a deoptimization reason that can be used by a log or cpu profiler.
1094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Use --trace-deopt to enable.
1095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void RecordDeoptReason(const int reason, const SourcePosition position);
1096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static int RelocateInternalReference(RelocInfo::Mode rmode, byte* pc,
1098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                       intptr_t pc_delta);
1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Writes a single byte or word of data in the code stream.  Used for
1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // inline tables, e.g., jump-tables.
1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void db(uint8_t data);
1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void dd(uint32_t data);
1104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void dq(uint64_t data);
1105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void dp(uintptr_t data) { dq(data); }
1106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void dd(Label* label);
1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PositionsRecorder* positions_recorder() { return &positions_recorder_; }
1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Postpone the generation of the trampoline pool for the specified number of
1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // instructions.
1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void BlockTrampolinePoolFor(int instructions);
1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if there is less than kGap bytes available in the buffer.
1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If this is the case, we need to grow the buffer before emitting
1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // an instruction or relocation information.
1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; }
1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the number of bytes available in the buffer.
1120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline intptr_t available_space() const {
1121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return reloc_info_writer.pos() - pc_;
1122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Read/patch instructions.
1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void instr_at_put(byte* pc, Instr instr) {
1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *reinterpret_cast<Instr*>(pc) = instr;
1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void instr_at_put(int pos, Instr instr) {
1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if an instruction is a branch of some kind.
1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsBranch(Instr instr);
1136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static bool IsBc(Instr instr);
1137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static bool IsBzc(Instr instr);
1138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsBeq(Instr instr);
1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsBne(Instr instr);
1141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static bool IsBeqzc(Instr instr);
1142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static bool IsBnezc(Instr instr);
1143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static bool IsBeqc(Instr instr);
1144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static bool IsBnec(Instr instr);
1145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsJump(Instr instr);
1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsJ(Instr instr);
1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsLui(Instr instr);
1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsOri(Instr instr);
1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsJal(Instr instr);
1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsJr(Instr instr);
1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsJalr(Instr instr);
1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsNop(Instr instr, unsigned int type);
1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsPop(Instr instr);
1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsPush(Instr instr);
1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsLwRegFpOffset(Instr instr);
1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsSwRegFpOffset(Instr instr);
1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsLwRegFpNegOffset(Instr instr);
1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsSwRegFpNegOffset(Instr instr);
1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static Register GetRtReg(Instr instr);
1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static Register GetRsReg(Instr instr);
1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static Register GetRdReg(Instr instr);
1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static uint32_t GetRt(Instr instr);
1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static uint32_t GetRtField(Instr instr);
1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static uint32_t GetRs(Instr instr);
1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static uint32_t GetRsField(Instr instr);
1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static uint32_t GetRd(Instr instr);
1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static uint32_t GetRdField(Instr instr);
1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static uint32_t GetSa(Instr instr);
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static uint32_t GetSaField(Instr instr);
1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static uint32_t GetOpcodeField(Instr instr);
1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static uint32_t GetFunction(Instr instr);
1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static uint32_t GetFunctionField(Instr instr);
1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static uint32_t GetImmediate16(Instr instr);
1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static uint32_t GetLabelConst(Instr instr);
1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static int32_t GetBranchOffset(Instr instr);
1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsLw(Instr instr);
1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static int16_t GetLwOffset(Instr instr);
1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static Instr SetLwOffset(Instr instr, int16_t offset);
1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsSw(Instr instr);
1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static Instr SetSwOffset(Instr instr, int16_t offset);
1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsAddImmediate(Instr instr);
1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static Instr SetAddImmediateOffset(Instr instr, int16_t offset);
1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsAndImmediate(Instr instr);
1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsEmittedConstant(Instr instr);
1194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CheckTrampolinePool();
1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void PatchConstantPoolAccessInstruction(int pc_offset, int offset,
1198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                          ConstantPoolEntry::Access access,
1199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                          ConstantPoolEntry::Type type) {
1200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // No embedded constant pool support.
1201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    UNREACHABLE();
1202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool IsPrevInstrCompactBranch() { return prev_instr_compact_branch_; }
1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch protected:
1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Relocation for a type-recording IC has the AST id added to it.  This
1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // member variable is a way to pass the information from the call site to
1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the relocation info.
1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TypeFeedbackId recorded_ast_id_;
1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline static void set_target_internal_reference_encoded_at(Address pc,
1213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                              Address target);
1214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int64_t buffer_space() const { return reloc_info_writer.pos() - pc_; }
1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Decode branch instruction at pos and return branch target pos.
1218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int target_at(int pos, bool is_internal);
1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Patch branch instruction at pos to branch to given branch target pos.
1221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void target_at_put(int pos, int target_pos, bool is_internal);
1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Say if we need to relocate with this mode.
1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool MustUseReg(RelocInfo::Mode rmode);
1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Record reloc info for current pc_.
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Block the emission of the trampoline pool before pc_offset.
1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void BlockTrampolinePoolBefore(int pc_offset) {
1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (no_trampoline_pool_before_ < pc_offset)
1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      no_trampoline_pool_before_ = pc_offset;
1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void StartBlockTrampolinePool() {
1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    trampoline_pool_blocked_nesting_++;
1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EndBlockTrampolinePool() {
1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    trampoline_pool_blocked_nesting_--;
1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool is_trampoline_pool_blocked() const {
1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return trampoline_pool_blocked_nesting_ > 0;
1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool has_exception() const {
1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return internal_trampoline_exception_;
1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi);
1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool is_trampoline_emitted() const {
1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return trampoline_emitted_;
1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Temporarily block automatic assembly buffer growth.
1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void StartBlockGrowBuffer() {
1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!block_buffer_growth_);
1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    block_buffer_growth_ = true;
1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EndBlockGrowBuffer() {
1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(block_buffer_growth_);
1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    block_buffer_growth_ = false;
1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool is_buffer_growth_blocked() const {
1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return block_buffer_growth_;
1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void EmitForbiddenSlotInstruction() {
1273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (IsPrevInstrCompactBranch()) {
1274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      nop();
1275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ClearCompactBranchState();
1276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void CheckTrampolinePoolQuick(int extra_instructions = 0);
1280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Buffer size and constant pool distance are checked together at regular
1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // intervals of kBufferCheckInterval emitted bytes.
1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kBufferCheckInterval = 1*KB/2;
1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Code generation.
1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The relocation writer's position is at least kGap bytes below the end of
1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the generated instructions. This is so that multi-instruction sequences do
1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // not have to check for overflow. The same is true for writes of large
1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // relocation info entries.
1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kGap = 32;
1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Repeated checking whether the trampoline pool should be emitted is rather
1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // expensive. By default we only check again once a number of instructions
1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // has been generated.
1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kCheckConstIntervalInst = 32;
1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize;
1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int next_buffer_check_;  // pc offset of next buffer check.
1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Emission of the trampoline pool may be blocked in some code sequences.
1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int trampoline_pool_blocked_nesting_;  // Block emission if this is not zero.
1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int no_trampoline_pool_before_;  // Block emission before this pc offset.
1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Keep track of the last emitted pool to guarantee a maximal distance.
1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int last_trampoline_pool_end_;  // pc offset of the end of the last pool.
1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Automatic growth of the assembly buffer may be blocked for some sequences.
1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool block_buffer_growth_;  // Block growth when true.
1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Relocation information generation.
1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Each relocation is encoded as a variable size value.
1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RelocInfoWriter reloc_info_writer;
1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The bound position, before this we cannot do instruction elimination.
1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int last_bound_pos_;
1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Readable constants for compact branch handling in emit()
1321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  enum class CompactBranchType : bool { NO = false, COMPACT_BRANCH = true };
1322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Code emission.
1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void CheckBuffer();
1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void GrowBuffer();
1326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void emit(Instr x,
1327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   CompactBranchType is_compact_branch = CompactBranchType::NO);
1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void emit(uint64_t x);
1329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void CheckForEmitInForbiddenSlot();
1330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  template <typename T>
1331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void EmitHelper(T x);
1332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void EmitHelper(Instr x, CompactBranchType is_compact_branch);
1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction generation.
1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We have 3 different kind of encoding layout on MIPS.
1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // However due to many different types of objects encoded in the same fields
1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // we have quite a few aliases for each mode.
1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Using the same structure to refer to Register and FPURegister would spare a
1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // few aliases, but mixing both does not look clean to me.
1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Anyway we could surely implement this differently.
1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void GenInstrRegister(Opcode opcode,
1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        Register rs,
1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        Register rt,
1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        Register rd,
1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        uint16_t sa = 0,
1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        SecondaryField func = NULLSF);
1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void GenInstrRegister(Opcode opcode,
1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        Register rs,
1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        Register rt,
1352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        uint16_t msb,
1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        uint16_t lsb,
1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        SecondaryField func);
1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void GenInstrRegister(Opcode opcode,
1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        SecondaryField fmt,
1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        FPURegister ft,
1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        FPURegister fs,
1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        FPURegister fd,
1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        SecondaryField func = NULLSF);
1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void GenInstrRegister(Opcode opcode,
1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        FPURegister fr,
1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        FPURegister ft,
1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        FPURegister fs,
1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        FPURegister fd,
1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        SecondaryField func = NULLSF);
1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void GenInstrRegister(Opcode opcode,
1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        SecondaryField fmt,
1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        Register rt,
1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        FPURegister fs,
1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        FPURegister fd,
1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        SecondaryField func = NULLSF);
1376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void GenInstrRegister(Opcode opcode,
1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        SecondaryField fmt,
1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        Register rt,
1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        FPUControlRegister fs,
1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        SecondaryField func = NULLSF);
1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void GenInstrImmediate(
1385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Opcode opcode, Register rs, Register rt, int32_t j,
1386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      CompactBranchType is_compact_branch = CompactBranchType::NO);
1387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void GenInstrImmediate(
1388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Opcode opcode, Register rs, SecondaryField SF, int32_t j,
1389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      CompactBranchType is_compact_branch = CompactBranchType::NO);
1390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void GenInstrImmediate(
1391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Opcode opcode, Register r1, FPURegister r2, int32_t j,
1392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      CompactBranchType is_compact_branch = CompactBranchType::NO);
1393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void GenInstrImmediate(
1394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Opcode opcode, Register rs, int32_t offset21,
1395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      CompactBranchType is_compact_branch = CompactBranchType::NO);
1396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void GenInstrImmediate(Opcode opcode, Register rs, uint32_t offset21);
1397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void GenInstrImmediate(
1398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Opcode opcode, int32_t offset26,
1399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      CompactBranchType is_compact_branch = CompactBranchType::NO);
1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void GenInstrJump(Opcode opcode,
1402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     uint32_t address);
1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Helpers.
1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void LoadRegPlusOffsetToAt(const MemOperand& src);
1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Labels.
1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void print(Label* L);
1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void bind_to(Label* L, int pos);
1410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void next(Label* L, bool is_internal);
1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // One trampoline consists of:
1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // - space for trampoline slots,
1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // - space for labels.
1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Space for trampoline slots is equal to slot_count * 2 * kInstrSize.
1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Space for trampoline slots preceeds space for labels. Each label is of one
1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // instruction size, so total amount for labels is equal to
1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // label_count *  kInstrSize.
1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  class Trampoline {
1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Trampoline() {
1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      start_ = 0;
1424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      next_slot_ = 0;
1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      free_slot_count_ = 0;
1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      end_ = 0;
1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Trampoline(int start, int slot_count) {
1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      start_ = start;
1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      next_slot_ = start;
1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      free_slot_count_ = slot_count;
1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      end_ = start + slot_count * kTrampolineSlotsSize;
1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int start() {
1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return start_;
1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int end() {
1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return end_;
1439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int take_slot() {
1441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int trampoline_slot = kInvalidSlotPos;
1442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (free_slot_count_ <= 0) {
1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // We have run out of space on trampolines.
1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Make sure we fail in debug mode, so we become aware of each case
1445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // when this happens.
1446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(0);
1447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Internal exception will be caught.
1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        trampoline_slot = next_slot_;
1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        free_slot_count_--;
1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        next_slot_ += kTrampolineSlotsSize;
1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return trampoline_slot;
1454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int start_;
1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int end_;
1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int next_slot_;
1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int free_slot_count_;
1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
1462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t get_trampoline_entry(int32_t pos);
1464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int unbound_labels_count_;
1465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // After trampoline is emitted, long branches are used in generated code for
1466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // the forward branches whose target offsets could be beyond reach of branch
1467014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // instruction. We use this information to trigger different mode of
1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // branch instruction generation, where we use jump instructions rather
1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // than regular branch instructions.
1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool trampoline_emitted_;
1471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kTrampolineSlotsSize = 2 * kInstrSize;
1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kMaxBranchOffset = (1 << (18 - 1)) - 1;
1473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kMaxCompactBranchOffset = (1 << (28 - 1)) - 1;
1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kInvalidSlotPos = -1;
1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Internal reference positions, required for unbounded internal reference
1477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // labels.
1478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  std::set<int64_t> internal_reference_positions_;
1479014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1480014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void EmittedCompactBranchInstruction() { prev_instr_compact_branch_ = true; }
1481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void ClearCompactBranchState() { prev_instr_compact_branch_ = false; }
1482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool prev_instr_compact_branch_ = false;
1483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Trampoline trampoline_;
1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool internal_trampoline_exception_;
1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class RegExpMacroAssemblerMIPS;
1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class RelocInfo;
1489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class CodePatcher;
1490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class BlockTrampolinePoolScope;
1491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PositionsRecorder positions_recorder_;
1493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class PositionsRecorder;
1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class EnsureSpace;
1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass EnsureSpace BASE_EMBEDDED {
1499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit EnsureSpace(Assembler* assembler) {
1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    assembler->CheckBuffer();
1502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
1506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_ARM_ASSEMBLER_MIPS_H_
1509