15c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Copyright (c) 1994-2006 Sun Microsystems Inc.
25c838251403b0be9a882540f1922577abba4c872ager@chromium.org// All Rights Reserved.
35c838251403b0be9a882540f1922577abba4c872ager@chromium.org//
45c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Redistribution and use in source and binary forms, with or without
55c838251403b0be9a882540f1922577abba4c872ager@chromium.org// modification, are permitted provided that the following conditions are
65c838251403b0be9a882540f1922577abba4c872ager@chromium.org// met:
75c838251403b0be9a882540f1922577abba4c872ager@chromium.org//
85c838251403b0be9a882540f1922577abba4c872ager@chromium.org// - Redistributions of source code must retain the above copyright notice,
95c838251403b0be9a882540f1922577abba4c872ager@chromium.org// this list of conditions and the following disclaimer.
105c838251403b0be9a882540f1922577abba4c872ager@chromium.org//
115c838251403b0be9a882540f1922577abba4c872ager@chromium.org// - Redistribution in binary form must reproduce the above copyright
125c838251403b0be9a882540f1922577abba4c872ager@chromium.org// notice, this list of conditions and the following disclaimer in the
135c838251403b0be9a882540f1922577abba4c872ager@chromium.org// documentation and/or other materials provided with the distribution.
145c838251403b0be9a882540f1922577abba4c872ager@chromium.org//
155c838251403b0be9a882540f1922577abba4c872ager@chromium.org// - Neither the name of Sun Microsystems or the names of contributors may
165c838251403b0be9a882540f1922577abba4c872ager@chromium.org// be used to endorse or promote products derived from this software without
175c838251403b0be9a882540f1922577abba4c872ager@chromium.org// specific prior written permission.
185c838251403b0be9a882540f1922577abba4c872ager@chromium.org//
195c838251403b0be9a882540f1922577abba4c872ager@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
205c838251403b0be9a882540f1922577abba4c872ager@chromium.org// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
215c838251403b0be9a882540f1922577abba4c872ager@chromium.org// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
225c838251403b0be9a882540f1922577abba4c872ager@chromium.org// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
235c838251403b0be9a882540f1922577abba4c872ager@chromium.org// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
245c838251403b0be9a882540f1922577abba4c872ager@chromium.org// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
255c838251403b0be9a882540f1922577abba4c872ager@chromium.org// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
265c838251403b0be9a882540f1922577abba4c872ager@chromium.org// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
275c838251403b0be9a882540f1922577abba4c872ager@chromium.org// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
285c838251403b0be9a882540f1922577abba4c872ager@chromium.org// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
295c838251403b0be9a882540f1922577abba4c872ager@chromium.org// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
305c838251403b0be9a882540f1922577abba4c872ager@chromium.org
315c838251403b0be9a882540f1922577abba4c872ager@chromium.org// The original source code covered by the above license above has been
325c838251403b0be9a882540f1922577abba4c872ager@chromium.org// modified significantly by Google Inc.
332efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
345c838251403b0be9a882540f1922577abba4c872ager@chromium.org
355c838251403b0be9a882540f1922577abba4c872ager@chromium.org
365c838251403b0be9a882540f1922577abba4c872ager@chromium.org#ifndef V8_MIPS_ASSEMBLER_MIPS_H_
375c838251403b0be9a882540f1922577abba4c872ager@chromium.org#define V8_MIPS_ASSEMBLER_MIPS_H_
385c838251403b0be9a882540f1922577abba4c872ager@chromium.org
395c838251403b0be9a882540f1922577abba4c872ager@chromium.org#include <stdio.h>
4069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org
41196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/assembler.h"
42196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/mips/constants-mips.h"
43196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/serialize.h"
445c838251403b0be9a882540f1922577abba4c872ager@chromium.org
455c838251403b0be9a882540f1922577abba4c872ager@chromium.orgnamespace v8 {
465c838251403b0be9a882540f1922577abba4c872ager@chromium.orgnamespace internal {
475c838251403b0be9a882540f1922577abba4c872ager@chromium.org
485c838251403b0be9a882540f1922577abba4c872ager@chromium.org// CPU Registers.
495c838251403b0be9a882540f1922577abba4c872ager@chromium.org//
505c838251403b0be9a882540f1922577abba4c872ager@chromium.org// 1) We would prefer to use an enum, but enum values are assignment-
515c838251403b0be9a882540f1922577abba4c872ager@chromium.org// compatible with int, which has caused code-generation bugs.
525c838251403b0be9a882540f1922577abba4c872ager@chromium.org//
535c838251403b0be9a882540f1922577abba4c872ager@chromium.org// 2) We would prefer to use a class instead of a struct but we don't like
545c838251403b0be9a882540f1922577abba4c872ager@chromium.org// the register initialization to depend on the particular initialization
555c838251403b0be9a882540f1922577abba4c872ager@chromium.org// order (which appears to be different on OS X, Linux, and Windows for the
565c838251403b0be9a882540f1922577abba4c872ager@chromium.org// installed versions of C++ we tried). Using a struct permits C-style
575c838251403b0be9a882540f1922577abba4c872ager@chromium.org// "initialization". Also, the Register objects cannot be const as this
585c838251403b0be9a882540f1922577abba4c872ager@chromium.org// forces initialization stubs in MSVC, making us dependent on initialization
595c838251403b0be9a882540f1922577abba4c872ager@chromium.org// order.
605c838251403b0be9a882540f1922577abba4c872ager@chromium.org//
615c838251403b0be9a882540f1922577abba4c872ager@chromium.org// 3) By not using an enum, we are possibly preventing the compiler from
625c838251403b0be9a882540f1922577abba4c872ager@chromium.org// doing certain constant folds, which may significantly reduce the
635c838251403b0be9a882540f1922577abba4c872ager@chromium.org// code generated for some assembly instructions (because they boil down
645c838251403b0be9a882540f1922577abba4c872ager@chromium.org// to a few constants). If this is a problem, we could change the code
655c838251403b0be9a882540f1922577abba4c872ager@chromium.org// such that we use an enum in optimized mode, and the struct in debug
665c838251403b0be9a882540f1922577abba4c872ager@chromium.org// mode. This way we get the compile-time error checking in debug mode
675c838251403b0be9a882540f1922577abba4c872ager@chromium.org// and best performance in optimized code.
685c838251403b0be9a882540f1922577abba4c872ager@chromium.org
695c838251403b0be9a882540f1922577abba4c872ager@chromium.org
705c838251403b0be9a882540f1922577abba4c872ager@chromium.org// -----------------------------------------------------------------------------
7183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org// Implementation of Register and FPURegister.
725c838251403b0be9a882540f1922577abba4c872ager@chromium.org
735c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Core register.
745c838251403b0be9a882540f1922577abba4c872ager@chromium.orgstruct Register {
757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kNumRegisters = v8::internal::kNumRegisters;
76fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  static const int kMaxNumAllocatableRegisters = 14;  // v0 through t6 and cp.
7783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static const int kSizeInBytes = 4;
78fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  static const int kCpRegister = 23;  // cp (s7) is the 23rd register.
7959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
80731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org#if defined(V8_TARGET_LITTLE_ENDIAN)
81731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  static const int kMantissaOffset = 0;
82731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  static const int kExponentOffset = 4;
83731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org#elif defined(V8_TARGET_BIG_ENDIAN)
84731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  static const int kMantissaOffset = 4;
85731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  static const int kExponentOffset = 0;
86731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org#else
87731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org#error Unknown endianness
88731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org#endif
89731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org
9059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  inline static int NumAllocatableRegisters();
917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static int ToAllocationIndex(Register reg) {
93fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org    ASSERT((reg.code() - 2) < (kMaxNumAllocatableRegisters - 1) ||
94fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org           reg.is(from_code(kCpRegister)));
95fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org    return reg.is(from_code(kCpRegister)) ?
96fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org           kMaxNumAllocatableRegisters - 1 :  // Return last index for 'cp'.
97fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org           reg.code() - 2;  // zero_reg and 'at' are skipped.
987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static Register FromAllocationIndex(int index) {
10159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
102fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org    return index == kMaxNumAllocatableRegisters - 1 ?
103fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org           from_code(kCpRegister) :  // Last index is always the 'cp' register.
104fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org           from_code(index + 2);  // zero_reg and 'at' are skipped.
1057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
1067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const char* AllocationIndexToString(int index) {
10859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
1097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    const char* const names[] = {
1107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "v0",
1117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "v1",
1127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "a0",
1137516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "a1",
1147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "a2",
1157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "a3",
1167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "t0",
1177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "t1",
1187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "t2",
1197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "t3",
1207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "t4",
1217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "t5",
1227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "t6",
123fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org      "s7",
1247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    };
1257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    return names[index];
1267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
1277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static Register from_code(int code) {
1297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    Register r = { code };
1307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    return r;
1317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
1327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1334a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
1344a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  bool is(Register reg) const { return code_ == reg.code_; }
1354a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  int code() const {
1365c838251403b0be9a882540f1922577abba4c872ager@chromium.org    ASSERT(is_valid());
1375c838251403b0be9a882540f1922577abba4c872ager@chromium.org    return code_;
1385c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
1394a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  int bit() const {
1405c838251403b0be9a882540f1922577abba4c872ager@chromium.org    ASSERT(is_valid());
1415c838251403b0be9a882540f1922577abba4c872ager@chromium.org    return 1 << code_;
1425c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
1435c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1445c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Unfortunately we can't make this private in a struct.
1455c838251403b0be9a882540f1922577abba4c872ager@chromium.org  int code_;
1465c838251403b0be9a882540f1922577abba4c872ager@chromium.org};
1475c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1487d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org#define REGISTER(N, C) \
1497d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  const int kRegister_ ## N ## _Code = C; \
1507d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  const Register N = { C }
1517d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org
1527d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(no_reg, -1);
1537d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// Always zero.
1547d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(zero_reg, 0);
1557d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// at: Reserved for synthetic instructions.
1567d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(at, 1);
1577d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// v0, v1: Used when returning multiple values from subroutines.
1587d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(v0, 2);
1597d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(v1, 3);
1607d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// a0 - a4: Used to pass non-FP parameters.
1617d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(a0, 4);
1627d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(a1, 5);
1637d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(a2, 6);
1647d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(a3, 7);
1657d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// t0 - t9: Can be used without reservation, act as temporary registers and are
1667d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// allowed to be destroyed by subroutines.
1677d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t0, 8);
1687d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t1, 9);
1697d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t2, 10);
1707d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t3, 11);
1717d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t4, 12);
1727d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t5, 13);
1737d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t6, 14);
1747d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t7, 15);
1757d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// s0 - s7: Subroutine register variables. Subroutines that write to these
1767d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// registers must restore their values before exiting so that the caller can
1777d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// expect the values to be preserved.
1787d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s0, 16);
1797d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s1, 17);
1807d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s2, 18);
1817d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s3, 19);
1827d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s4, 20);
1837d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s5, 21);
1847d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s6, 22);
1857d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s7, 23);
1867d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t8, 24);
1877d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t9, 25);
1887d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// k0, k1: Reserved for system calls and interrupt handlers.
1897d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(k0, 26);
1907d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(k1, 27);
1917d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// gp: Reserved.
1927d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(gp, 28);
1937d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// sp: Stack pointer.
1947d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(sp, 29);
1957d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// fp: Frame pointer.
1967d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(fp, 30);
1977d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// ra: Return address pointer.
1987d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(ra, 31);
1997d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org
2007d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org#undef REGISTER
2017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2025c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2035c838251403b0be9a882540f1922577abba4c872ager@chromium.orgint ToNumber(Register reg);
2045c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2055c838251403b0be9a882540f1922577abba4c872ager@chromium.orgRegister ToRegister(int num);
2065c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2075c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Coprocessor register.
2085c838251403b0be9a882540f1922577abba4c872ager@chromium.orgstruct FPURegister {
2097c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org  static const int kMaxNumRegisters = v8::internal::kNumFPURegisters;
21034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
21134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // TODO(plind): Warning, inconsistent numbering here. kNumFPURegisters refers
21234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to
21334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // number of Double regs (64-bit regs, or FPU-reg-pairs).
21434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
21534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // A few double registers are reserved: one as a scratch register and one to
21634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // hold 0.0.
21734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  //  f28: 0.0
21834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  //  f30: scratch register.
21934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  static const int kNumReservedRegisters = 2;
2207c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org  static const int kMaxNumAllocatableRegisters = kMaxNumRegisters / 2 -
22134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      kNumReservedRegisters;
22234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
22359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  inline static int NumRegisters();
22459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  inline static int NumAllocatableRegisters();
2252efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  inline static int ToAllocationIndex(FPURegister reg);
22659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  static const char* AllocationIndexToString(int index);
2277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static FPURegister FromAllocationIndex(int index) {
22959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
23034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    return from_code(index * 2);
2317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
2327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static FPURegister from_code(int code) {
2347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    FPURegister r = { code };
2357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    return r;
2367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
2377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2387c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org  bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters ; }
2394a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  bool is(FPURegister creg) const { return code_ == creg.code_; }
24034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  FPURegister low() const {
24134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    // Find low reg of a Double-reg pair, which is the reg itself.
24234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    ASSERT(code_ % 2 == 0);  // Specified Double reg must be even.
24334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    FPURegister reg;
24434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    reg.code_ = code_;
24534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    ASSERT(reg.is_valid());
24634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    return reg;
24734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  }
24834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  FPURegister high() const {
24934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    // Find high reg of a Doubel-reg pair, which is reg + 1.
25034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    ASSERT(code_ % 2 == 0);  // Specified Double reg must be even.
25134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    FPURegister reg;
25234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    reg.code_ = code_ + 1;
25334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    ASSERT(reg.is_valid());
25434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    return reg;
25534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  }
25634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
2574a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  int code() const {
2585c838251403b0be9a882540f1922577abba4c872ager@chromium.org    ASSERT(is_valid());
2595c838251403b0be9a882540f1922577abba4c872ager@chromium.org    return code_;
2605c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
2614a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  int bit() const {
2625c838251403b0be9a882540f1922577abba4c872ager@chromium.org    ASSERT(is_valid());
2635c838251403b0be9a882540f1922577abba4c872ager@chromium.org    return 1 << code_;
2645c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
2657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void setcode(int f) {
2667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    code_ = f;
2677516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    ASSERT(is_valid());
2687516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
2695c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Unfortunately we can't make this private in a struct.
2705c838251403b0be9a882540f1922577abba4c872ager@chromium.org  int code_;
2715c838251403b0be9a882540f1922577abba4c872ager@chromium.org};
2725c838251403b0be9a882540f1922577abba4c872ager@chromium.org
27334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// V8 now supports the O32 ABI, and the FPU Registers are organized as 32
27434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// 32-bit registers, f0 through f31. When used as 'double' they are used
27534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// in pairs, starting with the even numbered register. So a double operation
27634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// on f0 really uses f0 and f1.
27734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// (Modern mips hardware also supports 32 64-bit registers, via setting
27834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// (priviledged) Status Register FR bit to 1. This is used by the N32 ABI,
27934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// but it is not in common use. Someday we will want to support this in v8.)
28034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
28134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// For O32 ABI, Floats and Doubles refer to same set of 32 32-bit registers.
2827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgtypedef FPURegister DoubleRegister;
28334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.orgtypedef FPURegister FloatRegister;
2847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
28534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.orgconst FPURegister no_freg = { -1 };
2867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f0 = { 0 };  // Return value in hard float mode.
2887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f1 = { 1 };
2897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f2 = { 2 };
2907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f3 = { 3 };
2917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f4 = { 4 };
2927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f5 = { 5 };
2937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f6 = { 6 };
2947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f7 = { 7 };
2957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f8 = { 8 };
2967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f9 = { 9 };
2977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f10 = { 10 };
2987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f11 = { 11 };
2997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f12 = { 12 };  // Arg 0 in hard float mode.
3007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f13 = { 13 };
3017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f14 = { 14 };  // Arg 1 in hard float mode.
3027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f15 = { 15 };
3037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f16 = { 16 };
3047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f17 = { 17 };
3057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f18 = { 18 };
3067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f19 = { 19 };
3077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f20 = { 20 };
3087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f21 = { 21 };
3097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f22 = { 22 };
3107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f23 = { 23 };
3117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f24 = { 24 };
3127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f25 = { 25 };
3137516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f26 = { 26 };
3147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f27 = { 27 };
3157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f28 = { 28 };
3167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f29 = { 29 };
3177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f30 = { 30 };
3187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f31 = { 31 };
3197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
3202efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org// Register aliases.
3212efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org// cp is assumed to be a callee saved register.
32289e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org// Defined using #define instead of "static const Register&" because Clang
32389e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org// complains otherwise when a compilation unit that includes this header
32489e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org// doesn't use the variables.
32589e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org#define kRootRegister s6
32689e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org#define cp s7
32789e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org#define kLithiumScratchReg s3
32889e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org#define kLithiumScratchReg2 s4
32989e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org#define kLithiumScratchDouble f30
33089e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org#define kDoubleRegZero f28
33134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
3327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// FPU (coprocessor 1) control registers.
3337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// Currently only FCSR (#31) is implemented.
3347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgstruct FPUControlRegister {
3357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  bool is_valid() const { return code_ == kFCSRRegister; }
3367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  bool is(FPUControlRegister creg) const { return code_ == creg.code_; }
3377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  int code() const {
3387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    ASSERT(is_valid());
3397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    return code_;
3407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
3417516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  int bit() const {
3427516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    ASSERT(is_valid());
3437516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    return 1 << code_;
3447516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
3457516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void setcode(int f) {
3467516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    code_ = f;
3477516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    ASSERT(is_valid());
3487516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
3497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Unfortunately we can't make this private in a struct.
3507516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  int code_;
3515c838251403b0be9a882540f1922577abba4c872ager@chromium.org};
3525c838251403b0be9a882540f1922577abba4c872ager@chromium.org
35383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgconst FPUControlRegister no_fpucreg = { kInvalidFPUControlRegister };
3547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPUControlRegister FCSR = { kFCSRRegister };
3555c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3565c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3575c838251403b0be9a882540f1922577abba4c872ager@chromium.org// -----------------------------------------------------------------------------
3585c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Machine instruction Operands.
3595c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3605c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Class Operand represents a shifter operand in data processing instructions.
3615c838251403b0be9a882540f1922577abba4c872ager@chromium.orgclass Operand BASE_EMBEDDED {
3625c838251403b0be9a882540f1922577abba4c872ager@chromium.org public:
3635c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Immediate.
3645c838251403b0be9a882540f1922577abba4c872ager@chromium.org  INLINE(explicit Operand(int32_t immediate,
36559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org         RelocInfo::Mode rmode = RelocInfo::NONE32));
3665c838251403b0be9a882540f1922577abba4c872ager@chromium.org  INLINE(explicit Operand(const ExternalReference& f));
3675c838251403b0be9a882540f1922577abba4c872ager@chromium.org  INLINE(explicit Operand(const char* s));
3685c838251403b0be9a882540f1922577abba4c872ager@chromium.org  INLINE(explicit Operand(Object** opp));
3695c838251403b0be9a882540f1922577abba4c872ager@chromium.org  INLINE(explicit Operand(Context** cpp));
3705c838251403b0be9a882540f1922577abba4c872ager@chromium.org  explicit Operand(Handle<Object> handle);
3715c838251403b0be9a882540f1922577abba4c872ager@chromium.org  INLINE(explicit Operand(Smi* value));
3725c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3735c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Register.
3745c838251403b0be9a882540f1922577abba4c872ager@chromium.org  INLINE(explicit Operand(Register rm));
3755c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3765c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Return true if this is a register operand.
3775c838251403b0be9a882540f1922577abba4c872ager@chromium.org  INLINE(bool is_reg() const);
3785c838251403b0be9a882540f1922577abba4c872ager@chromium.org
379594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  inline int32_t immediate() const {
380594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    ASSERT(!is_reg());
381594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    return imm32_;
382594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  }
383594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org
3845c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Register rm() const { return rm_; }
3855c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3865c838251403b0be9a882540f1922577abba4c872ager@chromium.org private:
3875c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Register rm_;
38883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  int32_t imm32_;  // Valid if rm_ == no_reg.
3895c838251403b0be9a882540f1922577abba4c872ager@chromium.org  RelocInfo::Mode rmode_;
3905c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3915c838251403b0be9a882540f1922577abba4c872ager@chromium.org  friend class Assembler;
3925c838251403b0be9a882540f1922577abba4c872ager@chromium.org  friend class MacroAssembler;
3935c838251403b0be9a882540f1922577abba4c872ager@chromium.org};
3945c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3955c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3965c838251403b0be9a882540f1922577abba4c872ager@chromium.org// On MIPS we have only one adressing mode with base_reg + offset.
3975c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Class MemOperand represents a memory operand in load and store instructions.
3985c838251403b0be9a882540f1922577abba4c872ager@chromium.orgclass MemOperand : public Operand {
3995c838251403b0be9a882540f1922577abba4c872ager@chromium.org public:
400afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  // Immediate value attached to offset.
401afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  enum OffsetAddend {
402afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org    offset_minus_one = -1,
403afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org    offset_zero = 0
404afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  };
405afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org
4067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  explicit MemOperand(Register rn, int32_t offset = 0);
407afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  explicit MemOperand(Register rn, int32_t unit, int32_t multiplier,
408afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org                      OffsetAddend offset_addend = offset_zero);
40904921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org  int32_t offset() const { return offset_; }
4105c838251403b0be9a882540f1922577abba4c872ager@chromium.org
41134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  bool OffsetIsInt16Encodable() const {
41234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    return is_int16(offset_);
41334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  }
41434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
4155c838251403b0be9a882540f1922577abba4c872ager@chromium.org private:
4167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  int32_t offset_;
4175c838251403b0be9a882540f1922577abba4c872ager@chromium.org
4185c838251403b0be9a882540f1922577abba4c872ager@chromium.org  friend class Assembler;
4195c838251403b0be9a882540f1922577abba4c872ager@chromium.org};
4205c838251403b0be9a882540f1922577abba4c872ager@chromium.org
4215c838251403b0be9a882540f1922577abba4c872ager@chromium.org
4227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgclass Assembler : public AssemblerBase {
4235c838251403b0be9a882540f1922577abba4c872ager@chromium.org public:
4245c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Create an assembler. Instructions and relocation information are emitted
4255c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // into a buffer, with the instructions starting from the beginning and the
4265c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // relocation information starting from the end of the buffer. See CodeDesc
4275c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // for a detailed comment on the layout (globals.h).
4285c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //
4295c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // If the provided buffer is NULL, the assembler allocates and grows its own
4305c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // buffer, and buffer_size determines the initial buffer size. The buffer is
4315c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // owned by the assembler and deallocated upon destruction of the assembler.
4325c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //
4335c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // If the provided buffer is not NULL, the assembler uses the provided buffer
4345c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // for code generation and assumes its size to be buffer_size. If the buffer
4355c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // is too small, a fatal error occurs. No deallocation of the buffer is done
4365c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // upon destruction of the assembler.
43783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Assembler(Isolate* isolate, void* buffer, int buffer_size);
4388e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  virtual ~Assembler() { }
4395c838251403b0be9a882540f1922577abba4c872ager@chromium.org
4405c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // GetCode emits any pending (non-emitted) code and fills the descriptor
4415c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // desc. GetCode() is idempotent; it returns the same result if no other
4425c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Assembler functions are invoked in between GetCode() calls.
4435c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void GetCode(CodeDesc* desc);
4445c838251403b0be9a882540f1922577abba4c872ager@chromium.org
4455c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Label operations & relative jumps (PPUM Appendix D).
4465c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //
4475c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Takes a branch opcode (cc) and a label (L) and generates
4485c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // either a backward branch or a forward branch and links it
4495c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // to the label fixup chain. Usage:
4505c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //
4515c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Label L;    // unbound label
4525c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // j(cc, &L);  // forward branch to unbound label
4535c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // bind(&L);   // bind label to the current pc
4545c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // j(cc, &L);  // backward branch to bound label
4555c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // bind(&L);   // illegal: a label may be bound only once
4565c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //
4575c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Note: The same Label can be used for forward and backward branches
4585c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // but it may be bound only once.
45983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void bind(Label* L);  // Binds an unbound label L to current code position.
4603cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // Determines if Label is bound and near enough so that branch instruction
4613cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // can be used to reach it, instead of jump instruction.
4623cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  bool is_near(Label* L);
4635c838251403b0be9a882540f1922577abba4c872ager@chromium.org
46483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Returns the branch offset to the given label from the current code
46583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // position. Links the label to the current position if it is still unbound.
4665c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Manages the jump elimination optimization if the second parameter is true.
4675c838251403b0be9a882540f1922577abba4c872ager@chromium.org  int32_t branch_offset(Label* L, bool jump_elimination_allowed);
4685c838251403b0be9a882540f1922577abba4c872ager@chromium.org  int32_t shifted_branch_offset(Label* L, bool jump_elimination_allowed) {
4695c838251403b0be9a882540f1922577abba4c872ager@chromium.org    int32_t o = branch_offset(L, jump_elimination_allowed);
4705c838251403b0be9a882540f1922577abba4c872ager@chromium.org    ASSERT((o & 3) == 0);   // Assert the offset is aligned.
4715c838251403b0be9a882540f1922577abba4c872ager@chromium.org    return o >> 2;
4725c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
4733cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  uint32_t jump_address(Label* L);
4745c838251403b0be9a882540f1922577abba4c872ager@chromium.org
4755c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Puts a labels target address at the given position.
4765c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // The high 8 bits are set to zero.
4775c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void label_at_put(Label* L, int at_offset);
4785c838251403b0be9a882540f1922577abba4c872ager@chromium.org
4795c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Read/Modify the code target address in the branch/call instruction at pc.
4805c838251403b0be9a882540f1922577abba4c872ager@chromium.org  static Address target_address_at(Address pc);
4816a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org  static void set_target_address_at(Address pc,
4826a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                    Address target,
4836a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                    ICacheFlushMode icache_flush_mode =
4846a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                        FLUSH_ICACHE_IF_NEEDED);
48597b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  // On MIPS there is no Constant Pool so we skip that parameter.
48697b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  INLINE(static Address target_address_at(Address pc,
48797b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org                                          ConstantPoolArray* constant_pool)) {
48897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    return target_address_at(pc);
48997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  }
49097b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  INLINE(static void set_target_address_at(Address pc,
49197b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org                                           ConstantPoolArray* constant_pool,
4926a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                           Address target,
4936a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                           ICacheFlushMode icache_flush_mode =
4946a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                               FLUSH_ICACHE_IF_NEEDED)) {
4956a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org    set_target_address_at(pc, target, icache_flush_mode);
49697b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  }
49797b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  INLINE(static Address target_address_at(Address pc, Code* code)) {
49897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
49997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    return target_address_at(pc, constant_pool);
50097b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  }
50197b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  INLINE(static void set_target_address_at(Address pc,
50297b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org                                           Code* code,
5036a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                           Address target,
5046a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                           ICacheFlushMode icache_flush_mode =
5056a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                               FLUSH_ICACHE_IF_NEEDED)) {
50697b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
5076a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org    set_target_address_at(pc, constant_pool, target, icache_flush_mode);
50897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  }
5095c838251403b0be9a882540f1922577abba4c872ager@chromium.org
51089e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  // Return the code target address at a call site from the return address
51189e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  // of that call in the instruction stream.
51289e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  inline static Address target_address_from_return_address(Address pc);
51389e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org
51434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  static void JumpLabelToJumpRegister(Address pc);
51534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
51628faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org  static void QuietNaN(HeapObject* nan);
51728faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org
5185c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // This sets the branch destination (which gets loaded at the call address).
51988aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org  // This is for calls and branches within generated code.  The serializer
52088aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org  // has already deserialized the lui/ori instructions etc.
52188aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org  inline static void deserialization_set_special_target_at(
52297b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org      Address instruction_payload, Code* code, Address target) {
52388aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org    set_target_address_at(
52488aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org        instruction_payload - kInstructionsFor32BitConstant * kInstrSize,
52597b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org        code,
52688aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org        target);
5275c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
5285c838251403b0be9a882540f1922577abba4c872ager@chromium.org
5297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Size of an instruction.
5307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kInstrSize = sizeof(Instr);
5317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Difference between address of current opcode and target address offset.
5337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kBranchPCOffset = 4;
5347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Here we are patching the address in the LUI/ORI instruction pair.
5367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // These values are used in the serialization process and must be zero for
5377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // MIPS platform, as Code, Embedded Object or External-reference pointers
5387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // are split across two consecutive instructions and don't exist separately
5397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // in the code, so the serializer should not step forwards in memory after
5407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // a target is resolved and written.
54188aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org  static const int kSpecialTargetSize = 0;
5427516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5437516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Number of consecutive instructions used to store 32bit constant.
54434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // Before jump-optimizations, this constant was used in
54534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // RelocInfo::target_address_address() function to tell serializer address of
54634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // the instruction that follows LUI/ORI instruction pair. Now, with new jump
54734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // optimization, where jump-through-register instruction that usually
54834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // follows LUI/ORI pair is substituted with J/JAL, this constant equals
54934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // to 3 instructions (LUI+ORI+J/JAL/JR/JALR).
55034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  static const int kInstructionsFor32BitConstant = 3;
5515c838251403b0be9a882540f1922577abba4c872ager@chromium.org
5525c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Distance between the instruction referring to the address of the call
5535c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // target and the return address.
5545c838251403b0be9a882540f1922577abba4c872ager@chromium.org  static const int kCallTargetAddressOffset = 4 * kInstrSize;
5555c838251403b0be9a882540f1922577abba4c872ager@chromium.org
5565c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Distance between start of patched return sequence and the emitted address
5575c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // to jump to.
5587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kPatchReturnSequenceAddressOffset = 0;
5595c838251403b0be9a882540f1922577abba4c872ager@chromium.org
5602356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org  // Distance between start of patched debug break slot and the emitted address
5612356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org  // to jump to.
5627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kPatchDebugBreakSlotAddressOffset =  0 * kInstrSize;
5637516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Difference between address of current opcode and value read from pc
5657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // register.
5667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kPcLoadDelta = 4;
5677516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
56889e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  static const int kPatchDebugBreakSlotReturnOffset = 4 * kInstrSize;
56989e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org
5707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Number of instructions used for the JS return sequence. The constant is
5717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // used by the debugger to patch the JS return sequence.
5727516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kJSReturnSequenceInstructions = 7;
5737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kDebugBreakSlotInstructions = 4;
5747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kDebugBreakSlotLength =
5757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      kDebugBreakSlotInstructions * kInstrSize;
5767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5775c838251403b0be9a882540f1922577abba4c872ager@chromium.org
5785c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // ---------------------------------------------------------------------------
5795c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Code generation.
5805c838251403b0be9a882540f1922577abba4c872ager@chromium.org
5817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Insert the smallest number of nop instructions
5827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // possible to align the pc offset to a multiple
5837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // of m. m must be a power of 2 (>= 4).
5847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void Align(int m);
5857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Aligns code to something that's optimal for a jump target for the platform.
5867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void CodeTargetAlign();
5877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Different nop operations are used by the code generator to detect certain
5897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // states of the generated code.
5907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  enum NopMarkerTypes {
5917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    NON_MARKING_NOP = 0,
5927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    DEBUG_BREAK_NOP,
5937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    // IC markers.
5947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    PROPERTY_ACCESS_INLINED,
5957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    PROPERTY_ACCESS_INLINED_CONTEXT,
5967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
5977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    // Helper values.
5987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    LAST_CODE_MARKER,
599fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED,
600fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // Code aging
601ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    CODE_AGE_MARKER_NOP = 6,
602ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    CODE_AGE_SEQUENCE_NOP
6037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  };
6047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
60533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  // Type == 0 is the default non-marking nop. For mips this is a
60633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  // sll(zero_reg, zero_reg, 0). We use rt_reg == at for non-zero
60733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  // marking, to avoid conflict with ssnop and ehb instructions.
6087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void nop(unsigned int type = 0) {
6097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    ASSERT(type < 32);
61033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    Register nop_rt_reg = (type == 0) ? zero_reg : at;
61133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    sll(zero_reg, nop_rt_reg, type, true);
6127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
6135c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6145c838251403b0be9a882540f1922577abba4c872ager@chromium.org
61583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // --------Branch-and-jump-instructions----------
6165c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // We don't use likely variant of instructions.
6175c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void b(int16_t offset);
6185c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void b(Label* L) { b(branch_offset(L, false)>>2); }
6195c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bal(int16_t offset);
6205c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bal(Label* L) { bal(branch_offset(L, false)>>2); }
6215c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6225c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void beq(Register rs, Register rt, int16_t offset);
6235c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void beq(Register rs, Register rt, Label* L) {
6245c838251403b0be9a882540f1922577abba4c872ager@chromium.org    beq(rs, rt, branch_offset(L, false) >> 2);
6255c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
6265c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bgez(Register rs, int16_t offset);
6275c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bgezal(Register rs, int16_t offset);
6285c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bgtz(Register rs, int16_t offset);
6295c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void blez(Register rs, int16_t offset);
6305c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bltz(Register rs, int16_t offset);
6315c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bltzal(Register rs, int16_t offset);
6325c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bne(Register rs, Register rt, int16_t offset);
6335c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bne(Register rs, Register rt, Label* L) {
6345c838251403b0be9a882540f1922577abba4c872ager@chromium.org    bne(rs, rt, branch_offset(L, false)>>2);
6355c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
6365c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6375c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Never use the int16_t b(l)cond version with a branch offset
63883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // instead of using the Label* version.
6395c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6402efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // Jump targets must be in the current 256 MB-aligned region. i.e. 28 bits.
6415c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void j(int32_t target);
6425c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void jal(int32_t target);
6435c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void jalr(Register rs, Register rd = ra);
6445c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void jr(Register target);
64534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  void j_or_jr(int32_t target, Register rs);
64634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  void jal_or_jalr(int32_t target, Register rs);
6475c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6485c838251403b0be9a882540f1922577abba4c872ager@chromium.org
649e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  // -------Data-processing-instructions---------
6505c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6515c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Arithmetic.
6525c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void addu(Register rd, Register rs, Register rt);
6535c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void subu(Register rd, Register rs, Register rt);
6545c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void mult(Register rs, Register rt);
6555c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void multu(Register rs, Register rt);
6565c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void div(Register rs, Register rt);
6575c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void divu(Register rs, Register rt);
6585c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void mul(Register rd, Register rs, Register rt);
6595c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6605c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void addiu(Register rd, Register rs, int32_t j);
6615c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6625c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Logical.
6635c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void and_(Register rd, Register rs, Register rt);
6645c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void or_(Register rd, Register rs, Register rt);
6655c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void xor_(Register rd, Register rs, Register rt);
6665c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void nor(Register rd, Register rs, Register rt);
6675c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6685c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void andi(Register rd, Register rs, int32_t j);
6695c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void ori(Register rd, Register rs, int32_t j);
6705c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void xori(Register rd, Register rs, int32_t j);
6715c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void lui(Register rd, int32_t j);
6725c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6735c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Shifts.
6747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Please note: sll(zero_reg, zero_reg, x) instructions are reserved as nop
6757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // and may cause problems in normal code. coming_from_nop makes sure this
6767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // doesn't happen.
6777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void sll(Register rd, Register rt, uint16_t sa, bool coming_from_nop = false);
6785c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void sllv(Register rd, Register rt, Register rs);
6795c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void srl(Register rd, Register rt, uint16_t sa);
6805c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void srlv(Register rd, Register rt, Register rs);
6815c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void sra(Register rt, Register rd, uint16_t sa);
6825c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void srav(Register rt, Register rd, Register rs);
6837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void rotr(Register rd, Register rt, uint16_t sa);
6847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void rotrv(Register rd, Register rt, Register rs);
6855c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6865c838251403b0be9a882540f1922577abba4c872ager@chromium.org
687e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  // ------------Memory-instructions-------------
6885c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6895c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void lb(Register rd, const MemOperand& rs);
6905c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void lbu(Register rd, const MemOperand& rs);
6917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void lh(Register rd, const MemOperand& rs);
6927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void lhu(Register rd, const MemOperand& rs);
6935c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void lw(Register rd, const MemOperand& rs);
6947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void lwl(Register rd, const MemOperand& rs);
6957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void lwr(Register rd, const MemOperand& rs);
6965c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void sb(Register rd, const MemOperand& rs);
6977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void sh(Register rd, const MemOperand& rs);
6985c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void sw(Register rd, const MemOperand& rs);
6997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void swl(Register rd, const MemOperand& rs);
7007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void swr(Register rd, const MemOperand& rs);
7015c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7025c838251403b0be9a882540f1922577abba4c872ager@chromium.org
703e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  // ----------------Prefetch--------------------
704afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org
705afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  void pref(int32_t hint, const MemOperand& rs);
706afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org
707afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org
708e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  // -------------Misc-instructions--------------
7095c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7105c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Break / Trap instructions.
711c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org  void break_(uint32_t code, bool break_as_stop = false);
712c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org  void stop(const char* msg, uint32_t code = kMaxStopCode);
7135c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void tge(Register rs, Register rt, uint16_t code);
7145c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void tgeu(Register rs, Register rt, uint16_t code);
7155c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void tlt(Register rs, Register rt, uint16_t code);
7165c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void tltu(Register rs, Register rt, uint16_t code);
7175c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void teq(Register rs, Register rt, uint16_t code);
7185c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void tne(Register rs, Register rt, uint16_t code);
7195c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7205c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Move from HI/LO register.
7215c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void mfhi(Register rd);
7225c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void mflo(Register rd);
7235c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7245c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Set on less than.
7255c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void slt(Register rd, Register rs, Register rt);
7265c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void sltu(Register rd, Register rs, Register rt);
7275c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void slti(Register rd, Register rs, int32_t j);
7285c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void sltiu(Register rd, Register rs, int32_t j);
7295c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Conditional move.
7317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void movz(Register rd, Register rs, Register rt);
7327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void movn(Register rd, Register rs, Register rt);
7337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void movt(Register rd, Register rs, uint16_t cc = 0);
7347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void movf(Register rd, Register rs, uint16_t cc = 0);
7357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
7367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Bit twiddling.
7377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void clz(Register rd, Register rs);
7387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void ins_(Register rt, Register rs, uint16_t pos, uint16_t size);
7397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void ext_(Register rt, Register rs, uint16_t pos, uint16_t size);
7405c838251403b0be9a882540f1922577abba4c872ager@chromium.org
741e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  // --------Coprocessor-instructions----------------
7425c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7435c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Load, store, and move.
7445c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void lwc1(FPURegister fd, const MemOperand& src);
7455c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void ldc1(FPURegister fd, const MemOperand& src);
7465c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7475c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void swc1(FPURegister fs, const MemOperand& dst);
7485c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void sdc1(FPURegister fs, const MemOperand& dst);
7495c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7507516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void mtc1(Register rt, FPURegister fs);
7517516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void mfc1(Register rt, FPURegister fs);
7527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
7537516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void ctc1(Register rt, FPUControlRegister fs);
7547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void cfc1(Register rt, FPUControlRegister fs);
7557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
7567516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Arithmetic.
7577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void add_d(FPURegister fd, FPURegister fs, FPURegister ft);
7587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void sub_d(FPURegister fd, FPURegister fs, FPURegister ft);
7597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void mul_d(FPURegister fd, FPURegister fs, FPURegister ft);
76059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  void madd_d(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft);
7617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void div_d(FPURegister fd, FPURegister fs, FPURegister ft);
7627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void abs_d(FPURegister fd, FPURegister fs);
7637516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void mov_d(FPURegister fd, FPURegister fs);
7647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void neg_d(FPURegister fd, FPURegister fs);
7657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void sqrt_d(FPURegister fd, FPURegister fs);
7665c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7675c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Conversion.
7685c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void cvt_w_s(FPURegister fd, FPURegister fs);
7695c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void cvt_w_d(FPURegister fd, FPURegister fs);
7707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void trunc_w_s(FPURegister fd, FPURegister fs);
7717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void trunc_w_d(FPURegister fd, FPURegister fs);
7727516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void round_w_s(FPURegister fd, FPURegister fs);
7737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void round_w_d(FPURegister fd, FPURegister fs);
7747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void floor_w_s(FPURegister fd, FPURegister fs);
7757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void floor_w_d(FPURegister fd, FPURegister fs);
7767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void ceil_w_s(FPURegister fd, FPURegister fs);
7777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void ceil_w_d(FPURegister fd, FPURegister fs);
7785c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7795c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void cvt_l_s(FPURegister fd, FPURegister fs);
7805c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void cvt_l_d(FPURegister fd, FPURegister fs);
7817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void trunc_l_s(FPURegister fd, FPURegister fs);
7827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void trunc_l_d(FPURegister fd, FPURegister fs);
7837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void round_l_s(FPURegister fd, FPURegister fs);
7847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void round_l_d(FPURegister fd, FPURegister fs);
7857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void floor_l_s(FPURegister fd, FPURegister fs);
7867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void floor_l_d(FPURegister fd, FPURegister fs);
7877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void ceil_l_s(FPURegister fd, FPURegister fs);
7887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void ceil_l_d(FPURegister fd, FPURegister fs);
7895c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7905c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void cvt_s_w(FPURegister fd, FPURegister fs);
7915c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void cvt_s_l(FPURegister fd, FPURegister fs);
7925c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void cvt_s_d(FPURegister fd, FPURegister fs);
7935c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7945c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void cvt_d_w(FPURegister fd, FPURegister fs);
7955c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void cvt_d_l(FPURegister fd, FPURegister fs);
7965c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void cvt_d_s(FPURegister fd, FPURegister fs);
7975c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7985c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Conditions and branches.
7995c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void c(FPUCondition cond, SecondaryField fmt,
8005c838251403b0be9a882540f1922577abba4c872ager@chromium.org         FPURegister ft, FPURegister fs, uint16_t cc = 0);
8015c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8025c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bc1f(int16_t offset, uint16_t cc = 0);
8035c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bc1f(Label* L, uint16_t cc = 0) { bc1f(branch_offset(L, false)>>2, cc); }
8045c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bc1t(int16_t offset, uint16_t cc = 0);
8055c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bc1t(Label* L, uint16_t cc = 0) { bc1t(branch_offset(L, false)>>2, cc); }
8067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void fcmp(FPURegister src1, const double src2, FPUCondition cond);
8075c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8085c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Check the code size generated from label to here.
8096db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  int SizeOfCodeGeneratedSince(Label* label) {
8106db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    return pc_offset() - label->pos();
8116db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  }
8126db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
8136db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // Check the number of instructions generated from label to here.
8146db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  int InstructionsGeneratedSince(Label* label) {
8156db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    return SizeOfCodeGeneratedSince(label) / kInstrSize;
8165c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
8175c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Class for scoping postponing the trampoline pool generation.
8197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  class BlockTrampolinePoolScope {
8207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org   public:
8217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) {
8227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      assem_->StartBlockTrampolinePool();
8237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    }
8247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    ~BlockTrampolinePoolScope() {
8257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      assem_->EndBlockTrampolinePool();
8267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    }
8277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org   private:
8297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    Assembler* assem_;
8307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope);
8327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  };
8337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8343cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // Class for postponing the assembly buffer growth. Typically used for
8353cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // sequences of instructions that must be emitted as a unit, before
8363cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // buffer growth (and relocation) can occur.
8373cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // This blocking scope is not nestable.
8383cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  class BlockGrowBufferScope {
8393cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org   public:
8403cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    explicit BlockGrowBufferScope(Assembler* assem) : assem_(assem) {
8413cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      assem_->StartBlockGrowBuffer();
8423cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    }
8433cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    ~BlockGrowBufferScope() {
8443cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      assem_->EndBlockGrowBuffer();
8453cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    }
8463cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
8473c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org   private:
8483c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    Assembler* assem_;
8493cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
8503c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    DISALLOW_IMPLICIT_CONSTRUCTORS(BlockGrowBufferScope);
8513cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  };
8523cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
8535c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Debugging.
8545c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8555c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Mark address of the ExitJSFrame code.
8565c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void RecordJSReturn();
8575c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Mark address of a debug break slot.
8597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void RecordDebugBreakSlot();
8607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
86183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Record the AST id of the CallIC being compiled, so that it can be placed
86283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // in the relocation information.
863471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org  void SetRecordedAstId(TypeFeedbackId ast_id) {
864471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org    ASSERT(recorded_ast_id_.IsNone());
865717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org    recorded_ast_id_ = ast_id;
866717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org  }
867717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org
868471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org  TypeFeedbackId RecordedAstId() {
869471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org    ASSERT(!recorded_ast_id_.IsNone());
870717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org    return recorded_ast_id_;
871717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org  }
872717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org
873471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org  void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
87483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
8755c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Record a comment relocation entry that can be used by a disassembler.
8767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Use --code-comments to enable.
8775c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void RecordComment(const char* msg);
8785c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8793cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  static int RelocateInternalReference(byte* pc, intptr_t pc_delta);
8803cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
8817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Writes a single byte or word of data in the code stream.  Used for
8827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // inline tables, e.g., jump-tables.
8837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void db(uint8_t data);
8847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void dd(uint32_t data);
8855c838251403b0be9a882540f1922577abba4c872ager@chromium.org
886057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  // Emits the address of the code stub's first instruction.
887057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  void emit_code_stub_address(Code* stub);
888057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org
8897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  PositionsRecorder* positions_recorder() { return &positions_recorder_; }
8907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Postpone the generation of the trampoline pool for the specified number of
8927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // instructions.
8937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void BlockTrampolinePoolFor(int instructions);
8947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8955c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Check if there is less than kGap bytes available in the buffer.
8965c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // If this is the case, we need to grow the buffer before emitting
8975c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // an instruction or relocation information.
8985c838251403b0be9a882540f1922577abba4c872ager@chromium.org  inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; }
8995c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9005c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Get the number of bytes available in the buffer.
9015c838251403b0be9a882540f1922577abba4c872ager@chromium.org  inline int available_space() const { return reloc_info_writer.pos() - pc_; }
9025c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9035c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Read/patch instructions.
9045c838251403b0be9a882540f1922577abba4c872ager@chromium.org  static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
9057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static void instr_at_put(byte* pc, Instr instr) {
9065c838251403b0be9a882540f1922577abba4c872ager@chromium.org    *reinterpret_cast<Instr*>(pc) = instr;
9075c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
9085c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
9095c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void instr_at_put(int pos, Instr instr) {
9105c838251403b0be9a882540f1922577abba4c872ager@chromium.org    *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
9115c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
9125c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9135c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Check if an instruction is a branch of some kind.
9147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsBranch(Instr instr);
91583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static bool IsBeq(Instr instr);
91683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static bool IsBne(Instr instr);
9177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9183cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  static bool IsJump(Instr instr);
9193cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  static bool IsJ(Instr instr);
9203cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  static bool IsLui(Instr instr);
9213cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  static bool IsOri(Instr instr);
9223cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
92334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  static bool IsJal(Instr instr);
92434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  static bool IsJr(Instr instr);
92534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  static bool IsJalr(Instr instr);
92634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
9277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsNop(Instr instr, unsigned int type);
9287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsPop(Instr instr);
9297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsPush(Instr instr);
9307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsLwRegFpOffset(Instr instr);
9317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsSwRegFpOffset(Instr instr);
9327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsLwRegFpNegOffset(Instr instr);
9337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsSwRegFpNegOffset(Instr instr);
9347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
93583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static Register GetRtReg(Instr instr);
93683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static Register GetRsReg(Instr instr);
93783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static Register GetRdReg(Instr instr);
93883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
93983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetRt(Instr instr);
94083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetRtField(Instr instr);
94183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetRs(Instr instr);
94283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetRsField(Instr instr);
94383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetRd(Instr instr);
94483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetRdField(Instr instr);
94583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetSa(Instr instr);
94683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetSaField(Instr instr);
94783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetOpcodeField(Instr instr);
9483cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  static uint32_t GetFunction(Instr instr);
9493cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  static uint32_t GetFunctionField(Instr instr);
95083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetImmediate16(Instr instr);
95183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetLabelConst(Instr instr);
9527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9537516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static int32_t GetBranchOffset(Instr instr);
9547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsLw(Instr instr);
9557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static int16_t GetLwOffset(Instr instr);
9567516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static Instr SetLwOffset(Instr instr, int16_t offset);
9577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsSw(Instr instr);
9597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static Instr SetSwOffset(Instr instr, int16_t offset);
9607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsAddImmediate(Instr instr);
9617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static Instr SetAddImmediateOffset(Instr instr, int16_t offset);
9627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
96383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static bool IsAndImmediate(Instr instr);
9647bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org  static bool IsEmittedConstant(Instr instr);
96583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
9663cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  void CheckTrampolinePool();
9677516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
96869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  // Allocate a constant pool of the correct size for the generated code.
9699fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org  Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate);
97069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org
97169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  // Generate the constant pool for the generated code.
97269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  void PopulateConstantPool(ConstantPoolArray* constant_pool);
97369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org
9747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org protected:
97583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Relocation for a type-recording IC has the AST id added to it.  This
97683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // member variable is a way to pass the information from the call site to
97783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // the relocation info.
978471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org  TypeFeedbackId recorded_ast_id_;
97983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
9807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  int32_t buffer_space() const { return reloc_info_writer.pos() - pc_; }
9815c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9825c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Decode branch instruction at pos and return branch target pos.
9835c838251403b0be9a882540f1922577abba4c872ager@chromium.org  int target_at(int32_t pos);
9845c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9855c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Patch branch instruction at pos to branch to given branch target pos.
9865c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void target_at_put(int32_t pos, int32_t target_pos);
9875c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9885c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Say if we need to relocate with this mode.
9897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  bool MustUseReg(RelocInfo::Mode rmode);
9905c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9915c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Record reloc info for current pc_.
9925c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
9935c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Block the emission of the trampoline pool before pc_offset.
9957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void BlockTrampolinePoolBefore(int pc_offset) {
9967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    if (no_trampoline_pool_before_ < pc_offset)
9977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      no_trampoline_pool_before_ = pc_offset;
9987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
9997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void StartBlockTrampolinePool() {
10017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    trampoline_pool_blocked_nesting_++;
10027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
10033cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
10047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void EndBlockTrampolinePool() {
10057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    trampoline_pool_blocked_nesting_--;
10067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
10077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  bool is_trampoline_pool_blocked() const {
10097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    return trampoline_pool_blocked_nesting_ > 0;
10107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
10117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
101283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  bool has_exception() const {
101383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    return internal_trampoline_exception_;
101483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
101583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
101634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi);
101734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
10183cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  bool is_trampoline_emitted() const {
10193cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    return trampoline_emitted_;
10203cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  }
10213cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
10223cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // Temporarily block automatic assembly buffer growth.
10233cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  void StartBlockGrowBuffer() {
10243cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    ASSERT(!block_buffer_growth_);
10253cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    block_buffer_growth_ = true;
10263cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  }
10273cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
10283cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  void EndBlockGrowBuffer() {
10293cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    ASSERT(block_buffer_growth_);
10303cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    block_buffer_growth_ = false;
10313cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  }
10323cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
10333cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  bool is_buffer_growth_blocked() const {
10343cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    return block_buffer_growth_;
10353cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  }
10363cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
10375c838251403b0be9a882540f1922577abba4c872ager@chromium.org private:
10385c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Buffer size and constant pool distance are checked together at regular
10395c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // intervals of kBufferCheckInterval emitted bytes.
10405c838251403b0be9a882540f1922577abba4c872ager@chromium.org  static const int kBufferCheckInterval = 1*KB/2;
10415c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10425c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Code generation.
10435c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // The relocation writer's position is at least kGap bytes below the end of
10445c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // the generated instructions. This is so that multi-instruction sequences do
10455c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // not have to check for overflow. The same is true for writes of large
10465c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // relocation info entries.
10475c838251403b0be9a882540f1922577abba4c872ager@chromium.org  static const int kGap = 32;
10485c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10507516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Repeated checking whether the trampoline pool should be emitted is rather
10517516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // expensive. By default we only check again once a number of instructions
10527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // has been generated.
10537516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kCheckConstIntervalInst = 32;
10547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize;
10557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10567516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  int next_buffer_check_;  // pc offset of next buffer check.
10577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Emission of the trampoline pool may be blocked in some code sequences.
10597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  int trampoline_pool_blocked_nesting_;  // Block emission if this is not zero.
10607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  int no_trampoline_pool_before_;  // Block emission before this pc offset.
10617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Keep track of the last emitted pool to guarantee a maximal distance.
10637516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  int last_trampoline_pool_end_;  // pc offset of the end of the last pool.
10647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10653cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // Automatic growth of the assembly buffer may be blocked for some sequences.
10663cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  bool block_buffer_growth_;  // Block growth when true.
10673cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
10685c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Relocation information generation.
10695c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Each relocation is encoded as a variable size value.
10705c838251403b0be9a882540f1922577abba4c872ager@chromium.org  static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
10715c838251403b0be9a882540f1922577abba4c872ager@chromium.org  RelocInfoWriter reloc_info_writer;
10725c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10735c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // The bound position, before this we cannot do instruction elimination.
10745c838251403b0be9a882540f1922577abba4c872ager@chromium.org  int last_bound_pos_;
10755c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10765c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Code emission.
10775c838251403b0be9a882540f1922577abba4c872ager@chromium.org  inline void CheckBuffer();
10785c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void GrowBuffer();
10795c838251403b0be9a882540f1922577abba4c872ager@chromium.org  inline void emit(Instr x);
10807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  inline void CheckTrampolinePoolQuick();
10815c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10825c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Instruction generation.
10835c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // We have 3 different kind of encoding layout on MIPS.
10845c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // However due to many different types of objects encoded in the same fields
10855c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // we have quite a few aliases for each mode.
10865c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Using the same structure to refer to Register and FPURegister would spare a
10875c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // few aliases, but mixing both does not look clean to me.
10885c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Anyway we could surely implement this differently.
10895c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10905c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void GenInstrRegister(Opcode opcode,
10915c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        Register rs,
10925c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        Register rt,
10935c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        Register rd,
10945c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        uint16_t sa = 0,
10955c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        SecondaryField func = NULLSF);
10965c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10975c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void GenInstrRegister(Opcode opcode,
10987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                        Register rs,
10997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                        Register rt,
11007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                        uint16_t msb,
11017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                        uint16_t lsb,
11027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                        SecondaryField func);
11037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
11047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void GenInstrRegister(Opcode opcode,
11055c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        SecondaryField fmt,
11065c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        FPURegister ft,
11075c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        FPURegister fs,
11085c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        FPURegister fd,
11095c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        SecondaryField func = NULLSF);
11105c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11115c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void GenInstrRegister(Opcode opcode,
111259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                        FPURegister fr,
111359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                        FPURegister ft,
111459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                        FPURegister fs,
111559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                        FPURegister fd,
111659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                        SecondaryField func = NULLSF);
111759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
111859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  void GenInstrRegister(Opcode opcode,
11195c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        SecondaryField fmt,
11205c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        Register rt,
11215c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        FPURegister fs,
11225c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        FPURegister fd,
11235c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        SecondaryField func = NULLSF);
11245c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void GenInstrRegister(Opcode opcode,
11267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                        SecondaryField fmt,
11277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                        Register rt,
11287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                        FPUControlRegister fs,
11297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                        SecondaryField func = NULLSF);
11307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
11315c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11325c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void GenInstrImmediate(Opcode opcode,
11335c838251403b0be9a882540f1922577abba4c872ager@chromium.org                         Register rs,
11345c838251403b0be9a882540f1922577abba4c872ager@chromium.org                         Register rt,
11355c838251403b0be9a882540f1922577abba4c872ager@chromium.org                         int32_t  j);
11365c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void GenInstrImmediate(Opcode opcode,
11375c838251403b0be9a882540f1922577abba4c872ager@chromium.org                         Register rs,
11385c838251403b0be9a882540f1922577abba4c872ager@chromium.org                         SecondaryField SF,
11395c838251403b0be9a882540f1922577abba4c872ager@chromium.org                         int32_t  j);
11405c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void GenInstrImmediate(Opcode opcode,
11415c838251403b0be9a882540f1922577abba4c872ager@chromium.org                         Register r1,
11425c838251403b0be9a882540f1922577abba4c872ager@chromium.org                         FPURegister r2,
11435c838251403b0be9a882540f1922577abba4c872ager@chromium.org                         int32_t  j);
11445c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11455c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11465c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void GenInstrJump(Opcode opcode,
11475c838251403b0be9a882540f1922577abba4c872ager@chromium.org                     uint32_t address);
11485c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Helpers.
11507516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void LoadRegPlusOffsetToAt(const MemOperand& src);
11515c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11525c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Labels.
11535c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void print(Label* L);
11545c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bind_to(Label* L, int pos);
11555c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void next(Label* L);
11565c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // One trampoline consists of:
11587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // - space for trampoline slots,
11597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // - space for labels.
11607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  //
11617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Space for trampoline slots is equal to slot_count * 2 * kInstrSize.
11627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Space for trampoline slots preceeds space for labels. Each label is of one
11637516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // instruction size, so total amount for labels is equal to
11647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // label_count *  kInstrSize.
11657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  class Trampoline {
11667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org   public:
11673cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    Trampoline() {
11683cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      start_ = 0;
11693cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      next_slot_ = 0;
11703cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      free_slot_count_ = 0;
11713cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      end_ = 0;
11723cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    }
11733cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    Trampoline(int start, int slot_count) {
11747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      start_ = start;
11757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      next_slot_ = start;
11767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      free_slot_count_ = slot_count;
11773cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      end_ = start + slot_count * kTrampolineSlotsSize;
11787516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    }
11797516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    int start() {
11807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      return start_;
11817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    }
11827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    int end() {
11837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      return end_;
11847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    }
11857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    int take_slot() {
118683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      int trampoline_slot = kInvalidSlotPos;
118783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      if (free_slot_count_ <= 0) {
118883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        // We have run out of space on trampolines.
118983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        // Make sure we fail in debug mode, so we become aware of each case
119083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        // when this happens.
119183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        ASSERT(0);
119283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        // Internal exception will be caught.
119383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      } else {
119483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        trampoline_slot = next_slot_;
119583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        free_slot_count_--;
11963cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org        next_slot_ += kTrampolineSlotsSize;
119783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      }
11987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      return trampoline_slot;
11997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    }
120083e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org
12017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org   private:
12027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    int start_;
12037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    int end_;
12047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    int next_slot_;
12057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    int free_slot_count_;
12067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  };
12077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12083cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  int32_t get_trampoline_entry(int32_t pos);
12093cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  int unbound_labels_count_;
12103cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // If trampoline is emitted, generated code is becoming large. As this is
12113cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // already a slow case which can possibly break our code generation for the
12123cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // extreme case, we use this information to trigger different mode of
12133cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // branch instruction generation, where we use jump instructions rather
12143cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // than regular branch instructions.
12153cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  bool trampoline_emitted_;
12163cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  static const int kTrampolineSlotsSize = 4 * kInstrSize;
12177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kMaxBranchOffset = (1 << (18 - 1)) - 1;
121883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static const int kInvalidSlotPos = -1;
12197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12203cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  Trampoline trampoline_;
122183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  bool internal_trampoline_exception_;
12227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12235c838251403b0be9a882540f1922577abba4c872ager@chromium.org  friend class RegExpMacroAssemblerMIPS;
12245c838251403b0be9a882540f1922577abba4c872ager@chromium.org  friend class RelocInfo;
12257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  friend class CodePatcher;
12267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  friend class BlockTrampolinePoolScope;
12277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  PositionsRecorder positions_recorder_;
12297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  friend class PositionsRecorder;
12307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  friend class EnsureSpace;
12317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org};
12327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgclass EnsureSpace BASE_EMBEDDED {
12357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org public:
12367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  explicit EnsureSpace(Assembler* assembler) {
12377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    assembler->CheckBuffer();
12387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
12395c838251403b0be9a882540f1922577abba4c872ager@chromium.org};
12405c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12415c838251403b0be9a882540f1922577abba4c872ager@chromium.org} }  // namespace v8::internal
12425c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12435c838251403b0be9a882540f1922577abba4c872ager@chromium.org#endif  // V8_ARM_ASSEMBLER_MIPS_H_
1244