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