assembler-mips.h revision 3ef787dbeca8a5fb1086949cda830dccee07bfbd
165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// Copyright (c) 1994-2006 Sun Microsystems Inc.
265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// All Rights Reserved.
365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch//
465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// Redistribution and use in source and binary forms, with or without
565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// modification, are permitted provided that the following conditions are
665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// met:
765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch//
865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// - Redistributions of source code must retain the above copyright notice,
965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// this list of conditions and the following disclaimer.
1065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch//
1165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// - Redistribution in binary form must reproduce the above copyright
1265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// notice, this list of conditions and the following disclaimer in the
1365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// documentation and/or other materials provided with the distribution.
1465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch//
1565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// - Neither the name of Sun Microsystems or the names of contributors may
1665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// be used to endorse or promote products derived from this software without
1765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// specific prior written permission.
1865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch//
1965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
2065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
2165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
2365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// The original source code covered by the above license above has been
3265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// modified significantly by Google Inc.
3365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#ifndef V8_MIPS_ASSEMBLER_MIPS_H_
3765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#define V8_MIPS_ASSEMBLER_MIPS_H_
3865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
3965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include <stdio.h>
4065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include "assembler.h"
4165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include "constants-mips.h"
4265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include "serialize.h"
4365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
442fc2651226baac27029e38c9d6ef883fa32084dbSteve Blocknamespace v8 {
4565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochnamespace internal {
4665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// CPU Registers.
4865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch//
4965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// 1) We would prefer to use an enum, but enum values are assignment-
5065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// compatible with int, which has caused code-generation bugs.
5165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch//
5265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// 2) We would prefer to use a class instead of a struct but we don't like
5365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// the register initialization to depend on the particular initialization
5465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// order (which appears to be different on OS X, Linux, and Windows for the
552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// installed versions of C++ we tried). Using a struct permits C-style
562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// "initialization". Also, the Register objects cannot be const as this
572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// forces initialization stubs in MSVC, making us dependent on initialization
582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// order.
592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block//
602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// 3) By not using an enum, we are possibly preventing the compiler from
612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// doing certain constant folds, which may significantly reduce the
622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// code generated for some assembly instructions (because they boil down
632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// to a few constants). If this is a problem, we could change the code
642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// such that we use an enum in optimized mode, and the struct in debug
652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// mode. This way we get the compile-time error checking in debug mode
6665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// and best performance in optimized code.
6765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
6865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
6965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// -----------------------------------------------------------------------------
7065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// Implementation of Register and FPURegister.
7165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
7265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// Core register.
7365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstruct Register {
7465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static const int kNumRegisters = v8::internal::kNumRegisters;
7565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static const int kNumAllocatableRegisters = 14;  // v0 through t7.
7665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static const int kSizeInBytes = 4;
7765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
7865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static int ToAllocationIndex(Register reg) {
7965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return reg.code() - 2;  // zero_reg and 'at' are skipped.
8065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
8165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
8265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static Register FromAllocationIndex(int index) {
8365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
842fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return from_code(index + 2);  // zero_reg and 'at' are skipped.
852fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  }
862fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
872fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  static const char* AllocationIndexToString(int index) {
882fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
892fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    const char* const names[] = {
902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      "v0",
9165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      "v1",
9265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      "a0",
9365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      "a1",
9465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      "a2",
9565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      "a3",
9665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      "t0",
9765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      "t1",
9865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      "t2",
9965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      "t3",
10065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      "t4",
10165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      "t5",
10265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      "t6",
10365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      "t7",
10465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    };
10565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return names[index];
10665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
10765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
10865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static Register from_code(int code) {
10965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    Register r = { code };
11065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return r;
11165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
11265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
11365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
11465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  bool is(Register reg) const { return code_ == reg.code_; }
1152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  int code() const {
1162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(is_valid());
1172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return code_;
1182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  }
1192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  int bit() const {
1202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(is_valid());
1212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return 1 << code_;
1222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  }
1232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // Unfortunately we can't make this private in a struct.
1252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  int code_;
1262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block};
1272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1282fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register no_reg = { -1 };
1292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1302fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register zero_reg = { 0 };  // Always zero.
1312fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register at = { 1 };   // at: Reserved for synthetic instructions.
1322fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register v0 = { 2 };   // v0, v1: Used when returning multiple values
1332fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register v1 = { 3 };   //   from subroutines.
1342fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register a0 = { 4 };   // a0 - a4: Used to pass non-FP parameters.
1352fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register a1 = { 5 };
1362fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register a2 = { 6 };
1372fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register a3 = { 7 };
1382fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register t0 = { 8 };   // t0 - t9: Can be used without reservation, act
1392fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register t1 = { 9 };   //   as temporary registers and are allowed to
1402fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register t2 = { 10 };  //   be destroyed by subroutines.
1412fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register t3 = { 11 };
1422fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register t4 = { 12 };
1432fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register t5 = { 13 };
1442fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register t6 = { 14 };
1452fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register t7 = { 15 };
1462fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register s0 = { 16 };  // s0 - s7: Subroutine register variables.
1472fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register s1 = { 17 };  //   Subroutines that write to these registers
1482fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register s2 = { 18 };  //   must restore their values before exiting so
1492fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register s3 = { 19 };  //   that the caller can expect the values to be
1502fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register s4 = { 20 };  //   preserved.
1512fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register s5 = { 21 };
1522fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register s6 = { 22 };
1532fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register s7 = { 23 };
1542fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register t8 = { 24 };
1552fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register t9 = { 25 };
1562fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register k0 = { 26 };  // k0, k1: Reserved for system calls and
1572fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register k1 = { 27 };  // interrupt handlers.
1582fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register gp = { 28 };  // gp: Reserved.
1592fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register sp = { 29 };  // sp: Stack pointer.
1602fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register s8_fp = { 30 };  // fp: Frame pointer.
1612fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst Register ra = { 31 };  // ra: Return address pointer.
1622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1642fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockint ToNumber(Register reg);
1652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1662fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockRegister ToRegister(int num);
1672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// Coprocessor register.
1692fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstruct FPURegister {
1702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  static const int kNumRegisters = v8::internal::kNumFPURegisters;
1712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // TODO(plind): Warning, inconsistent numbering here. kNumFPURegisters refers
1732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to
1742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // number of Double regs (64-bit regs, or FPU-reg-pairs).
1752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // A few double registers are reserved: one as a scratch register and one to
1772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // hold 0.0.
1782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  //  f28: 0.0
1792fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  //  f30: scratch register.
1802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  static const int kNumReservedRegisters = 2;
1812fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  static const int kNumAllocatableRegisters = kNumRegisters / 2 -
1822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      kNumReservedRegisters;
1832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1842fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1852fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  inline static int ToAllocationIndex(FPURegister reg);
1862fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1872fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  static FPURegister FromAllocationIndex(int index) {
1882fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
1892fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return from_code(index * 2);
1902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  }
1912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  static const char* AllocationIndexToString(int index) {
1932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
1942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    const char* const names[] = {
1952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      "f0",
1962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      "f2",
1972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      "f4",
1982fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      "f6",
1992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      "f8",
2002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      "f10",
2012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      "f12",
20265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      "f14",
20365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      "f16",
20465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      "f18",
20565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      "f20",
20665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      "f22",
20765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      "f24",
20865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      "f26"
20965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    };
21065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return names[index];
21165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
21265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
21365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static FPURegister from_code(int code) {
21465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    FPURegister r = { code };
21565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return r;
21665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
21765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
21865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  bool is_valid() const { return 0 <= code_ && code_ < kNumFPURegisters ; }
21965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  bool is(FPURegister creg) const { return code_ == creg.code_; }
22065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  FPURegister low() const {
22165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Find low reg of a Double-reg pair, which is the reg itself.
22265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(code_ % 2 == 0);  // Specified Double reg must be even.
22365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    FPURegister reg;
22465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    reg.code_ = code_;
22565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(reg.is_valid());
22665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return reg;
22765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
22865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  FPURegister high() const {
22965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Find high reg of a Doubel-reg pair, which is reg + 1.
23065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(code_ % 2 == 0);  // Specified Double reg must be even.
23165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    FPURegister reg;
23265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    reg.code_ = code_ + 1;
23365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(reg.is_valid());
23465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return reg;
23565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
23665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
23765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  int code() const {
23865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(is_valid());
23965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return code_;
24065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
24165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  int bit() const {
24265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(is_valid());
24365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return 1 << code_;
24465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
24565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void setcode(int f) {
24665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    code_ = f;
2472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(is_valid());
2482fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  }
24965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Unfortunately we can't make this private in a struct.
25065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  int code_;
25165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch};
2522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
25365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// V8 now supports the O32 ABI, and the FPU Registers are organized as 32
25465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// 32-bit registers, f0 through f31. When used as 'double' they are used
2552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// in pairs, starting with the even numbered register. So a double operation
2562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// on f0 really uses f0 and f1.
2572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// (Modern mips hardware also supports 32 64-bit registers, via setting
2582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// (priviledged) Status Register FR bit to 1. This is used by the N32 ABI,
25965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// but it is not in common use. Someday we will want to support this in v8.)
2602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
26165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// For O32 ABI, Floats and Doubles refer to same set of 32 32-bit registers.
26265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochtypedef FPURegister DoubleRegister;
2632fc2651226baac27029e38c9d6ef883fa32084dbSteve Blocktypedef FPURegister FloatRegister;
26465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
26565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister no_freg = { -1 };
26665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
26765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f0 = { 0 };  // Return value in hard float mode.
26865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f1 = { 1 };
26965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f2 = { 2 };
27065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f3 = { 3 };
27165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f4 = { 4 };
27265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f5 = { 5 };
27365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f6 = { 6 };
27465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f7 = { 7 };
27565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f8 = { 8 };
27665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f9 = { 9 };
27765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f10 = { 10 };
27865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f11 = { 11 };
27965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f12 = { 12 };  // Arg 0 in hard float mode.
2802fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst FPURegister f13 = { 13 };
2812fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst FPURegister f14 = { 14 };  // Arg 1 in hard float mode.
2822fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst FPURegister f15 = { 15 };
2832fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst FPURegister f16 = { 16 };
2842fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockconst FPURegister f17 = { 17 };
28565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f18 = { 18 };
28665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f19 = { 19 };
28765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f20 = { 20 };
28865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f21 = { 21 };
28965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f22 = { 22 };
29065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f23 = { 23 };
29165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f24 = { 24 };
29265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f25 = { 25 };
29365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f26 = { 26 };
29465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f27 = { 27 };
29565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f28 = { 28 };
29665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f29 = { 29 };
29765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f30 = { 30 };
29865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPURegister f31 = { 31 };
29965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
30065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// Register aliases.
30165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// cp is assumed to be a callee saved register.
30265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic const Register& kLithiumScratchReg = s3;  // Scratch register.
30365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic const Register& kLithiumScratchReg2 = s4;  // Scratch register.
30465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic const Register& kRootRegister = s6;  // Roots array pointer.
30565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic const Register& cp = s7;     // JavaScript context pointer.
30665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic const Register& fp = s8_fp;  // Alias for fp.
30765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic const DoubleRegister& kLithiumScratchDouble = f30;
30865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic const FPURegister& kDoubleRegZero = f28;
30965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
31065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// FPU (coprocessor 1) control registers.
31165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// Currently only FCSR (#31) is implemented.
31265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstruct FPUControlRegister {
31365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  bool is_valid() const { return code_ == kFCSRRegister; }
31465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  bool is(FPUControlRegister creg) const { return code_ == creg.code_; }
31565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  int code() const {
31665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(is_valid());
31765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return code_;
31865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
31965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  int bit() const {
32065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(is_valid());
32165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return 1 << code_;
32265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
32365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void setcode(int f) {
32465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    code_ = f;
32565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(is_valid());
32665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
32765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Unfortunately we can't make this private in a struct.
32865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  int code_;
32965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch};
33065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
33165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPUControlRegister no_fpucreg = { kInvalidFPUControlRegister };
33265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochconst FPUControlRegister FCSR = { kFCSRRegister };
33365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
33465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
33565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// -----------------------------------------------------------------------------
33665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// Machine instruction Operands.
33765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
33865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// Class Operand represents a shifter operand in data processing instructions.
33965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochclass Operand BASE_EMBEDDED {
34065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch public:
34165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Immediate.
34265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  INLINE(explicit Operand(int32_t immediate,
34365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch         RelocInfo::Mode rmode = RelocInfo::NONE));
34465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  INLINE(explicit Operand(const ExternalReference& f));
34565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  INLINE(explicit Operand(const char* s));
34665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  INLINE(explicit Operand(Object** opp));
34765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  INLINE(explicit Operand(Context** cpp));
34865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  explicit Operand(Handle<Object> handle);
34965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  INLINE(explicit Operand(Smi* value));
3502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // Register.
3522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  INLINE(explicit Operand(Register rm));
3532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // Return true if this is a register operand.
3552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  INLINE(bool is_reg() const);
3562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  Register rm() const { return rm_; }
3582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block private:
3602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  Register rm_;
3612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  int32_t imm32_;  // Valid if rm_ == no_reg.
3622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  RelocInfo::Mode rmode_;
3632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  friend class Assembler;
3652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  friend class MacroAssembler;
3662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block};
3672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// On MIPS we have only one adressing mode with base_reg + offset.
3702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// Class MemOperand represents a memory operand in load and store instructions.
3712fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockclass MemOperand : public Operand {
3722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block public:
37365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  explicit MemOperand(Register rn, int32_t offset = 0);
37465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  int32_t offset() const { return offset_; }
37565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
37665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  bool OffsetIsInt16Encodable() const {
37765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return is_int16(offset_);
37865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
37965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
38065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch private:
38165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  int32_t offset_;
38265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
38365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  friend class Assembler;
38465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch};
38565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
38665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
38765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// CpuFeatures keeps track of which features are supported by the target CPU.
38865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// Supported features must be enabled by a Scope before use.
38965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochclass CpuFeatures : public AllStatic {
39065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch public:
39165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Detect features of the target CPU. Set safe defaults if the serializer
39265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // is enabled (snapshots must be portable).
39365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static void Probe();
39465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
39565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Check whether a feature is supported by the target CPU.
39665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsSupported(CpuFeature f) {
39765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(initialized_);
39865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (f == FPU && !FLAG_enable_fpu) return false;
39965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return (supported_ & (1u << f)) != 0;
40065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
40165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
40265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
40365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#ifdef DEBUG
40465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Check whether a feature is currently enabled.
40565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsEnabled(CpuFeature f) {
40665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(initialized_);
4072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    Isolate* isolate = Isolate::UncheckedCurrent();
4082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (isolate == NULL) {
4092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      // When no isolate is available, work as if we're running in
4102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      // release mode.
4112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      return IsSupported(f);
4122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
4132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    unsigned enabled = static_cast<unsigned>(isolate->enabled_cpu_features());
4142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return (enabled & (1u << f)) != 0;
4152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  }
4162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#endif
41781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
4182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // Enable a specified feature within a scope.
4192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  class Scope BASE_EMBEDDED {
4202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#ifdef DEBUG
4212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
4222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block   public:
4232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    explicit Scope(CpuFeature f) {
4242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      unsigned mask = 1u << f;
4252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      ASSERT(CpuFeatures::IsSupported(f));
4262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      ASSERT(!Serializer::enabled() ||
4272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block             (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
4282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      isolate_ = Isolate::UncheckedCurrent();
4292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      old_enabled_ = 0;
4302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      if (isolate_ != NULL) {
4312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        old_enabled_ = static_cast<unsigned>(isolate_->enabled_cpu_features());
4322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        isolate_->set_enabled_cpu_features(old_enabled_ | mask);
4332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      }
4342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
4352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ~Scope() {
4362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
4372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      if (isolate_ != NULL) {
4382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        isolate_->set_enabled_cpu_features(old_enabled_);
4392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      }
4402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
44181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
44281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch private:
44381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Isolate* isolate_;
44481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    unsigned old_enabled_;
44581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#else
44681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
44781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch public:
44881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    explicit Scope(CpuFeature f) {}
44981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#endif
45081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch  };
45181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
45281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch  class TryForceFeatureScope BASE_EMBEDDED {
45381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch   public:
45481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    explicit TryForceFeatureScope(CpuFeature f)
45581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        : old_supported_(CpuFeatures::supported_) {
45681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch      if (CanForce()) {
45765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        CpuFeatures::supported_ |= (1u << f);
45865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      }
45965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
46065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
46165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ~TryForceFeatureScope() {
46281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch      if (CanForce()) {
46381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        CpuFeatures::supported_ = old_supported_;
46481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch      }
46581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    }
46681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
46781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch   private:
4682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    static bool CanForce() {
46965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      // It's only safe to temporarily force support of CPU features
47065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      // when there's only a single isolate, which is guaranteed when
47165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      // the serializer is enabled.
47265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      return Serializer::enabled();
47365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
47465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
47565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    const unsigned old_supported_;
47665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  };
47765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
47865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch private:
47965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#ifdef DEBUG
48065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool initialized_;
48165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#endif
4822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  static unsigned supported_;
48365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static unsigned found_by_runtime_probing_;
48465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
48565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
48665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch};
48765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
48865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
48965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochclass Assembler : public AssemblerBase {
49065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch public:
49165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Create an assembler. Instructions and relocation information are emitted
49265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // into a buffer, with the instructions starting from the beginning and the
4932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // relocation information starting from the end of the buffer. See CodeDesc
4942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // for a detailed comment on the layout (globals.h).
49565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  //
49665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // If the provided buffer is NULL, the assembler allocates and grows its own
49765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // buffer, and buffer_size determines the initial buffer size. The buffer is
49865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // owned by the assembler and deallocated upon destruction of the assembler.
49965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  //
50065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // If the provided buffer is not NULL, the assembler uses the provided buffer
50165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // for code generation and assumes its size to be buffer_size. If the buffer
50265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // is too small, a fatal error occurs. No deallocation of the buffer is done
50365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // upon destruction of the assembler.
50465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  Assembler(Isolate* isolate, void* buffer, int buffer_size);
50565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  ~Assembler();
50665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
50765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Overrides the default provided by FLAG_debug_code.
50865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
50965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
51065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // GetCode emits any pending (non-emitted) code and fills the descriptor
51165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // desc. GetCode() is idempotent; it returns the same result if no other
51265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Assembler functions are invoked in between GetCode() calls.
51365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void GetCode(CodeDesc* desc);
51465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
51565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Label operations & relative jumps (PPUM Appendix D).
51665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  //
51765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Takes a branch opcode (cc) and a label (L) and generates
51865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // either a backward branch or a forward branch and links it
51965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // to the label fixup chain. Usage:
52065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  //
52165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Label L;    // unbound label
52265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // j(cc, &L);  // forward branch to unbound label
52365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // bind(&L);   // bind label to the current pc
52465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // j(cc, &L);  // backward branch to bound label
52565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // bind(&L);   // illegal: a label may be bound only once
5262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  //
5272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // Note: The same Label can be used for forward and backward branches
5282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // but it may be bound only once.
5292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void bind(Label* L);  // Binds an unbound label L to current code position.
53065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Determines if Label is bound and near enough so that branch instruction
53165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // can be used to reach it, instead of jump instruction.
53265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  bool is_near(Label* L);
53365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
53465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Returns the branch offset to the given label from the current code
53565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // position. Links the label to the current position if it is still unbound.
53665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Manages the jump elimination optimization if the second parameter is true.
53765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  int32_t branch_offset(Label* L, bool jump_elimination_allowed);
53865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  int32_t shifted_branch_offset(Label* L, bool jump_elimination_allowed) {
5392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    int32_t o = branch_offset(L, jump_elimination_allowed);
5402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT((o & 3) == 0);   // Assert the offset is aligned.
54165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return o >> 2;
54265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
5432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  uint32_t jump_address(Label* L);
5442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
54565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Puts a labels target address at the given position.
54665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // The high 8 bits are set to zero.
5472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void label_at_put(Label* L, int at_offset);
54865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
54965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Read/Modify the code target address in the branch/call instruction at pc.
55065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static Address target_address_at(Address pc);
55165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static void set_target_address_at(Address pc, Address target);
55265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
55365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static void JumpLabelToJumpRegister(Address pc);
55465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
55565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // This sets the branch destination (which gets loaded at the call address).
55665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // This is for calls and branches within generated code.  The serializer
55765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // has already deserialized the lui/ori instructions etc.
55865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  inline static void deserialization_set_special_target_at(
55965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      Address instruction_payload, Address target) {
56065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    set_target_address_at(
56165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        instruction_payload - kInstructionsFor32BitConstant * kInstrSize,
56265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        target);
56365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
56465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
56565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // This sets the branch destination.
56665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // This is for calls and branches to runtime code.
56765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  inline static void set_external_target_at(Address instruction_payload,
56865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                                            Address target) {
56965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    set_target_address_at(instruction_payload, target);
57065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
57165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
57265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Size of an instruction.
57365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static const int kInstrSize = sizeof(Instr);
57465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
57565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Difference between address of current opcode and target address offset.
57665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static const int kBranchPCOffset = 4;
57765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
57865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Here we are patching the address in the LUI/ORI instruction pair.
57965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // These values are used in the serialization process and must be zero for
58065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // MIPS platform, as Code, Embedded Object or External-reference pointers
58165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // are split across two consecutive instructions and don't exist separately
58265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // in the code, so the serializer should not step forwards in memory after
58365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // a target is resolved and written.
58465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static const int kSpecialTargetSize = 0;
58565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
58665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Number of consecutive instructions used to store 32bit constant.
58765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Before jump-optimizations, this constant was used in
58865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // RelocInfo::target_address_address() function to tell serializer address of
58965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // the instruction that follows LUI/ORI instruction pair. Now, with new jump
59065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // optimization, where jump-through-register instruction that usually
59165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // follows LUI/ORI pair is substituted with J/JAL, this constant equals
59265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // to 3 instructions (LUI+ORI+J/JAL/JR/JALR).
59365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static const int kInstructionsFor32BitConstant = 3;
59465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
59565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Distance between the instruction referring to the address of the call
59665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // target and the return address.
59765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static const int kCallTargetAddressOffset = 4 * kInstrSize;
59865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
59965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Distance between start of patched return sequence and the emitted address
60065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // to jump to.
60165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static const int kPatchReturnSequenceAddressOffset = 0;
60265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
60365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Distance between start of patched debug break slot and the emitted address
60465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // to jump to.
60565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static const int kPatchDebugBreakSlotAddressOffset =  0 * kInstrSize;
60665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
60765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Difference between address of current opcode and value read from pc
60865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // register.
60965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static const int kPcLoadDelta = 4;
61065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
61165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Number of instructions used for the JS return sequence. The constant is
61265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // used by the debugger to patch the JS return sequence.
61365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static const int kJSReturnSequenceInstructions = 7;
61465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static const int kDebugBreakSlotInstructions = 4;
61565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static const int kDebugBreakSlotLength =
61665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      kDebugBreakSlotInstructions * kInstrSize;
61765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
61865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
61965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // ---------------------------------------------------------------------------
62065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Code generation.
62165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
62265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Insert the smallest number of nop instructions
62365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // possible to align the pc offset to a multiple
62465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // of m. m must be a power of 2 (>= 4).
62565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void Align(int m);
62665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Aligns code to something that's optimal for a jump target for the platform.
62765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void CodeTargetAlign();
62865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
62965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Different nop operations are used by the code generator to detect certain
63065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // states of the generated code.
63165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  enum NopMarkerTypes {
63265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    NON_MARKING_NOP = 0,
63365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    DEBUG_BREAK_NOP,
63465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // IC markers.
63565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    PROPERTY_ACCESS_INLINED,
63665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    PROPERTY_ACCESS_INLINED_CONTEXT,
63765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
63865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Helper values.
63965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    LAST_CODE_MARKER,
64065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
64165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  };
64265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
6432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // Type == 0 is the default non-marking type.
64465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void nop(unsigned int type = 0) {
64565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(type < 32);
64665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    sll(zero_reg, zero_reg, type, true);
64765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
64865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
64965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
65065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // --------Branch-and-jump-instructions----------
65165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // We don't use likely variant of instructions.
6522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void b(int16_t offset);
6532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void b(Label* L) { b(branch_offset(L, false)>>2); }
6542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void bal(int16_t offset);
65565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void bal(Label* L) { bal(branch_offset(L, false)>>2); }
65665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
65765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void beq(Register rs, Register rt, int16_t offset);
65865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void beq(Register rs, Register rt, Label* L) {
65965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    beq(rs, rt, branch_offset(L, false) >> 2);
66065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
66165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void bgez(Register rs, int16_t offset);
66265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void bgezal(Register rs, int16_t offset);
66365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void bgtz(Register rs, int16_t offset);
66465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void blez(Register rs, int16_t offset);
66565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void bltz(Register rs, int16_t offset);
66665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void bltzal(Register rs, int16_t offset);
66765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void bne(Register rs, Register rt, int16_t offset);
66865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void bne(Register rs, Register rt, Label* L) {
669ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    bne(rs, rt, branch_offset(L, false)>>2);
670ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch  }
671ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
672ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch  // Never use the int16_t b(l)cond version with a branch offset
673ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch  // instead of using the Label* version.
674ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
67581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch  // Jump targets must be in the current 256 MB-aligned region. i.e. 28 bits.
67681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch  void j(int32_t target);
67781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch  void jal(int32_t target);
67881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch  void jalr(Register rs, Register rd = ra);
67981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch  void jr(Register target);
68081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch  void j_or_jr(int32_t target, Register rs);
68181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch  void jal_or_jalr(int32_t target, Register rs);
68281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
68365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
68465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  //-------Data-processing-instructions---------
68565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
68665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Arithmetic.
68765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void addu(Register rd, Register rs, Register rt);
68865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void subu(Register rd, Register rs, Register rt);
68965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void mult(Register rs, Register rt);
69065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void multu(Register rs, Register rt);
69165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void div(Register rs, Register rt);
69265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void divu(Register rs, Register rt);
69365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void mul(Register rd, Register rs, Register rt);
69465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
69565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void addiu(Register rd, Register rs, int32_t j);
69665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
69765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Logical.
69865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void and_(Register rd, Register rs, Register rt);
69965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void or_(Register rd, Register rs, Register rt);
70065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void xor_(Register rd, Register rs, Register rt);
70165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void nor(Register rd, Register rs, Register rt);
70265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
70365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void andi(Register rd, Register rs, int32_t j);
70465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void ori(Register rd, Register rs, int32_t j);
70565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void xori(Register rd, Register rs, int32_t j);
70665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void lui(Register rd, int32_t j);
70765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
70865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Shifts.
70965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Please note: sll(zero_reg, zero_reg, x) instructions are reserved as nop
71065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // and may cause problems in normal code. coming_from_nop makes sure this
71165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // doesn't happen.
7122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void sll(Register rd, Register rt, uint16_t sa, bool coming_from_nop = false);
7132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void sllv(Register rd, Register rt, Register rs);
7142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void srl(Register rd, Register rt, uint16_t sa);
7152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void srlv(Register rd, Register rt, Register rs);
71665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void sra(Register rt, Register rd, uint16_t sa);
71765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void srav(Register rt, Register rd, Register rs);
71865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void rotr(Register rd, Register rt, uint16_t sa);
71965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void rotrv(Register rd, Register rt, Register rs);
72065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
72165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
72265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  //------------Memory-instructions-------------
72365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
72465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void lb(Register rd, const MemOperand& rs);
72565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void lbu(Register rd, const MemOperand& rs);
72665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void lh(Register rd, const MemOperand& rs);
72765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void lhu(Register rd, const MemOperand& rs);
72865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void lw(Register rd, const MemOperand& rs);
72965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void lwl(Register rd, const MemOperand& rs);
73065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void lwr(Register rd, const MemOperand& rs);
73165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void sb(Register rd, const MemOperand& rs);
73265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void sh(Register rd, const MemOperand& rs);
73365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void sw(Register rd, const MemOperand& rs);
73465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void swl(Register rd, const MemOperand& rs);
73565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void swr(Register rd, const MemOperand& rs);
73665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
73765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
73865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  //-------------Misc-instructions--------------
73965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
74065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Break / Trap instructions.
74165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void break_(uint32_t code, bool break_as_stop = false);
74265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void stop(const char* msg, uint32_t code = kMaxStopCode);
74365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void tge(Register rs, Register rt, uint16_t code);
74465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void tgeu(Register rs, Register rt, uint16_t code);
74565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void tlt(Register rs, Register rt, uint16_t code);
74665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void tltu(Register rs, Register rt, uint16_t code);
74765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void teq(Register rs, Register rt, uint16_t code);
74865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void tne(Register rs, Register rt, uint16_t code);
74965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
75065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Move from HI/LO register.
75165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void mfhi(Register rd);
75265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void mflo(Register rd);
75365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
75465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Set on less than.
75565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void slt(Register rd, Register rs, Register rt);
75665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void sltu(Register rd, Register rs, Register rt);
75765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void slti(Register rd, Register rs, int32_t j);
75865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void sltiu(Register rd, Register rs, int32_t j);
75965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
76065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Conditional move.
76165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void movz(Register rd, Register rs, Register rt);
76265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void movn(Register rd, Register rs, Register rt);
76365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void movt(Register rd, Register rs, uint16_t cc = 0);
76465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void movf(Register rd, Register rs, uint16_t cc = 0);
76565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
76665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Bit twiddling.
76765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void clz(Register rd, Register rs);
76865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void ins_(Register rt, Register rs, uint16_t pos, uint16_t size);
76965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void ext_(Register rt, Register rs, uint16_t pos, uint16_t size);
77065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
77165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  //--------Coprocessor-instructions----------------
77265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
77365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Load, store, and move.
77465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void lwc1(FPURegister fd, const MemOperand& src);
77565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void ldc1(FPURegister fd, const MemOperand& src);
77665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
77765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void swc1(FPURegister fs, const MemOperand& dst);
77865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void sdc1(FPURegister fs, const MemOperand& dst);
77965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
78065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void mtc1(Register rt, FPURegister fs);
78165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void mfc1(Register rt, FPURegister fs);
78265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
78365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void ctc1(Register rt, FPUControlRegister fs);
78465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void cfc1(Register rt, FPUControlRegister fs);
78565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
78665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Arithmetic.
78765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void add_d(FPURegister fd, FPURegister fs, FPURegister ft);
78865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void sub_d(FPURegister fd, FPURegister fs, FPURegister ft);
78965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void mul_d(FPURegister fd, FPURegister fs, FPURegister ft);
79065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void div_d(FPURegister fd, FPURegister fs, FPURegister ft);
79165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void abs_d(FPURegister fd, FPURegister fs);
79265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void mov_d(FPURegister fd, FPURegister fs);
79365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void neg_d(FPURegister fd, FPURegister fs);
79465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void sqrt_d(FPURegister fd, FPURegister fs);
79565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
79665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Conversion.
79765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void cvt_w_s(FPURegister fd, FPURegister fs);
79865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void cvt_w_d(FPURegister fd, FPURegister fs);
79965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void trunc_w_s(FPURegister fd, FPURegister fs);
80065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void trunc_w_d(FPURegister fd, FPURegister fs);
80165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void round_w_s(FPURegister fd, FPURegister fs);
80265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void round_w_d(FPURegister fd, FPURegister fs);
80365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void floor_w_s(FPURegister fd, FPURegister fs);
80465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void floor_w_d(FPURegister fd, FPURegister fs);
80565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void ceil_w_s(FPURegister fd, FPURegister fs);
80665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void ceil_w_d(FPURegister fd, FPURegister fs);
80765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
80865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void cvt_l_s(FPURegister fd, FPURegister fs);
80965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void cvt_l_d(FPURegister fd, FPURegister fs);
81065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void trunc_l_s(FPURegister fd, FPURegister fs);
81165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void trunc_l_d(FPURegister fd, FPURegister fs);
81265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void round_l_s(FPURegister fd, FPURegister fs);
81365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void round_l_d(FPURegister fd, FPURegister fs);
81465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void floor_l_s(FPURegister fd, FPURegister fs);
81565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void floor_l_d(FPURegister fd, FPURegister fs);
81665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void ceil_l_s(FPURegister fd, FPURegister fs);
81765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void ceil_l_d(FPURegister fd, FPURegister fs);
81865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
81965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void cvt_s_w(FPURegister fd, FPURegister fs);
82065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void cvt_s_l(FPURegister fd, FPURegister fs);
82165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void cvt_s_d(FPURegister fd, FPURegister fs);
82265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
82365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void cvt_d_w(FPURegister fd, FPURegister fs);
82465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void cvt_d_l(FPURegister fd, FPURegister fs);
82565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void cvt_d_s(FPURegister fd, FPURegister fs);
8262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
82765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Conditions and branches.
8282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void c(FPUCondition cond, SecondaryField fmt,
82965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch         FPURegister ft, FPURegister fs, uint16_t cc = 0);
8302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
83165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void bc1f(int16_t offset, uint16_t cc = 0);
83265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void bc1f(Label* L, uint16_t cc = 0) { bc1f(branch_offset(L, false)>>2, cc); }
83365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void bc1t(int16_t offset, uint16_t cc = 0);
83465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void bc1t(Label* L, uint16_t cc = 0) { bc1t(branch_offset(L, false)>>2, cc); }
83565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void fcmp(FPURegister src1, const double src2, FPUCondition cond);
83665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
83765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Check the code size generated from label to here.
83865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  int SizeOfCodeGeneratedSince(Label* label) {
83965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return pc_offset() - label->pos();
84065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
84165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
84265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Check the number of instructions generated from label to here.
84365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  int InstructionsGeneratedSince(Label* label) {
84465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return SizeOfCodeGeneratedSince(label) / kInstrSize;
84565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
84665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
84765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Class for scoping postponing the trampoline pool generation.
84865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  class BlockTrampolinePoolScope {
84965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch   public:
85065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) {
85165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      assem_->StartBlockTrampolinePool();
85265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
85365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ~BlockTrampolinePoolScope() {
85465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      assem_->EndBlockTrampolinePool();
85565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
85665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
85765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch   private:
85865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    Assembler* assem_;
85965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
86065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope);
86165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  };
86265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
86365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Class for postponing the assembly buffer growth. Typically used for
86465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // sequences of instructions that must be emitted as a unit, before
86565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // buffer growth (and relocation) can occur.
86665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // This blocking scope is not nestable.
86765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  class BlockGrowBufferScope {
86865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch   public:
86965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    explicit BlockGrowBufferScope(Assembler* assem) : assem_(assem) {
87065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      assem_->StartBlockGrowBuffer();
87165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
87265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ~BlockGrowBufferScope() {
87365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      assem_->EndBlockGrowBuffer();
87465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
87565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
87665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    private:
87765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch     Assembler* assem_;
87865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
87965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch     DISALLOW_IMPLICIT_CONSTRUCTORS(BlockGrowBufferScope);
88065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  };
88165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
88265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Debugging.
88365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
88465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Mark address of the ExitJSFrame code.
88565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void RecordJSReturn();
88665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
88765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Mark address of a debug break slot.
88865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void RecordDebugBreakSlot();
88965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
89065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Record the AST id of the CallIC being compiled, so that it can be placed
89165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // in the relocation information.
89265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void SetRecordedAstId(unsigned ast_id) {
89365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(recorded_ast_id_ == kNoASTId);
89465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    recorded_ast_id_ = ast_id;
89565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
89665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
89765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  unsigned RecordedAstId() {
89865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(recorded_ast_id_ != kNoASTId);
89965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return recorded_ast_id_;
90065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
90165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
90265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void ClearRecordedAstId() { recorded_ast_id_ = kNoASTId; }
90365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
90465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Record a comment relocation entry that can be used by a disassembler.
90565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Use --code-comments to enable.
90665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void RecordComment(const char* msg);
90765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
90865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static int RelocateInternalReference(byte* pc, intptr_t pc_delta);
90965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
91065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Writes a single byte or word of data in the code stream.  Used for
91165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // inline tables, e.g., jump-tables.
91265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void db(uint8_t data);
91365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void dd(uint32_t data);
91465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
91565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  int32_t pc_offset() const { return pc_ - buffer_; }
91665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
91765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  PositionsRecorder* positions_recorder() { return &positions_recorder_; }
91865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
91965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Postpone the generation of the trampoline pool for the specified number of
92065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // instructions.
92165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void BlockTrampolinePoolFor(int instructions);
92265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
92365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Check if there is less than kGap bytes available in the buffer.
92465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // If this is the case, we need to grow the buffer before emitting
92565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // an instruction or relocation information.
92665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; }
92765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
92865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Get the number of bytes available in the buffer.
92965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  inline int available_space() const { return reloc_info_writer.pos() - pc_; }
93065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
93165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Read/patch instructions.
93265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
93365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static void instr_at_put(byte* pc, Instr instr) {
93465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    *reinterpret_cast<Instr*>(pc) = instr;
93565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
93665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
93765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void instr_at_put(int pos, Instr instr) {
93865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
93965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
94065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
94165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Check if an instruction is a branch of some kind.
94265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsBranch(Instr instr);
94365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsBeq(Instr instr);
94465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsBne(Instr instr);
94565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
94665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsJump(Instr instr);
94765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsJ(Instr instr);
94865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsLui(Instr instr);
94965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsOri(Instr instr);
95065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
95165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsJal(Instr instr);
95265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsJr(Instr instr);
95365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsJalr(Instr instr);
95465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
95565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsNop(Instr instr, unsigned int type);
95665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsPop(Instr instr);
95765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsPush(Instr instr);
95865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsLwRegFpOffset(Instr instr);
95965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsSwRegFpOffset(Instr instr);
96065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsLwRegFpNegOffset(Instr instr);
96165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsSwRegFpNegOffset(Instr instr);
96265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
96365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static Register GetRtReg(Instr instr);
96465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static Register GetRsReg(Instr instr);
96565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static Register GetRdReg(Instr instr);
96665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
96765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static uint32_t GetRt(Instr instr);
96865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static uint32_t GetRtField(Instr instr);
96965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static uint32_t GetRs(Instr instr);
97065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static uint32_t GetRsField(Instr instr);
97165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static uint32_t GetRd(Instr instr);
97265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static uint32_t GetRdField(Instr instr);
97365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static uint32_t GetSa(Instr instr);
97465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static uint32_t GetSaField(Instr instr);
97565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static uint32_t GetOpcodeField(Instr instr);
97665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static uint32_t GetFunction(Instr instr);
97765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static uint32_t GetFunctionField(Instr instr);
97865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static uint32_t GetImmediate16(Instr instr);
97965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static uint32_t GetLabelConst(Instr instr);
98065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
98165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static int32_t GetBranchOffset(Instr instr);
98265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsLw(Instr instr);
98365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static int16_t GetLwOffset(Instr instr);
98465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static Instr SetLwOffset(Instr instr, int16_t offset);
98565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
98665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsSw(Instr instr);
98765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static Instr SetSwOffset(Instr instr, int16_t offset);
98865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsAddImmediate(Instr instr);
98965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static Instr SetAddImmediateOffset(Instr instr, int16_t offset);
99065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
99165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static bool IsAndImmediate(Instr instr);
99265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
99365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void CheckTrampolinePool();
99465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
99565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch protected:
99665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Relocation for a type-recording IC has the AST id added to it.  This
99765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // member variable is a way to pass the information from the call site to
99865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // the relocation info.
99965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  unsigned recorded_ast_id_;
100065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
100165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  bool emit_debug_code() const { return emit_debug_code_; }
100265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
100365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  int32_t buffer_space() const { return reloc_info_writer.pos() - pc_; }
100465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
100565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Decode branch instruction at pos and return branch target pos.
100665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  int target_at(int32_t pos);
100765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
100865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Patch branch instruction at pos to branch to given branch target pos.
100965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void target_at_put(int32_t pos, int32_t target_pos);
101065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
101165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Say if we need to relocate with this mode.
101265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  bool MustUseReg(RelocInfo::Mode rmode);
101365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
101465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Record reloc info for current pc_.
101565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
101665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
101765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Block the emission of the trampoline pool before pc_offset.
101865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void BlockTrampolinePoolBefore(int pc_offset) {
101965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (no_trampoline_pool_before_ < pc_offset)
102065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      no_trampoline_pool_before_ = pc_offset;
102165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
102265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
102365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void StartBlockTrampolinePool() {
102465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    trampoline_pool_blocked_nesting_++;
102565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
102665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
102765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void EndBlockTrampolinePool() {
102865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    trampoline_pool_blocked_nesting_--;
102965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
103065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
103165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  bool is_trampoline_pool_blocked() const {
103265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return trampoline_pool_blocked_nesting_ > 0;
103365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
103465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
103565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  bool has_exception() const {
103665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return internal_trampoline_exception_;
103765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
103865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
103965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi);
104065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
104165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  bool is_trampoline_emitted() const {
104265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return trampoline_emitted_;
104365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
104465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
104565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Temporarily block automatic assembly buffer growth.
104665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void StartBlockGrowBuffer() {
104765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(!block_buffer_growth_);
10482fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    block_buffer_growth_ = true;
10492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  }
105065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
10512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void EndBlockGrowBuffer() {
10522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(block_buffer_growth_);
105365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    block_buffer_growth_ = false;
105465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
105565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
105665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  bool is_buffer_growth_blocked() const {
105765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return block_buffer_growth_;
105865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  }
105965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
106065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch private:
106165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Code buffer:
106265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // The buffer into which code and relocation info are generated.
106365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  byte* buffer_;
106465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  int buffer_size_;
106565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // True if the assembler owns the buffer, false if buffer is external.
106665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  bool own_buffer_;
106765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
106865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Buffer size and constant pool distance are checked together at regular
106965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // intervals of kBufferCheckInterval emitted bytes.
107065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static const int kBufferCheckInterval = 1*KB/2;
10712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
107265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Code generation.
107365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // The relocation writer's position is at least kGap bytes below the end of
107465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // the generated instructions. This is so that multi-instruction sequences do
10752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // not have to check for overflow. The same is true for writes of large
10762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // relocation info entries.
107765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static const int kGap = 32;
107865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  byte* pc_;  // The program counter - moves forward.
107965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
108065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
108165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Repeated checking whether the trampoline pool should be emitted is rather
108265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // expensive. By default we only check again once a number of instructions
108365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // has been generated.
108465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static const int kCheckConstIntervalInst = 32;
108565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize;
108665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
108765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  int next_buffer_check_;  // pc offset of next buffer check.
108865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
10892fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // Emission of the trampoline pool may be blocked in some code sequences.
109065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  int trampoline_pool_blocked_nesting_;  // Block emission if this is not zero.
10912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  int no_trampoline_pool_before_;  // Block emission before this pc offset.
10922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
10932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // Keep track of the last emitted pool to guarantee a maximal distance.
10942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  int last_trampoline_pool_end_;  // pc offset of the end of the last pool.
10952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
10962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // Automatic growth of the assembly buffer may be blocked for some sequences.
10972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  bool block_buffer_growth_;  // Block growth when true.
10982fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
10992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // Relocation information generation.
11002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // Each relocation is encoded as a variable size value.
11012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
11022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  RelocInfoWriter reloc_info_writer;
11032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
11042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // The bound position, before this we cannot do instruction elimination.
11052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  int last_bound_pos_;
11062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
11072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // Code emission.
11082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  inline void CheckBuffer();
11092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void GrowBuffer();
11102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  inline void emit(Instr x);
11112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  inline void CheckTrampolinePoolQuick();
11122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
11132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // Instruction generation.
11142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // We have 3 different kind of encoding layout on MIPS.
11152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // However due to many different types of objects encoded in the same fields
11162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // we have quite a few aliases for each mode.
11172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // Using the same structure to refer to Register and FPURegister would spare a
11182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // few aliases, but mixing both does not look clean to me.
11192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // Anyway we could surely implement this differently.
11202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
11212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void GenInstrRegister(Opcode opcode,
11222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        Register rs,
11232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        Register rt,
11242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        Register rd,
11252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        uint16_t sa = 0,
11262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        SecondaryField func = NULLSF);
11272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
11282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void GenInstrRegister(Opcode opcode,
11292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        Register rs,
11302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        Register rt,
11312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        uint16_t msb,
11322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        uint16_t lsb,
11332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        SecondaryField func);
11342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
11352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void GenInstrRegister(Opcode opcode,
11362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        SecondaryField fmt,
113765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                        FPURegister ft,
113865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                        FPURegister fs,
113965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                        FPURegister fd,
114065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                        SecondaryField func = NULLSF);
114165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
114265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void GenInstrRegister(Opcode opcode,
114381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                        SecondaryField fmt,
114465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                        Register rt,
114565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                        FPURegister fs,
114665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                        FPURegister fd,
114765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                        SecondaryField func = NULLSF);
114865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
114965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void GenInstrRegister(Opcode opcode,
115065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                        SecondaryField fmt,
115165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                        Register rt,
115265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                        FPUControlRegister fs,
115365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                        SecondaryField func = NULLSF);
115465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
115565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
11562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void GenInstrImmediate(Opcode opcode,
11572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                         Register rs,
11582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                         Register rt,
11592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                         int32_t  j);
116065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void GenInstrImmediate(Opcode opcode,
116165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                         Register rs,
116265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                         SecondaryField SF,
116365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                         int32_t  j);
116465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  void GenInstrImmediate(Opcode opcode,
116565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                         Register r1,
116665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                         FPURegister r2,
116765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                         int32_t  j);
11682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
11692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
11702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void GenInstrJump(Opcode opcode,
11712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                     uint32_t address);
11722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
11732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // Helpers.
11742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void LoadRegPlusOffsetToAt(const MemOperand& src);
11752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
11762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // Labels.
11772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void print(Label* L);
11782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void bind_to(Label* L, int pos);
11792fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  void next(Label* L);
11802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
11812fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // One trampoline consists of:
118265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // - space for trampoline slots,
118365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // - space for labels.
118465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  //
118565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Space for trampoline slots is equal to slot_count * 2 * kInstrSize.
118665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // Space for trampoline slots preceeds space for labels. Each label is of one
118765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // instruction size, so total amount for labels is equal to
118865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  // label_count *  kInstrSize.
118965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch  class Trampoline {
119065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch   public:
119165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    Trampoline() {
119265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      start_ = 0;
119365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      next_slot_ = 0;
11942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      free_slot_count_ = 0;
11952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      end_ = 0;
11962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
11972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    Trampoline(int start, int slot_count) {
11982fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      start_ = start;
11992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      next_slot_ = start;
120065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      free_slot_count_ = slot_count;
120165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch      end_ = start + slot_count * kTrampolineSlotsSize;
120265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
12032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    int start() {
12042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      return start_;
12052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
12062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    int end() {
12072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      return end_;
12082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
12092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    int take_slot() {
12102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      int trampoline_slot = kInvalidSlotPos;
12112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      if (free_slot_count_ <= 0) {
12122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // We have run out of space on trampolines.
12132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // Make sure we fail in debug mode, so we become aware of each case
12142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // when this happens.
12152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        ASSERT(0);
12162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // Internal exception will be caught.
12172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      } else {
12182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        trampoline_slot = next_slot_;
12192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        free_slot_count_--;
12202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        next_slot_ += kTrampolineSlotsSize;
12212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      }
12222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block      return trampoline_slot;
12232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
12242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
12252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block   private:
12262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    int start_;
12272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    int end_;
12282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    int next_slot_;
12292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    int free_slot_count_;
12302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  };
12312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
12322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  int32_t get_trampoline_entry(int32_t pos);
12332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  int unbound_labels_count_;
12342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // If trampoline is emitted, generated code is becoming large. As this is
12352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // already a slow case which can possibly break our code generation for the
12362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // extreme case, we use this information to trigger different mode of
12372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // branch instruction generation, where we use jump instructions rather
12382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  // than regular branch instructions.
12392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  bool trampoline_emitted_;
12402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  static const int kTrampolineSlotsSize = 4 * kInstrSize;
12412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  static const int kMaxBranchOffset = (1 << (18 - 1)) - 1;
12422fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  static const int kInvalidSlotPos = -1;
12432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
12442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  Trampoline trampoline_;
12452fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  bool internal_trampoline_exception_;
12462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
12472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  friend class RegExpMacroAssemblerMIPS;
12482fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  friend class RelocInfo;
12492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  friend class CodePatcher;
12502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  friend class BlockTrampolinePoolScope;
12512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
12522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  PositionsRecorder positions_recorder_;
12532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  bool emit_debug_code_;
12542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  friend class PositionsRecorder;
12552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  friend class EnsureSpace;
12562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block};
12572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
12582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
12592fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockclass EnsureSpace BASE_EMBEDDED {
12602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block public:
12612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  explicit EnsureSpace(Assembler* assembler) {
12622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    assembler->CheckBuffer();
12632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  }
12642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block};
12652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
12662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} }  // namespace v8::internal
12672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
12682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#endif  // V8_ARM_ASSEMBLER_MIPS_H_
12692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block