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>
405c838251403b0be9a882540f1922577abba4c872ager@chromium.org#include "assembler.h"
415c838251403b0be9a882540f1922577abba4c872ager@chromium.org#include "constants-mips.h"
425c838251403b0be9a882540f1922577abba4c872ager@chromium.org#include "serialize.h"
435c838251403b0be9a882540f1922577abba4c872ager@chromium.org
445c838251403b0be9a882540f1922577abba4c872ager@chromium.orgnamespace v8 {
455c838251403b0be9a882540f1922577abba4c872ager@chromium.orgnamespace internal {
465c838251403b0be9a882540f1922577abba4c872ager@chromium.org
475c838251403b0be9a882540f1922577abba4c872ager@chromium.org// CPU Registers.
485c838251403b0be9a882540f1922577abba4c872ager@chromium.org//
495c838251403b0be9a882540f1922577abba4c872ager@chromium.org// 1) We would prefer to use an enum, but enum values are assignment-
505c838251403b0be9a882540f1922577abba4c872ager@chromium.org// compatible with int, which has caused code-generation bugs.
515c838251403b0be9a882540f1922577abba4c872ager@chromium.org//
525c838251403b0be9a882540f1922577abba4c872ager@chromium.org// 2) We would prefer to use a class instead of a struct but we don't like
535c838251403b0be9a882540f1922577abba4c872ager@chromium.org// the register initialization to depend on the particular initialization
545c838251403b0be9a882540f1922577abba4c872ager@chromium.org// order (which appears to be different on OS X, Linux, and Windows for the
555c838251403b0be9a882540f1922577abba4c872ager@chromium.org// installed versions of C++ we tried). Using a struct permits C-style
565c838251403b0be9a882540f1922577abba4c872ager@chromium.org// "initialization". Also, the Register objects cannot be const as this
575c838251403b0be9a882540f1922577abba4c872ager@chromium.org// forces initialization stubs in MSVC, making us dependent on initialization
585c838251403b0be9a882540f1922577abba4c872ager@chromium.org// order.
595c838251403b0be9a882540f1922577abba4c872ager@chromium.org//
605c838251403b0be9a882540f1922577abba4c872ager@chromium.org// 3) By not using an enum, we are possibly preventing the compiler from
615c838251403b0be9a882540f1922577abba4c872ager@chromium.org// doing certain constant folds, which may significantly reduce the
625c838251403b0be9a882540f1922577abba4c872ager@chromium.org// code generated for some assembly instructions (because they boil down
635c838251403b0be9a882540f1922577abba4c872ager@chromium.org// to a few constants). If this is a problem, we could change the code
645c838251403b0be9a882540f1922577abba4c872ager@chromium.org// such that we use an enum in optimized mode, and the struct in debug
655c838251403b0be9a882540f1922577abba4c872ager@chromium.org// mode. This way we get the compile-time error checking in debug mode
665c838251403b0be9a882540f1922577abba4c872ager@chromium.org// and best performance in optimized code.
675c838251403b0be9a882540f1922577abba4c872ager@chromium.org
685c838251403b0be9a882540f1922577abba4c872ager@chromium.org
695c838251403b0be9a882540f1922577abba4c872ager@chromium.org// -----------------------------------------------------------------------------
7083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org// Implementation of Register and FPURegister.
715c838251403b0be9a882540f1922577abba4c872ager@chromium.org
725c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Core register.
735c838251403b0be9a882540f1922577abba4c872ager@chromium.orgstruct Register {
747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kNumRegisters = v8::internal::kNumRegisters;
7559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  static const int kMaxNumAllocatableRegisters = 14;  // v0 through t7.
7683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static const int kSizeInBytes = 4;
7759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
7859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  inline static int NumAllocatableRegisters();
797516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static int ToAllocationIndex(Register reg) {
817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    return reg.code() - 2;  // zero_reg and 'at' are skipped.
827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static Register FromAllocationIndex(int index) {
8559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    return from_code(index + 2);  // zero_reg and 'at' are skipped.
877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const char* AllocationIndexToString(int index) {
9059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    const char* const names[] = {
927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "v0",
937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "v1",
947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "a0",
957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "a1",
967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "a2",
977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "a3",
987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "t0",
997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "t1",
1007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "t2",
1017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "t3",
1027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "t4",
1037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "t5",
1047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "t6",
1057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      "t7",
1067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    };
1077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    return names[index];
1087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
1097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static Register from_code(int code) {
1117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    Register r = { code };
1127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    return r;
1137516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
1147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1154a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
1164a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  bool is(Register reg) const { return code_ == reg.code_; }
1174a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  int code() const {
1185c838251403b0be9a882540f1922577abba4c872ager@chromium.org    ASSERT(is_valid());
1195c838251403b0be9a882540f1922577abba4c872ager@chromium.org    return code_;
1205c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
1214a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  int bit() const {
1225c838251403b0be9a882540f1922577abba4c872ager@chromium.org    ASSERT(is_valid());
1235c838251403b0be9a882540f1922577abba4c872ager@chromium.org    return 1 << code_;
1245c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
1255c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1265c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Unfortunately we can't make this private in a struct.
1275c838251403b0be9a882540f1922577abba4c872ager@chromium.org  int code_;
1285c838251403b0be9a882540f1922577abba4c872ager@chromium.org};
1295c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1307d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org#define REGISTER(N, C) \
1317d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  const int kRegister_ ## N ## _Code = C; \
1327d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  const Register N = { C }
1337d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org
1347d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(no_reg, -1);
1357d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// Always zero.
1367d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(zero_reg, 0);
1377d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// at: Reserved for synthetic instructions.
1387d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(at, 1);
1397d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// v0, v1: Used when returning multiple values from subroutines.
1407d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(v0, 2);
1417d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(v1, 3);
1427d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// a0 - a4: Used to pass non-FP parameters.
1437d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(a0, 4);
1447d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(a1, 5);
1457d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(a2, 6);
1467d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(a3, 7);
1477d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// t0 - t9: Can be used without reservation, act as temporary registers and are
1487d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// allowed to be destroyed by subroutines.
1497d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t0, 8);
1507d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t1, 9);
1517d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t2, 10);
1527d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t3, 11);
1537d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t4, 12);
1547d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t5, 13);
1557d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t6, 14);
1567d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t7, 15);
1577d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// s0 - s7: Subroutine register variables. Subroutines that write to these
1587d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// registers must restore their values before exiting so that the caller can
1597d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// expect the values to be preserved.
1607d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s0, 16);
1617d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s1, 17);
1627d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s2, 18);
1637d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s3, 19);
1647d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s4, 20);
1657d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s5, 21);
1667d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s6, 22);
1677d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(s7, 23);
1687d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t8, 24);
1697d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(t9, 25);
1707d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// k0, k1: Reserved for system calls and interrupt handlers.
1717d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(k0, 26);
1727d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(k1, 27);
1737d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// gp: Reserved.
1747d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(gp, 28);
1757d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// sp: Stack pointer.
1767d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(sp, 29);
1777d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// fp: Frame pointer.
1787d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(fp, 30);
1797d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org// ra: Return address pointer.
1807d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgREGISTER(ra, 31);
1817d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org
1827d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org#undef REGISTER
1837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1845c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1855c838251403b0be9a882540f1922577abba4c872ager@chromium.orgint ToNumber(Register reg);
1865c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1875c838251403b0be9a882540f1922577abba4c872ager@chromium.orgRegister ToRegister(int num);
1885c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1895c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Coprocessor register.
1905c838251403b0be9a882540f1922577abba4c872ager@chromium.orgstruct FPURegister {
1917c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org  static const int kMaxNumRegisters = v8::internal::kNumFPURegisters;
19234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
19334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // TODO(plind): Warning, inconsistent numbering here. kNumFPURegisters refers
19434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to
19534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // number of Double regs (64-bit regs, or FPU-reg-pairs).
19634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
19734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // A few double registers are reserved: one as a scratch register and one to
19834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // hold 0.0.
19934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  //  f28: 0.0
20034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  //  f30: scratch register.
20134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  static const int kNumReservedRegisters = 2;
2027c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org  static const int kMaxNumAllocatableRegisters = kMaxNumRegisters / 2 -
20334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      kNumReservedRegisters;
20434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
20559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  inline static int NumRegisters();
20659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  inline static int NumAllocatableRegisters();
2072efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  inline static int ToAllocationIndex(FPURegister reg);
20859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  static const char* AllocationIndexToString(int index);
2097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static FPURegister FromAllocationIndex(int index) {
21159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
21234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    return from_code(index * 2);
2137516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
2147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static FPURegister from_code(int code) {
2167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    FPURegister r = { code };
2177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    return r;
2187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
2197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2207c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org  bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters ; }
2214a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  bool is(FPURegister creg) const { return code_ == creg.code_; }
22234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  FPURegister low() const {
22334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    // Find low reg of a Double-reg pair, which is the reg itself.
22434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    ASSERT(code_ % 2 == 0);  // Specified Double reg must be even.
22534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    FPURegister reg;
22634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    reg.code_ = code_;
22734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    ASSERT(reg.is_valid());
22834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    return reg;
22934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  }
23034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  FPURegister high() const {
23134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    // Find high reg of a Doubel-reg pair, which is reg + 1.
23234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    ASSERT(code_ % 2 == 0);  // Specified Double reg must be even.
23334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    FPURegister reg;
23434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    reg.code_ = code_ + 1;
23534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    ASSERT(reg.is_valid());
23634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    return reg;
23734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  }
23834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
2394a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  int code() const {
2405c838251403b0be9a882540f1922577abba4c872ager@chromium.org    ASSERT(is_valid());
2415c838251403b0be9a882540f1922577abba4c872ager@chromium.org    return code_;
2425c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
2434a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  int bit() const {
2445c838251403b0be9a882540f1922577abba4c872ager@chromium.org    ASSERT(is_valid());
2455c838251403b0be9a882540f1922577abba4c872ager@chromium.org    return 1 << code_;
2465c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
2477516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void setcode(int f) {
2487516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    code_ = f;
2497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    ASSERT(is_valid());
2507516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
2515c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Unfortunately we can't make this private in a struct.
2525c838251403b0be9a882540f1922577abba4c872ager@chromium.org  int code_;
2535c838251403b0be9a882540f1922577abba4c872ager@chromium.org};
2545c838251403b0be9a882540f1922577abba4c872ager@chromium.org
25534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// V8 now supports the O32 ABI, and the FPU Registers are organized as 32
25634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// 32-bit registers, f0 through f31. When used as 'double' they are used
25734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// in pairs, starting with the even numbered register. So a double operation
25834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// on f0 really uses f0 and f1.
25934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// (Modern mips hardware also supports 32 64-bit registers, via setting
26034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// (priviledged) Status Register FR bit to 1. This is used by the N32 ABI,
26134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// but it is not in common use. Someday we will want to support this in v8.)
26234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
26334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org// For O32 ABI, Floats and Doubles refer to same set of 32 32-bit registers.
2647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgtypedef FPURegister DoubleRegister;
26534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.orgtypedef FPURegister FloatRegister;
2667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
26734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.orgconst FPURegister no_freg = { -1 };
2687516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2697516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f0 = { 0 };  // Return value in hard float mode.
2707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f1 = { 1 };
2717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f2 = { 2 };
2727516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f3 = { 3 };
2737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f4 = { 4 };
2747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f5 = { 5 };
2757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f6 = { 6 };
2767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f7 = { 7 };
2777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f8 = { 8 };
2787516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f9 = { 9 };
2797516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f10 = { 10 };
2807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f11 = { 11 };
2817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f12 = { 12 };  // Arg 0 in hard float mode.
2827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f13 = { 13 };
2837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f14 = { 14 };  // Arg 1 in hard float mode.
2847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f15 = { 15 };
2857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f16 = { 16 };
2867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f17 = { 17 };
2877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f18 = { 18 };
2887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f19 = { 19 };
2897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f20 = { 20 };
2907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f21 = { 21 };
2917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f22 = { 22 };
2927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f23 = { 23 };
2937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f24 = { 24 };
2947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f25 = { 25 };
2957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f26 = { 26 };
2967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f27 = { 27 };
2977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f28 = { 28 };
2987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f29 = { 29 };
2997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f30 = { 30 };
3007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPURegister f31 = { 31 };
3017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
3022efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org// Register aliases.
3032efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org// cp is assumed to be a callee saved register.
30489e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org// Defined using #define instead of "static const Register&" because Clang
30589e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org// complains otherwise when a compilation unit that includes this header
30689e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org// doesn't use the variables.
30789e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org#define kRootRegister s6
30889e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org#define cp s7
30989e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org#define kLithiumScratchReg s3
31089e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org#define kLithiumScratchReg2 s4
31189e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org#define kLithiumScratchDouble f30
31289e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org#define kDoubleRegZero f28
31334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
3147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// FPU (coprocessor 1) control registers.
3157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// Currently only FCSR (#31) is implemented.
3167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgstruct FPUControlRegister {
3177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  bool is_valid() const { return code_ == kFCSRRegister; }
3187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  bool is(FPUControlRegister creg) const { return code_ == creg.code_; }
3197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  int code() const {
3207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    ASSERT(is_valid());
3217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    return code_;
3227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
3237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  int bit() const {
3247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    ASSERT(is_valid());
3257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    return 1 << code_;
3267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
3277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void setcode(int f) {
3287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    code_ = f;
3297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    ASSERT(is_valid());
3307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
3317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Unfortunately we can't make this private in a struct.
3327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  int code_;
3335c838251403b0be9a882540f1922577abba4c872ager@chromium.org};
3345c838251403b0be9a882540f1922577abba4c872ager@chromium.org
33583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgconst FPUControlRegister no_fpucreg = { kInvalidFPUControlRegister };
3367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgconst FPUControlRegister FCSR = { kFCSRRegister };
3375c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3385c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3395c838251403b0be9a882540f1922577abba4c872ager@chromium.org// -----------------------------------------------------------------------------
3405c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Machine instruction Operands.
3415c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3425c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Class Operand represents a shifter operand in data processing instructions.
3435c838251403b0be9a882540f1922577abba4c872ager@chromium.orgclass Operand BASE_EMBEDDED {
3445c838251403b0be9a882540f1922577abba4c872ager@chromium.org public:
3455c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Immediate.
3465c838251403b0be9a882540f1922577abba4c872ager@chromium.org  INLINE(explicit Operand(int32_t immediate,
34759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org         RelocInfo::Mode rmode = RelocInfo::NONE32));
3485c838251403b0be9a882540f1922577abba4c872ager@chromium.org  INLINE(explicit Operand(const ExternalReference& f));
3495c838251403b0be9a882540f1922577abba4c872ager@chromium.org  INLINE(explicit Operand(const char* s));
3505c838251403b0be9a882540f1922577abba4c872ager@chromium.org  INLINE(explicit Operand(Object** opp));
3515c838251403b0be9a882540f1922577abba4c872ager@chromium.org  INLINE(explicit Operand(Context** cpp));
3525c838251403b0be9a882540f1922577abba4c872ager@chromium.org  explicit Operand(Handle<Object> handle);
3535c838251403b0be9a882540f1922577abba4c872ager@chromium.org  INLINE(explicit Operand(Smi* value));
3545c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3555c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Register.
3565c838251403b0be9a882540f1922577abba4c872ager@chromium.org  INLINE(explicit Operand(Register rm));
3575c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3585c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Return true if this is a register operand.
3595c838251403b0be9a882540f1922577abba4c872ager@chromium.org  INLINE(bool is_reg() const);
3605c838251403b0be9a882540f1922577abba4c872ager@chromium.org
361594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  inline int32_t immediate() const {
362594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    ASSERT(!is_reg());
363594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    return imm32_;
364594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  }
365594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org
3665c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Register rm() const { return rm_; }
3675c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3685c838251403b0be9a882540f1922577abba4c872ager@chromium.org private:
3695c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Register rm_;
37083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  int32_t imm32_;  // Valid if rm_ == no_reg.
3715c838251403b0be9a882540f1922577abba4c872ager@chromium.org  RelocInfo::Mode rmode_;
3725c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3735c838251403b0be9a882540f1922577abba4c872ager@chromium.org  friend class Assembler;
3745c838251403b0be9a882540f1922577abba4c872ager@chromium.org  friend class MacroAssembler;
3755c838251403b0be9a882540f1922577abba4c872ager@chromium.org};
3765c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3775c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3785c838251403b0be9a882540f1922577abba4c872ager@chromium.org// On MIPS we have only one adressing mode with base_reg + offset.
3795c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Class MemOperand represents a memory operand in load and store instructions.
3805c838251403b0be9a882540f1922577abba4c872ager@chromium.orgclass MemOperand : public Operand {
3815c838251403b0be9a882540f1922577abba4c872ager@chromium.org public:
3827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  explicit MemOperand(Register rn, int32_t offset = 0);
38304921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org  int32_t offset() const { return offset_; }
3845c838251403b0be9a882540f1922577abba4c872ager@chromium.org
38534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  bool OffsetIsInt16Encodable() const {
38634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    return is_int16(offset_);
38734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  }
38834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
3895c838251403b0be9a882540f1922577abba4c872ager@chromium.org private:
3907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  int32_t offset_;
3915c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3925c838251403b0be9a882540f1922577abba4c872ager@chromium.org  friend class Assembler;
3935c838251403b0be9a882540f1922577abba4c872ager@chromium.org};
3945c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3955c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// CpuFeatures keeps track of which features are supported by the target CPU.
397750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org// Supported features must be enabled by a CpuFeatureScope before use.
39883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgclass CpuFeatures : public AllStatic {
3997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org public:
4007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Detect features of the target CPU. Set safe defaults if the serializer
4017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // is enabled (snapshots must be portable).
40283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static void Probe();
4037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Check whether a feature is supported by the target CPU.
40583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static bool IsSupported(CpuFeature f) {
40683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    ASSERT(initialized_);
4077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    return (supported_ & (1u << f)) != 0;
4087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
4097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
410750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
41183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    ASSERT(initialized_);
412750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    return (found_by_runtime_probing_only_ &
413750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org            (static_cast<uint64_t>(1) << f)) != 0;
4147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
41583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
4166e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  static bool IsSafeForSnapshot(CpuFeature f) {
4176e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org    return (IsSupported(f) &&
4186e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org            (!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f)));
4196e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  }
4206e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org
42183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org private:
42283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org#ifdef DEBUG
42383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static bool initialized_;
42483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org#endif
42583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static unsigned supported_;
426750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  static unsigned found_by_runtime_probing_only_;
4277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
428003650ee766f5e92756d470a37973fd371757485yangguo@chromium.org  friend class ExternalReference;
4297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
4307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org};
4317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgclass Assembler : public AssemblerBase {
4345c838251403b0be9a882540f1922577abba4c872ager@chromium.org public:
4355c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Create an assembler. Instructions and relocation information are emitted
4365c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // into a buffer, with the instructions starting from the beginning and the
4375c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // relocation information starting from the end of the buffer. See CodeDesc
4385c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // for a detailed comment on the layout (globals.h).
4395c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //
4405c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // If the provided buffer is NULL, the assembler allocates and grows its own
4415c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // buffer, and buffer_size determines the initial buffer size. The buffer is
4425c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // owned by the assembler and deallocated upon destruction of the assembler.
4435c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //
4445c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // If the provided buffer is not NULL, the assembler uses the provided buffer
4455c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // for code generation and assumes its size to be buffer_size. If the buffer
4465c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // is too small, a fatal error occurs. No deallocation of the buffer is done
4475c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // upon destruction of the assembler.
44883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Assembler(Isolate* isolate, void* buffer, int buffer_size);
4498e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  virtual ~Assembler() { }
4505c838251403b0be9a882540f1922577abba4c872ager@chromium.org
4515c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // GetCode emits any pending (non-emitted) code and fills the descriptor
4525c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // desc. GetCode() is idempotent; it returns the same result if no other
4535c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Assembler functions are invoked in between GetCode() calls.
4545c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void GetCode(CodeDesc* desc);
4555c838251403b0be9a882540f1922577abba4c872ager@chromium.org
4565c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Label operations & relative jumps (PPUM Appendix D).
4575c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //
4585c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Takes a branch opcode (cc) and a label (L) and generates
4595c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // either a backward branch or a forward branch and links it
4605c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // to the label fixup chain. Usage:
4615c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //
4625c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Label L;    // unbound label
4635c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // j(cc, &L);  // forward branch to unbound label
4645c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // bind(&L);   // bind label to the current pc
4655c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // j(cc, &L);  // backward branch to bound label
4665c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // bind(&L);   // illegal: a label may be bound only once
4675c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //
4685c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Note: The same Label can be used for forward and backward branches
4695c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // but it may be bound only once.
47083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void bind(Label* L);  // Binds an unbound label L to current code position.
4713cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // Determines if Label is bound and near enough so that branch instruction
4723cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // can be used to reach it, instead of jump instruction.
4733cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  bool is_near(Label* L);
4745c838251403b0be9a882540f1922577abba4c872ager@chromium.org
47583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Returns the branch offset to the given label from the current code
47683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // position. Links the label to the current position if it is still unbound.
4775c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Manages the jump elimination optimization if the second parameter is true.
4785c838251403b0be9a882540f1922577abba4c872ager@chromium.org  int32_t branch_offset(Label* L, bool jump_elimination_allowed);
4795c838251403b0be9a882540f1922577abba4c872ager@chromium.org  int32_t shifted_branch_offset(Label* L, bool jump_elimination_allowed) {
4805c838251403b0be9a882540f1922577abba4c872ager@chromium.org    int32_t o = branch_offset(L, jump_elimination_allowed);
4815c838251403b0be9a882540f1922577abba4c872ager@chromium.org    ASSERT((o & 3) == 0);   // Assert the offset is aligned.
4825c838251403b0be9a882540f1922577abba4c872ager@chromium.org    return o >> 2;
4835c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
4843cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  uint32_t jump_address(Label* L);
4855c838251403b0be9a882540f1922577abba4c872ager@chromium.org
4865c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Puts a labels target address at the given position.
4875c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // The high 8 bits are set to zero.
4885c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void label_at_put(Label* L, int at_offset);
4895c838251403b0be9a882540f1922577abba4c872ager@chromium.org
4905c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Read/Modify the code target address in the branch/call instruction at pc.
4915c838251403b0be9a882540f1922577abba4c872ager@chromium.org  static Address target_address_at(Address pc);
4925c838251403b0be9a882540f1922577abba4c872ager@chromium.org  static void set_target_address_at(Address pc, Address target);
4935c838251403b0be9a882540f1922577abba4c872ager@chromium.org
49489e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  // Return the code target address at a call site from the return address
49589e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  // of that call in the instruction stream.
49689e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  inline static Address target_address_from_return_address(Address pc);
49789e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org
49834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  static void JumpLabelToJumpRegister(Address pc);
49934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
50028faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org  static void QuietNaN(HeapObject* nan);
50128faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org
5025c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // This sets the branch destination (which gets loaded at the call address).
50388aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org  // This is for calls and branches within generated code.  The serializer
50488aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org  // has already deserialized the lui/ori instructions etc.
50588aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org  inline static void deserialization_set_special_target_at(
50688aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org      Address instruction_payload, Address target) {
50788aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org    set_target_address_at(
50888aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org        instruction_payload - kInstructionsFor32BitConstant * kInstrSize,
50988aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org        target);
5105c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
5115c838251403b0be9a882540f1922577abba4c872ager@chromium.org
5125c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // This sets the branch destination.
5135c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // This is for calls and branches to runtime code.
5145c838251403b0be9a882540f1922577abba4c872ager@chromium.org  inline static void set_external_target_at(Address instruction_payload,
5155c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                            Address target) {
5165c838251403b0be9a882540f1922577abba4c872ager@chromium.org    set_target_address_at(instruction_payload, target);
5175c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
5185c838251403b0be9a882540f1922577abba4c872ager@chromium.org
5197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Size of an instruction.
5207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kInstrSize = sizeof(Instr);
5217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Difference between address of current opcode and target address offset.
5237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kBranchPCOffset = 4;
5247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Here we are patching the address in the LUI/ORI instruction pair.
5267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // These values are used in the serialization process and must be zero for
5277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // MIPS platform, as Code, Embedded Object or External-reference pointers
5287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // are split across two consecutive instructions and don't exist separately
5297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // in the code, so the serializer should not step forwards in memory after
5307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // a target is resolved and written.
53188aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org  static const int kSpecialTargetSize = 0;
5327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Number of consecutive instructions used to store 32bit constant.
53434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // Before jump-optimizations, this constant was used in
53534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // RelocInfo::target_address_address() function to tell serializer address of
53634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // the instruction that follows LUI/ORI instruction pair. Now, with new jump
53734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // optimization, where jump-through-register instruction that usually
53834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // follows LUI/ORI pair is substituted with J/JAL, this constant equals
53934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // to 3 instructions (LUI+ORI+J/JAL/JR/JALR).
54034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  static const int kInstructionsFor32BitConstant = 3;
5415c838251403b0be9a882540f1922577abba4c872ager@chromium.org
5425c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Distance between the instruction referring to the address of the call
5435c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // target and the return address.
5445c838251403b0be9a882540f1922577abba4c872ager@chromium.org  static const int kCallTargetAddressOffset = 4 * kInstrSize;
5455c838251403b0be9a882540f1922577abba4c872ager@chromium.org
5465c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Distance between start of patched return sequence and the emitted address
5475c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // to jump to.
5487516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kPatchReturnSequenceAddressOffset = 0;
5495c838251403b0be9a882540f1922577abba4c872ager@chromium.org
5502356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org  // Distance between start of patched debug break slot and the emitted address
5512356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org  // to jump to.
5527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kPatchDebugBreakSlotAddressOffset =  0 * kInstrSize;
5537516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Difference between address of current opcode and value read from pc
5557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // register.
5567516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kPcLoadDelta = 4;
5577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
55889e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  static const int kPatchDebugBreakSlotReturnOffset = 4 * kInstrSize;
55989e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org
5607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Number of instructions used for the JS return sequence. The constant is
5617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // used by the debugger to patch the JS return sequence.
5627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kJSReturnSequenceInstructions = 7;
5637516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kDebugBreakSlotInstructions = 4;
5647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kDebugBreakSlotLength =
5657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      kDebugBreakSlotInstructions * kInstrSize;
5667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5675c838251403b0be9a882540f1922577abba4c872ager@chromium.org
5685c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // ---------------------------------------------------------------------------
5695c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Code generation.
5705c838251403b0be9a882540f1922577abba4c872ager@chromium.org
5717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Insert the smallest number of nop instructions
5727516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // possible to align the pc offset to a multiple
5737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // of m. m must be a power of 2 (>= 4).
5747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void Align(int m);
5757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Aligns code to something that's optimal for a jump target for the platform.
5767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void CodeTargetAlign();
5777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5787516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Different nop operations are used by the code generator to detect certain
5797516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // states of the generated code.
5807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  enum NopMarkerTypes {
5817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    NON_MARKING_NOP = 0,
5827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    DEBUG_BREAK_NOP,
5837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    // IC markers.
5847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    PROPERTY_ACCESS_INLINED,
5857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    PROPERTY_ACCESS_INLINED_CONTEXT,
5867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
5877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    // Helper values.
5887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    LAST_CODE_MARKER,
589fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED,
590fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // Code aging
591ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    CODE_AGE_MARKER_NOP = 6,
592ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    CODE_AGE_SEQUENCE_NOP
5937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  };
5947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
59533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  // Type == 0 is the default non-marking nop. For mips this is a
59633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  // sll(zero_reg, zero_reg, 0). We use rt_reg == at for non-zero
59733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  // marking, to avoid conflict with ssnop and ehb instructions.
5987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void nop(unsigned int type = 0) {
5997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    ASSERT(type < 32);
60033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    Register nop_rt_reg = (type == 0) ? zero_reg : at;
60133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    sll(zero_reg, nop_rt_reg, type, true);
6027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
6035c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6045c838251403b0be9a882540f1922577abba4c872ager@chromium.org
60583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // --------Branch-and-jump-instructions----------
6065c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // We don't use likely variant of instructions.
6075c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void b(int16_t offset);
6085c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void b(Label* L) { b(branch_offset(L, false)>>2); }
6095c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bal(int16_t offset);
6105c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bal(Label* L) { bal(branch_offset(L, false)>>2); }
6115c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6125c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void beq(Register rs, Register rt, int16_t offset);
6135c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void beq(Register rs, Register rt, Label* L) {
6145c838251403b0be9a882540f1922577abba4c872ager@chromium.org    beq(rs, rt, branch_offset(L, false) >> 2);
6155c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
6165c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bgez(Register rs, int16_t offset);
6175c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bgezal(Register rs, int16_t offset);
6185c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bgtz(Register rs, int16_t offset);
6195c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void blez(Register rs, int16_t offset);
6205c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bltz(Register rs, int16_t offset);
6215c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bltzal(Register rs, int16_t offset);
6225c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bne(Register rs, Register rt, int16_t offset);
6235c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bne(Register rs, Register rt, Label* L) {
6245c838251403b0be9a882540f1922577abba4c872ager@chromium.org    bne(rs, rt, branch_offset(L, false)>>2);
6255c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
6265c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6275c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Never use the int16_t b(l)cond version with a branch offset
62883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // instead of using the Label* version.
6295c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6302efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // Jump targets must be in the current 256 MB-aligned region. i.e. 28 bits.
6315c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void j(int32_t target);
6325c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void jal(int32_t target);
6335c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void jalr(Register rs, Register rd = ra);
6345c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void jr(Register target);
63534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  void j_or_jr(int32_t target, Register rs);
63634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  void jal_or_jalr(int32_t target, Register rs);
6375c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6385c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6395c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //-------Data-processing-instructions---------
6405c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6415c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Arithmetic.
6425c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void addu(Register rd, Register rs, Register rt);
6435c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void subu(Register rd, Register rs, Register rt);
6445c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void mult(Register rs, Register rt);
6455c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void multu(Register rs, Register rt);
6465c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void div(Register rs, Register rt);
6475c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void divu(Register rs, Register rt);
6485c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void mul(Register rd, Register rs, Register rt);
6495c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6505c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void addiu(Register rd, Register rs, int32_t j);
6515c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6525c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Logical.
6535c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void and_(Register rd, Register rs, Register rt);
6545c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void or_(Register rd, Register rs, Register rt);
6555c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void xor_(Register rd, Register rs, Register rt);
6565c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void nor(Register rd, Register rs, Register rt);
6575c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6585c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void andi(Register rd, Register rs, int32_t j);
6595c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void ori(Register rd, Register rs, int32_t j);
6605c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void xori(Register rd, Register rs, int32_t j);
6615c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void lui(Register rd, int32_t j);
6625c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6635c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Shifts.
6647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Please note: sll(zero_reg, zero_reg, x) instructions are reserved as nop
6657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // and may cause problems in normal code. coming_from_nop makes sure this
6667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // doesn't happen.
6677516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void sll(Register rd, Register rt, uint16_t sa, bool coming_from_nop = false);
6685c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void sllv(Register rd, Register rt, Register rs);
6695c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void srl(Register rd, Register rt, uint16_t sa);
6705c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void srlv(Register rd, Register rt, Register rs);
6715c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void sra(Register rt, Register rd, uint16_t sa);
6725c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void srav(Register rt, Register rd, Register rs);
6737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void rotr(Register rd, Register rt, uint16_t sa);
6747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void rotrv(Register rd, Register rt, Register rs);
6755c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6765c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6775c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //------------Memory-instructions-------------
6785c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6795c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void lb(Register rd, const MemOperand& rs);
6805c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void lbu(Register rd, const MemOperand& rs);
6817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void lh(Register rd, const MemOperand& rs);
6827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void lhu(Register rd, const MemOperand& rs);
6835c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void lw(Register rd, const MemOperand& rs);
6847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void lwl(Register rd, const MemOperand& rs);
6857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void lwr(Register rd, const MemOperand& rs);
6865c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void sb(Register rd, const MemOperand& rs);
6877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void sh(Register rd, const MemOperand& rs);
6885c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void sw(Register rd, const MemOperand& rs);
6897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void swl(Register rd, const MemOperand& rs);
6907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void swr(Register rd, const MemOperand& rs);
6915c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6925c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6935c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //-------------Misc-instructions--------------
6945c838251403b0be9a882540f1922577abba4c872ager@chromium.org
6955c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Break / Trap instructions.
696c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org  void break_(uint32_t code, bool break_as_stop = false);
697c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org  void stop(const char* msg, uint32_t code = kMaxStopCode);
6985c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void tge(Register rs, Register rt, uint16_t code);
6995c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void tgeu(Register rs, Register rt, uint16_t code);
7005c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void tlt(Register rs, Register rt, uint16_t code);
7015c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void tltu(Register rs, Register rt, uint16_t code);
7025c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void teq(Register rs, Register rt, uint16_t code);
7035c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void tne(Register rs, Register rt, uint16_t code);
7045c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7055c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Move from HI/LO register.
7065c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void mfhi(Register rd);
7075c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void mflo(Register rd);
7085c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7095c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Set on less than.
7105c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void slt(Register rd, Register rs, Register rt);
7115c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void sltu(Register rd, Register rs, Register rt);
7125c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void slti(Register rd, Register rs, int32_t j);
7135c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void sltiu(Register rd, Register rs, int32_t j);
7145c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Conditional move.
7167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void movz(Register rd, Register rs, Register rt);
7177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void movn(Register rd, Register rs, Register rt);
7187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void movt(Register rd, Register rs, uint16_t cc = 0);
7197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void movf(Register rd, Register rs, uint16_t cc = 0);
7207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
7217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Bit twiddling.
7227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void clz(Register rd, Register rs);
7237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void ins_(Register rt, Register rs, uint16_t pos, uint16_t size);
7247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void ext_(Register rt, Register rs, uint16_t pos, uint16_t size);
7255c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7265c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //--------Coprocessor-instructions----------------
7275c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7285c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Load, store, and move.
7295c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void lwc1(FPURegister fd, const MemOperand& src);
7305c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void ldc1(FPURegister fd, const MemOperand& src);
7315c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7325c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void swc1(FPURegister fs, const MemOperand& dst);
7335c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void sdc1(FPURegister fs, const MemOperand& dst);
7345c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void mtc1(Register rt, FPURegister fs);
7367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void mfc1(Register rt, FPURegister fs);
7377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
7387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void ctc1(Register rt, FPUControlRegister fs);
7397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void cfc1(Register rt, FPUControlRegister fs);
7407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
7417516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Arithmetic.
7427516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void add_d(FPURegister fd, FPURegister fs, FPURegister ft);
7437516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void sub_d(FPURegister fd, FPURegister fs, FPURegister ft);
7447516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void mul_d(FPURegister fd, FPURegister fs, FPURegister ft);
74559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  void madd_d(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft);
7467516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void div_d(FPURegister fd, FPURegister fs, FPURegister ft);
7477516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void abs_d(FPURegister fd, FPURegister fs);
7487516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void mov_d(FPURegister fd, FPURegister fs);
7497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void neg_d(FPURegister fd, FPURegister fs);
7507516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void sqrt_d(FPURegister fd, FPURegister fs);
7515c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7525c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Conversion.
7535c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void cvt_w_s(FPURegister fd, FPURegister fs);
7545c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void cvt_w_d(FPURegister fd, FPURegister fs);
7557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void trunc_w_s(FPURegister fd, FPURegister fs);
7567516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void trunc_w_d(FPURegister fd, FPURegister fs);
7577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void round_w_s(FPURegister fd, FPURegister fs);
7587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void round_w_d(FPURegister fd, FPURegister fs);
7597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void floor_w_s(FPURegister fd, FPURegister fs);
7607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void floor_w_d(FPURegister fd, FPURegister fs);
7617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void ceil_w_s(FPURegister fd, FPURegister fs);
7627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void ceil_w_d(FPURegister fd, FPURegister fs);
7635c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7645c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void cvt_l_s(FPURegister fd, FPURegister fs);
7655c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void cvt_l_d(FPURegister fd, FPURegister fs);
7667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void trunc_l_s(FPURegister fd, FPURegister fs);
7677516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void trunc_l_d(FPURegister fd, FPURegister fs);
7687516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void round_l_s(FPURegister fd, FPURegister fs);
7697516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void round_l_d(FPURegister fd, FPURegister fs);
7707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void floor_l_s(FPURegister fd, FPURegister fs);
7717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void floor_l_d(FPURegister fd, FPURegister fs);
7727516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void ceil_l_s(FPURegister fd, FPURegister fs);
7737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void ceil_l_d(FPURegister fd, FPURegister fs);
7745c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7755c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void cvt_s_w(FPURegister fd, FPURegister fs);
7765c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void cvt_s_l(FPURegister fd, FPURegister fs);
7775c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void cvt_s_d(FPURegister fd, FPURegister fs);
7785c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7795c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void cvt_d_w(FPURegister fd, FPURegister fs);
7805c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void cvt_d_l(FPURegister fd, FPURegister fs);
7815c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void cvt_d_s(FPURegister fd, FPURegister fs);
7825c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7835c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Conditions and branches.
7845c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void c(FPUCondition cond, SecondaryField fmt,
7855c838251403b0be9a882540f1922577abba4c872ager@chromium.org         FPURegister ft, FPURegister fs, uint16_t cc = 0);
7865c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7875c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bc1f(int16_t offset, uint16_t cc = 0);
7885c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bc1f(Label* L, uint16_t cc = 0) { bc1f(branch_offset(L, false)>>2, cc); }
7895c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bc1t(int16_t offset, uint16_t cc = 0);
7905c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bc1t(Label* L, uint16_t cc = 0) { bc1t(branch_offset(L, false)>>2, cc); }
7917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void fcmp(FPURegister src1, const double src2, FPUCondition cond);
7925c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7935c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Check the code size generated from label to here.
7946db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  int SizeOfCodeGeneratedSince(Label* label) {
7956db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    return pc_offset() - label->pos();
7966db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  }
7976db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
7986db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // Check the number of instructions generated from label to here.
7996db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  int InstructionsGeneratedSince(Label* label) {
8006db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    return SizeOfCodeGeneratedSince(label) / kInstrSize;
8015c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
8025c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Class for scoping postponing the trampoline pool generation.
8047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  class BlockTrampolinePoolScope {
8057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org   public:
8067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) {
8077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      assem_->StartBlockTrampolinePool();
8087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    }
8097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    ~BlockTrampolinePoolScope() {
8107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      assem_->EndBlockTrampolinePool();
8117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    }
8127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8137516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org   private:
8147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    Assembler* assem_;
8157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope);
8177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  };
8187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8193cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // Class for postponing the assembly buffer growth. Typically used for
8203cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // sequences of instructions that must be emitted as a unit, before
8213cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // buffer growth (and relocation) can occur.
8223cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // This blocking scope is not nestable.
8233cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  class BlockGrowBufferScope {
8243cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org   public:
8253cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    explicit BlockGrowBufferScope(Assembler* assem) : assem_(assem) {
8263cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      assem_->StartBlockGrowBuffer();
8273cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    }
8283cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    ~BlockGrowBufferScope() {
8293cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      assem_->EndBlockGrowBuffer();
8303cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    }
8313cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
8323cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    private:
8333cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org     Assembler* assem_;
8343cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
8353cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org     DISALLOW_IMPLICIT_CONSTRUCTORS(BlockGrowBufferScope);
8363cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  };
8373cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
8385c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Debugging.
8395c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8405c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Mark address of the ExitJSFrame code.
8415c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void RecordJSReturn();
8425c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8437516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Mark address of a debug break slot.
8447516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void RecordDebugBreakSlot();
8457516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
84683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Record the AST id of the CallIC being compiled, so that it can be placed
84783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // in the relocation information.
848471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org  void SetRecordedAstId(TypeFeedbackId ast_id) {
849471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org    ASSERT(recorded_ast_id_.IsNone());
850717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org    recorded_ast_id_ = ast_id;
851717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org  }
852717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org
853471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org  TypeFeedbackId RecordedAstId() {
854471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org    ASSERT(!recorded_ast_id_.IsNone());
855717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org    return recorded_ast_id_;
856717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org  }
857717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org
858471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org  void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
85983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
8605c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Record a comment relocation entry that can be used by a disassembler.
8617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Use --code-comments to enable.
8625c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void RecordComment(const char* msg);
8635c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8643cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  static int RelocateInternalReference(byte* pc, intptr_t pc_delta);
8653cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
8667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Writes a single byte or word of data in the code stream.  Used for
8677516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // inline tables, e.g., jump-tables.
8687516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void db(uint8_t data);
8697516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void dd(uint32_t data);
8705c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  PositionsRecorder* positions_recorder() { return &positions_recorder_; }
8727516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Postpone the generation of the trampoline pool for the specified number of
8747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // instructions.
8757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void BlockTrampolinePoolFor(int instructions);
8767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8775c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Check if there is less than kGap bytes available in the buffer.
8785c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // If this is the case, we need to grow the buffer before emitting
8795c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // an instruction or relocation information.
8805c838251403b0be9a882540f1922577abba4c872ager@chromium.org  inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; }
8815c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8825c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Get the number of bytes available in the buffer.
8835c838251403b0be9a882540f1922577abba4c872ager@chromium.org  inline int available_space() const { return reloc_info_writer.pos() - pc_; }
8845c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8855c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Read/patch instructions.
8865c838251403b0be9a882540f1922577abba4c872ager@chromium.org  static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
8877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static void instr_at_put(byte* pc, Instr instr) {
8885c838251403b0be9a882540f1922577abba4c872ager@chromium.org    *reinterpret_cast<Instr*>(pc) = instr;
8895c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
8905c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
8915c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void instr_at_put(int pos, Instr instr) {
8925c838251403b0be9a882540f1922577abba4c872ager@chromium.org    *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
8935c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
8945c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8955c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Check if an instruction is a branch of some kind.
8967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsBranch(Instr instr);
89783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static bool IsBeq(Instr instr);
89883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static bool IsBne(Instr instr);
8997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9003cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  static bool IsJump(Instr instr);
9013cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  static bool IsJ(Instr instr);
9023cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  static bool IsLui(Instr instr);
9033cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  static bool IsOri(Instr instr);
9043cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
90534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  static bool IsJal(Instr instr);
90634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  static bool IsJr(Instr instr);
90734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  static bool IsJalr(Instr instr);
90834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
9097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsNop(Instr instr, unsigned int type);
9107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsPop(Instr instr);
9117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsPush(Instr instr);
9127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsLwRegFpOffset(Instr instr);
9137516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsSwRegFpOffset(Instr instr);
9147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsLwRegFpNegOffset(Instr instr);
9157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsSwRegFpNegOffset(Instr instr);
9167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
91783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static Register GetRtReg(Instr instr);
91883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static Register GetRsReg(Instr instr);
91983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static Register GetRdReg(Instr instr);
92083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
92183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetRt(Instr instr);
92283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetRtField(Instr instr);
92383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetRs(Instr instr);
92483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetRsField(Instr instr);
92583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetRd(Instr instr);
92683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetRdField(Instr instr);
92783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetSa(Instr instr);
92883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetSaField(Instr instr);
92983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetOpcodeField(Instr instr);
9303cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  static uint32_t GetFunction(Instr instr);
9313cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  static uint32_t GetFunctionField(Instr instr);
93283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetImmediate16(Instr instr);
93383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static uint32_t GetLabelConst(Instr instr);
9347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static int32_t GetBranchOffset(Instr instr);
9367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsLw(Instr instr);
9377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static int16_t GetLwOffset(Instr instr);
9387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static Instr SetLwOffset(Instr instr, int16_t offset);
9397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsSw(Instr instr);
9417516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static Instr SetSwOffset(Instr instr, int16_t offset);
9427516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static bool IsAddImmediate(Instr instr);
9437516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static Instr SetAddImmediateOffset(Instr instr, int16_t offset);
9447516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
94583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static bool IsAndImmediate(Instr instr);
9467bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org  static bool IsEmittedConstant(Instr instr);
94783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
9483cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  void CheckTrampolinePool();
9497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9507516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org protected:
95183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Relocation for a type-recording IC has the AST id added to it.  This
95283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // member variable is a way to pass the information from the call site to
95383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // the relocation info.
954471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org  TypeFeedbackId recorded_ast_id_;
95583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
9567516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  int32_t buffer_space() const { return reloc_info_writer.pos() - pc_; }
9575c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9585c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Decode branch instruction at pos and return branch target pos.
9595c838251403b0be9a882540f1922577abba4c872ager@chromium.org  int target_at(int32_t pos);
9605c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9615c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Patch branch instruction at pos to branch to given branch target pos.
9625c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void target_at_put(int32_t pos, int32_t target_pos);
9635c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9645c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Say if we need to relocate with this mode.
9657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  bool MustUseReg(RelocInfo::Mode rmode);
9665c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9675c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Record reloc info for current pc_.
9685c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
9695c838251403b0be9a882540f1922577abba4c872ager@chromium.org
9707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Block the emission of the trampoline pool before pc_offset.
9717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void BlockTrampolinePoolBefore(int pc_offset) {
9727516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    if (no_trampoline_pool_before_ < pc_offset)
9737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      no_trampoline_pool_before_ = pc_offset;
9747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
9757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void StartBlockTrampolinePool() {
9777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    trampoline_pool_blocked_nesting_++;
9787516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
9793cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
9807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void EndBlockTrampolinePool() {
9817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    trampoline_pool_blocked_nesting_--;
9827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
9837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  bool is_trampoline_pool_blocked() const {
9857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    return trampoline_pool_blocked_nesting_ > 0;
9867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
9877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
98883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  bool has_exception() const {
98983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    return internal_trampoline_exception_;
99083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  }
99183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
99234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi);
99334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
9943cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  bool is_trampoline_emitted() const {
9953cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    return trampoline_emitted_;
9963cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  }
9973cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
9983cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // Temporarily block automatic assembly buffer growth.
9993cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  void StartBlockGrowBuffer() {
10003cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    ASSERT(!block_buffer_growth_);
10013cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    block_buffer_growth_ = true;
10023cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  }
10033cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
10043cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  void EndBlockGrowBuffer() {
10053cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    ASSERT(block_buffer_growth_);
10063cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    block_buffer_growth_ = false;
10073cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  }
10083cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
10093cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  bool is_buffer_growth_blocked() const {
10103cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    return block_buffer_growth_;
10113cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  }
10123cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
10135c838251403b0be9a882540f1922577abba4c872ager@chromium.org private:
10145c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Buffer size and constant pool distance are checked together at regular
10155c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // intervals of kBufferCheckInterval emitted bytes.
10165c838251403b0be9a882540f1922577abba4c872ager@chromium.org  static const int kBufferCheckInterval = 1*KB/2;
10175c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10185c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Code generation.
10195c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // The relocation writer's position is at least kGap bytes below the end of
10205c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // the generated instructions. This is so that multi-instruction sequences do
10215c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // not have to check for overflow. The same is true for writes of large
10225c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // relocation info entries.
10235c838251403b0be9a882540f1922577abba4c872ager@chromium.org  static const int kGap = 32;
10245c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Repeated checking whether the trampoline pool should be emitted is rather
10277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // expensive. By default we only check again once a number of instructions
10287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // has been generated.
10297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kCheckConstIntervalInst = 32;
10307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize;
10317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  int next_buffer_check_;  // pc offset of next buffer check.
10337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Emission of the trampoline pool may be blocked in some code sequences.
10357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  int trampoline_pool_blocked_nesting_;  // Block emission if this is not zero.
10367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  int no_trampoline_pool_before_;  // Block emission before this pc offset.
10377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Keep track of the last emitted pool to guarantee a maximal distance.
10397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  int last_trampoline_pool_end_;  // pc offset of the end of the last pool.
10407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10413cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // Automatic growth of the assembly buffer may be blocked for some sequences.
10423cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  bool block_buffer_growth_;  // Block growth when true.
10433cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
10445c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Relocation information generation.
10455c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Each relocation is encoded as a variable size value.
10465c838251403b0be9a882540f1922577abba4c872ager@chromium.org  static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
10475c838251403b0be9a882540f1922577abba4c872ager@chromium.org  RelocInfoWriter reloc_info_writer;
10485c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10495c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // The bound position, before this we cannot do instruction elimination.
10505c838251403b0be9a882540f1922577abba4c872ager@chromium.org  int last_bound_pos_;
10515c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10525c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Code emission.
10535c838251403b0be9a882540f1922577abba4c872ager@chromium.org  inline void CheckBuffer();
10545c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void GrowBuffer();
10555c838251403b0be9a882540f1922577abba4c872ager@chromium.org  inline void emit(Instr x);
10567516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  inline void CheckTrampolinePoolQuick();
10575c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10585c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Instruction generation.
10595c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // We have 3 different kind of encoding layout on MIPS.
10605c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // However due to many different types of objects encoded in the same fields
10615c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // we have quite a few aliases for each mode.
10625c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Using the same structure to refer to Register and FPURegister would spare a
10635c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // few aliases, but mixing both does not look clean to me.
10645c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Anyway we could surely implement this differently.
10655c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10665c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void GenInstrRegister(Opcode opcode,
10675c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        Register rs,
10685c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        Register rt,
10695c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        Register rd,
10705c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        uint16_t sa = 0,
10715c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        SecondaryField func = NULLSF);
10725c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10735c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void GenInstrRegister(Opcode opcode,
10747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                        Register rs,
10757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                        Register rt,
10767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                        uint16_t msb,
10777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                        uint16_t lsb,
10787516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                        SecondaryField func);
10797516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void GenInstrRegister(Opcode opcode,
10815c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        SecondaryField fmt,
10825c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        FPURegister ft,
10835c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        FPURegister fs,
10845c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        FPURegister fd,
10855c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        SecondaryField func = NULLSF);
10865c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10875c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void GenInstrRegister(Opcode opcode,
108859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                        FPURegister fr,
108959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                        FPURegister ft,
109059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                        FPURegister fs,
109159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                        FPURegister fd,
109259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                        SecondaryField func = NULLSF);
109359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
109459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  void GenInstrRegister(Opcode opcode,
10955c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        SecondaryField fmt,
10965c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        Register rt,
10975c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        FPURegister fs,
10985c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        FPURegister fd,
10995c838251403b0be9a882540f1922577abba4c872ager@chromium.org                        SecondaryField func = NULLSF);
11005c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void GenInstrRegister(Opcode opcode,
11027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                        SecondaryField fmt,
11037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                        Register rt,
11047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                        FPUControlRegister fs,
11057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                        SecondaryField func = NULLSF);
11067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
11075c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11085c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void GenInstrImmediate(Opcode opcode,
11095c838251403b0be9a882540f1922577abba4c872ager@chromium.org                         Register rs,
11105c838251403b0be9a882540f1922577abba4c872ager@chromium.org                         Register rt,
11115c838251403b0be9a882540f1922577abba4c872ager@chromium.org                         int32_t  j);
11125c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void GenInstrImmediate(Opcode opcode,
11135c838251403b0be9a882540f1922577abba4c872ager@chromium.org                         Register rs,
11145c838251403b0be9a882540f1922577abba4c872ager@chromium.org                         SecondaryField SF,
11155c838251403b0be9a882540f1922577abba4c872ager@chromium.org                         int32_t  j);
11165c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void GenInstrImmediate(Opcode opcode,
11175c838251403b0be9a882540f1922577abba4c872ager@chromium.org                         Register r1,
11185c838251403b0be9a882540f1922577abba4c872ager@chromium.org                         FPURegister r2,
11195c838251403b0be9a882540f1922577abba4c872ager@chromium.org                         int32_t  j);
11205c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11215c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11225c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void GenInstrJump(Opcode opcode,
11235c838251403b0be9a882540f1922577abba4c872ager@chromium.org                     uint32_t address);
11245c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Helpers.
11267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void LoadRegPlusOffsetToAt(const MemOperand& src);
11275c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11285c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Labels.
11295c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void print(Label* L);
11305c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void bind_to(Label* L, int pos);
11315c838251403b0be9a882540f1922577abba4c872ager@chromium.org  void next(Label* L);
11325c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // One trampoline consists of:
11347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // - space for trampoline slots,
11357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // - space for labels.
11367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  //
11377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Space for trampoline slots is equal to slot_count * 2 * kInstrSize.
11387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Space for trampoline slots preceeds space for labels. Each label is of one
11397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // instruction size, so total amount for labels is equal to
11407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // label_count *  kInstrSize.
11417516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  class Trampoline {
11427516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org   public:
11433cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    Trampoline() {
11443cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      start_ = 0;
11453cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      next_slot_ = 0;
11463cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      free_slot_count_ = 0;
11473cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      end_ = 0;
11483cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    }
11493cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    Trampoline(int start, int slot_count) {
11507516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      start_ = start;
11517516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      next_slot_ = start;
11527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      free_slot_count_ = slot_count;
11533cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org      end_ = start + slot_count * kTrampolineSlotsSize;
11547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    }
11557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    int start() {
11567516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      return start_;
11577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    }
11587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    int end() {
11597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      return end_;
11607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    }
11617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    int take_slot() {
116283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      int trampoline_slot = kInvalidSlotPos;
116383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      if (free_slot_count_ <= 0) {
116483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        // We have run out of space on trampolines.
116583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        // Make sure we fail in debug mode, so we become aware of each case
116683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        // when this happens.
116783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        ASSERT(0);
116883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        // Internal exception will be caught.
116983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      } else {
117083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        trampoline_slot = next_slot_;
117183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        free_slot_count_--;
11723cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org        next_slot_ += kTrampolineSlotsSize;
117383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      }
11747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      return trampoline_slot;
11757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    }
117683e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org
11777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org   private:
11787516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    int start_;
11797516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    int end_;
11807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    int next_slot_;
11817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    int free_slot_count_;
11827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  };
11837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
11843cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  int32_t get_trampoline_entry(int32_t pos);
11853cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  int unbound_labels_count_;
11863cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // If trampoline is emitted, generated code is becoming large. As this is
11873cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // already a slow case which can possibly break our code generation for the
11883cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // extreme case, we use this information to trigger different mode of
11893cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // branch instruction generation, where we use jump instructions rather
11903cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  // than regular branch instructions.
11913cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  bool trampoline_emitted_;
11923cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  static const int kTrampolineSlotsSize = 4 * kInstrSize;
11937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  static const int kMaxBranchOffset = (1 << (18 - 1)) - 1;
119483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  static const int kInvalidSlotPos = -1;
11957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
11963cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  Trampoline trampoline_;
119783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  bool internal_trampoline_exception_;
11987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
11995c838251403b0be9a882540f1922577abba4c872ager@chromium.org  friend class RegExpMacroAssemblerMIPS;
12005c838251403b0be9a882540f1922577abba4c872ager@chromium.org  friend class RelocInfo;
12017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  friend class CodePatcher;
12027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  friend class BlockTrampolinePoolScope;
12037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  PositionsRecorder positions_recorder_;
12057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  friend class PositionsRecorder;
12067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  friend class EnsureSpace;
12077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org};
12087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgclass EnsureSpace BASE_EMBEDDED {
12117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org public:
12127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  explicit EnsureSpace(Assembler* assembler) {
12137516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    assembler->CheckBuffer();
12147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
12155c838251403b0be9a882540f1922577abba4c872ager@chromium.org};
12165c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12175c838251403b0be9a882540f1922577abba4c872ager@chromium.org} }  // namespace v8::internal
12185c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12195c838251403b0be9a882540f1922577abba4c872ager@chromium.org#endif  // V8_ARM_ASSEMBLER_MIPS_H_
1220