13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
23100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Redistribution and use in source and binary forms, with or without
33100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// modification, are permitted provided that the following conditions are
43100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// met:
53100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//
63100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//     * Redistributions of source code must retain the above copyright
73100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       notice, this list of conditions and the following disclaimer.
83100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//     * Redistributions in binary form must reproduce the above
93100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       copyright notice, this list of conditions and the following
103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       disclaimer in the documentation and/or other materials provided
113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       with the distribution.
123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//     * Neither the name of Google Inc. nor the names of its
133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       contributors may be used to endorse or promote products derived
143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       from this software without specific prior written permission.
153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//
163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#ifndef V8_MIPS_MACRO_ASSEMBLER_MIPS_H_
293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define V8_MIPS_MACRO_ASSEMBLER_MIPS_H_
303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "assembler.h"
323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "mips/assembler-mips.h"
33257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "v8globals.h"
343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace v8 {
363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace internal {
373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Forward declaration.
393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuclass JumpTarget;
403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Reserved Register Usage Summary.
4244f0eee88ff00398ff7f715fab053374d808c90dSteve Block//
4344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Registers t8, t9, and at are reserved for use by the MacroAssembler.
4444f0eee88ff00398ff7f715fab053374d808c90dSteve Block//
4544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// The programmer should know that the MacroAssembler may clobber these three,
4644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// but won't touch other registers except in special cases.
4744f0eee88ff00398ff7f715fab053374d808c90dSteve Block//
4844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Per the MIPS ABI, register t9 must be used for indirect function call
4944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// via 'jalr t9' or 'jr t9' instructions. This is relied upon by gcc when
5044f0eee88ff00398ff7f715fab053374d808c90dSteve Block// trying to update gp register for position-independent-code. Whenever
5144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// MIPS generated code calls C code, it must be via t9 register.
523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
53592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
5444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Flags used for the AllocateInNewSpace functions.
5544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockenum AllocationFlags {
5644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // No special flags.
5744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  NO_ALLOCATION_FLAGS = 0,
5844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Return the pointer to the allocated already tagged as a heap object.
5944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  TAG_OBJECT = 1 << 0,
6044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // The content of the result register already contains the allocation top in
6144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // new space.
6244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  RESULT_CONTAINS_TOP = 1 << 1,
6344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Specify that the requested size of the space to allocate is specified in
6444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // words instead of bytes.
6544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  SIZE_IN_WORDS = 1 << 2
6644f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
6744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Flags used for the ObjectToDoubleFPURegister function.
6944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockenum ObjectToDoubleFlags {
7044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // No special flags.
7144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  NO_OBJECT_TO_DOUBLE_FLAGS = 0,
7244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Object is known to be a non smi.
7344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  OBJECT_NOT_SMI = 1 << 0,
7444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Don't load NaNs or infinities, branch to the non number case instead.
7544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  AVOID_NANS_AND_INFINITIES = 1 << 1
7644f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
7744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Allow programmer to use Branch Delay Slot of Branches, Jumps, Calls.
7944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockenum BranchDelaySlot {
8044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  USE_DELAY_SLOT,
8144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  PROTECT
8244f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
8344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Flags used for the li macro-assembler function.
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum LiFlags {
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the constant value can be represented in just 16 bits, then
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // optimize the li to use a single instruction, rather than lui/ori pair.
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  OPTIMIZE_SIZE = 0,
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Always use 2 instructions (lui/ori pair), even if the constant could
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // be loaded with just one, so that this value is patchable later.
913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CONSTANT_SIZE = 1
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum RAStatus { kRAHasNotBeenSaved, kRAHasBeenSaved };
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool AreAliased(Register r1, Register r2, Register r3, Register r4);
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// -----------------------------------------------------------------------------
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Static helper functions.
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline MemOperand ContextOperand(Register context, int index) {
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return MemOperand(context, Context::SlotOffset(index));
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline MemOperand GlobalObjectOperand()  {
1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return ContextOperand(cp, Context::GLOBAL_INDEX);
1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Generate a MemOperand for loading a field from an object.
1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline MemOperand FieldMemOperand(Register object, int offset) {
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return MemOperand(object, offset - kHeapObjectTag);
1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Generate a MemOperand for storing arguments 5..N on the stack
1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// when calling CallCFunction().
1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline MemOperand CFunctionArgumentOperand(int index) {
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(index > kCArgSlotCount);
1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Argument 5 takes the slot just past the four Arg-slots.
1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int offset = (index - 5) * kPointerSize + kCArgsSlotsSize;
1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return MemOperand(sp, offset);
1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// MacroAssembler implements a collection of frequently used macros.
1323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuclass MacroAssembler: public Assembler {
1333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu public:
134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // The isolate parameter can be NULL if the macro assembler should
135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // not use isolate-dependent functionality. In this case, it's the
136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // responsibility of the caller to never invoke such function on the
137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // macro assembler.
138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  MacroAssembler(Isolate* isolate, void* buffer, int size);
1393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Arguments macros.
14144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define COND_TYPED_ARGS Condition cond, Register r1, const Operand& r2
14244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define COND_ARGS cond, r1, r2
14344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Cases when relocation is not needed.
14544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define DECLARE_NORELOC_PROTOTYPE(Name, target_type) \
14644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Name(target_type target, BranchDelaySlot bd = PROTECT); \
14744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  inline void Name(BranchDelaySlot bd, target_type target) { \
14844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Name(target, bd); \
14944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } \
15044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Name(target_type target, \
15144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            COND_TYPED_ARGS, \
15244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            BranchDelaySlot bd = PROTECT); \
15344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  inline void Name(BranchDelaySlot bd, \
15444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                   target_type target, \
15544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                   COND_TYPED_ARGS) { \
15644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Name(target, COND_ARGS, bd); \
15744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
15844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
15944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define DECLARE_BRANCH_PROTOTYPES(Name) \
16044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  DECLARE_NORELOC_PROTOTYPE(Name, Label*) \
16144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  DECLARE_NORELOC_PROTOTYPE(Name, int16_t)
16244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  DECLARE_BRANCH_PROTOTYPES(Branch)
1643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  DECLARE_BRANCH_PROTOTYPES(BranchAndLink)
16544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#undef DECLARE_BRANCH_PROTOTYPES
16744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#undef COND_TYPED_ARGS
16844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#undef COND_ARGS
1693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Jump, Call, and Ret pseudo instructions implementing inter-working.
1723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define COND_ARGS Condition cond = al, Register rs = zero_reg, \
1733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
1743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Jump(Register target, COND_ARGS);
1763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Jump(intptr_t target, RelocInfo::Mode rmode, COND_ARGS);
1773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Jump(Address target, RelocInfo::Mode rmode, COND_ARGS);
1783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Jump(Handle<Code> code, RelocInfo::Mode rmode, COND_ARGS);
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static int CallSize(Register target, COND_ARGS);
1803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Call(Register target, COND_ARGS);
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static int CallSize(Address target, RelocInfo::Mode rmode, COND_ARGS);
1823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Call(Address target, RelocInfo::Mode rmode, COND_ARGS);
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static int CallSize(Handle<Code> code,
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      unsigned ast_id = kNoASTId,
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      COND_ARGS);
1873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Call(Handle<Code> code,
1883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
1893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            unsigned ast_id = kNoASTId,
1903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            COND_ARGS);
1913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Ret(COND_ARGS);
1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline void Ret(BranchDelaySlot bd, Condition cond = al,
1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register rs = zero_reg, const Operand& rt = Operand(zero_reg)) {
1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Ret(cond, rs, rt, bd);
1953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Branch(Label* L,
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              Condition cond,
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              Register rs,
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              Heap::RootListIndex index,
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              BranchDelaySlot bdslot = PROTECT);
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#undef COND_ARGS
204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Emit code to discard a non-negative number of pointer-sized elements
2063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // from the stack, clobbering only the sp register.
20744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Drop(int count,
20844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            Condition cond = cc_always,
20944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            Register reg = no_reg,
21044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            const Operand& op = Operand(no_reg));
21144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Trivial case of DropAndRet that utilizes the delay slot and only emits
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // 2 instructions.
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void DropAndRet(int drop);
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void DropAndRet(int drop,
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Condition cond,
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Register reg,
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  const Operand& op);
22044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
22144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Swap two registers.  If the scratch register is omitted then a slightly
22244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // less efficient form using xor instead of mov is emitted.
22344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Swap(Register reg1, Register reg2, Register scratch = no_reg);
2243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void Call(Label* target);
22644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  inline void Move(Register dst, Register src) {
228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!dst.is(src)) {
229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      mov(dst, src);
230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  inline void Move(FPURegister dst, FPURegister src) {
234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!dst.is(src)) {
235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      mov_d(dst, src);
236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  inline void Move(Register dst_low, Register dst_high, FPURegister src) {
240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    mfc1(dst_low, src);
241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    mfc1(dst_high, FPURegister::from_code(src.code() + 1));
242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  inline void Move(FPURegister dst, Register src_low, Register src_high) {
245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    mtc1(src_low, dst);
246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    mtc1(src_high, FPURegister::from_code(dst.code() + 1));
247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Conditional move.
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Move(FPURegister dst, double imm);
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Movz(Register rd, Register rs, Register rt);
2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Movn(Register rd, Register rs, Register rt);
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Movt(Register rd, Register rs, uint16_t cc = 0);
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Movf(Register rd, Register rs, uint16_t cc = 0);
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Clz(Register rd, Register rs);
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Jump unconditionally to given label.
2593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // We NEED a nop in the branch delay slot, as it used by v8, for example in
2603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // CodeGenerator::ProcessDeferred().
2616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Currently the branch delay slot is filled by the MacroAssembler.
2623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Use rather b(Label) for code generation.
2633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void jmp(Label* L) {
26444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Branch(L);
2653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
2663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Load an object from the root table.
2683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void LoadRoot(Register destination,
2693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                Heap::RootListIndex index);
2703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void LoadRoot(Register destination,
2713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                Heap::RootListIndex index,
2723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                Condition cond, Register src1, const Operand& src2);
2733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
27444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Store an object to the root table.
27544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void StoreRoot(Register source,
27644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                 Heap::RootListIndex index);
27744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void StoreRoot(Register source,
27844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                 Heap::RootListIndex index,
27944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                 Condition cond, Register src1, const Operand& src2);
28044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void LoadHeapObject(Register dst, Handle<HeapObject> object);
28244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void LoadObject(Register result, Handle<Object> object) {
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (object->IsHeapObject()) {
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      LoadHeapObject(result, Handle<HeapObject>::cast(object));
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      li(result, object);
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
290592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ---------------------------------------------------------------------------
2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // GC Support
2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void IncrementalMarkingRecordWriteHelper(Register object,
2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           Register value,
2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           Register address);
2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  enum RememberedSetFinalAction {
2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    kReturnAtEnd,
3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    kFallThroughAtEnd
3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
302592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
303592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Record in the remembered set the fact that we have a pointer to new space
3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // at the address pointed to by the addr register.  Only works if addr is not
3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // in new space.
3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void RememberedSetHelper(Register object,  // Used for debug code.
3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Register addr,
3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Register scratch,
3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           SaveFPRegsMode save_fp,
3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           RememberedSetFinalAction and_then);
3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CheckPageFlag(Register object,
3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     Register scratch,
3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     int mask,
3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     Condition cc,
3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     Label* condition_met);
3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if object is in new space.  Jumps if the object is not in new space.
3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The register scratch can be object itself, but it will be clobbered.
3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void JumpIfNotInNewSpace(Register object,
3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Register scratch,
3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Label* branch) {
3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    InNewSpace(object, scratch, ne, branch);
3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if object is in new space.  Jumps if the object is in new space.
3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The register scratch can be object itself, but scratch will be clobbered.
3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void JumpIfInNewSpace(Register object,
3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register scratch,
3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Label* branch) {
3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    InNewSpace(object, scratch, eq, branch);
3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if an object has a given incremental marking color.
3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void HasColor(Register object,
3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Register scratch0,
3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Register scratch1,
3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Label* has_color,
3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                int first_bit,
3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                int second_bit);
3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void JumpIfBlack(Register object,
34444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                   Register scratch0,
3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   Register scratch1,
3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   Label* on_black);
3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Checks the color of an object.  If the object is already grey or black
3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // then we just fall through, since it is already live.  If it is white and
3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // we can determine that it doesn't need to be scanned, then we just mark it
3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // black and fall through.  For the rest we jump to the label so the
3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // incremental marker can fix its assumptions.
3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void EnsureNotWhite(Register object,
3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Register scratch1,
3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Register scratch2,
3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Register scratch3,
3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Label* object_is_white_and_not_data);
3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Detects conservatively whether an object is data-only, i.e. it does need to
3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // be scanned by the garbage collector.
3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void JumpIfDataObject(Register value,
3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register scratch,
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Label* not_data_object);
3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Notify the garbage collector that we wrote a pointer into an object.
3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // |object| is the object being stored into, |value| is the object being
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // stored.  value and scratch registers are clobbered by the operation.
3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The offset is the offset from the start of the object, not the offset from
3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the tagged HeapObject pointer.  For use with FieldOperand(reg, off).
3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void RecordWriteField(
3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register object,
3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int offset,
3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register value,
3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register scratch,
3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RAStatus ra_status,
3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SaveFPRegsMode save_fp,
3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SmiCheck smi_check = INLINE_SMI_CHECK);
3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // As above, but the offset has the tag presubtracted.  For use with
3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // MemOperand(reg, off).
3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline void RecordWriteContextSlot(
3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register context,
3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int offset,
3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register value,
3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register scratch,
3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RAStatus ra_status,
3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SaveFPRegsMode save_fp,
3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SmiCheck smi_check = INLINE_SMI_CHECK) {
3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RecordWriteField(context,
3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     offset + kHeapObjectTag,
3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     value,
3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     scratch,
3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     ra_status,
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     save_fp,
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     remembered_set_action,
3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     smi_check);
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
400592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // For a given |object| notify the garbage collector that the slot |address|
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // has been written.  |value| is the object being stored. The value and
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // address registers are clobbered by the operation.
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void RecordWrite(
4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register object,
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register address,
4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register value,
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RAStatus ra_status,
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SaveFPRegsMode save_fp,
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SmiCheck smi_check = INLINE_SMI_CHECK);
41244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
41344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
41444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // ---------------------------------------------------------------------------
415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Inline caching support.
41644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
41744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Generate code for checking access rights - used for security checks
41844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // on access to global objects across environments. The holder register
41944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // is left untouched, whereas both scratch registers are clobbered.
42044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void CheckAccessGlobalProxy(Register holder_reg,
42144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Register scratch,
42244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Label* miss);
42344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
424c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  void GetNumberHash(Register reg0, Register scratch);
4253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void LoadFromNumberDictionary(Label* miss,
4273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                Register elements,
4283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                Register key,
4293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                Register result,
4303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                Register reg0,
4313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                Register reg1,
4323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                Register reg2);
4333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
43544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  inline void MarkCode(NopMarkerTypes type) {
43644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    nop(type);
43744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
43844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
43944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check if the given instruction is a 'type' marker.
4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // i.e. check if it is a sll zero_reg, zero_reg, <type> (referenced as
44144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // nop(type)). These instructions are generated to mark special location in
44244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // the code, like some special IC code.
44344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static inline bool IsMarkedCode(Instr instr, int type) {
44444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER));
44544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return IsNop(instr, type);
44644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
44744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
44844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
44944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static inline int GetCodeMarker(Instr instr) {
45044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    uint32_t opcode = ((instr & kOpcodeMask));
45144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    uint32_t rt = ((instr & kRtFieldMask) >> kRtShift);
45244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    uint32_t rs = ((instr & kRsFieldMask) >> kRsShift);
45344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    uint32_t sa = ((instr & kSaFieldMask) >> kSaShift);
45444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
45544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Return <n> if we have a sll zero_reg, zero_reg, n
45644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // else return -1.
45744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    bool sllzz = (opcode == SLL &&
45844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                  rt == static_cast<uint32_t>(ToNumber(zero_reg)) &&
45944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                  rs == static_cast<uint32_t>(ToNumber(zero_reg)));
46044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int type =
46144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        (sllzz && FIRST_IC_MARKER <= sa && sa < LAST_CODE_MARKER) ? sa : -1;
46244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT((type == -1) ||
46344f0eee88ff00398ff7f715fab053374d808c90dSteve Block           ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)));
46444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return type;
4656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // ---------------------------------------------------------------------------
470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Allocation support.
47144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
47244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Allocate an object in new space. The object_size is specified
47344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // either in bytes or in words if the allocation flag SIZE_IN_WORDS
47444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // is passed. If the new space is exhausted control continues at the
47544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // gc_required label. The allocated object is returned in result. If
47644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // the flag tag_allocated_object is true the result is tagged as as
47744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // a heap object. All registers are clobbered also when control
47844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // continues at the gc_required label.
47944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void AllocateInNewSpace(int object_size,
48044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Register result,
48144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Register scratch1,
48244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Register scratch2,
48344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Label* gc_required,
48444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          AllocationFlags flags);
48544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void AllocateInNewSpace(Register object_size,
48644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Register result,
48744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Register scratch1,
48844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Register scratch2,
48944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Label* gc_required,
49044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          AllocationFlags flags);
49144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
49244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Undo allocation in new space. The object passed and objects allocated after
49344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // it will no longer be allocated. The caller must make sure that no pointers
49444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // are left to the object(s) no longer allocated as they would be invalid when
49544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // allocation is undone.
49644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void UndoAllocationInNewSpace(Register object, Register scratch);
49744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
49844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
49944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void AllocateTwoByteString(Register result,
50044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                             Register length,
50144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                             Register scratch1,
50244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                             Register scratch2,
50344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                             Register scratch3,
50444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                             Label* gc_required);
50544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void AllocateAsciiString(Register result,
50644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           Register length,
50744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           Register scratch1,
50844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           Register scratch2,
50944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           Register scratch3,
51044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           Label* gc_required);
51144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void AllocateTwoByteConsString(Register result,
51244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 Register length,
51344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 Register scratch1,
51444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 Register scratch2,
51544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 Label* gc_required);
51644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void AllocateAsciiConsString(Register result,
51744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Register length,
51844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Register scratch1,
51944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Register scratch2,
52044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Label* gc_required);
521589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void AllocateTwoByteSlicedString(Register result,
522589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                   Register length,
523589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                   Register scratch1,
524589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                   Register scratch2,
525589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                   Label* gc_required);
526589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void AllocateAsciiSlicedString(Register result,
527589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                 Register length,
528589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                 Register scratch1,
529589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                 Register scratch2,
530589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                 Label* gc_required);
53144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
53244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Allocates a heap number or jumps to the gc_required label if the young
53344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // space is full and a scavenge is needed. All registers are clobbered also
53444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // when control continues at the gc_required label.
53544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void AllocateHeapNumber(Register result,
53644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Register scratch1,
53744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Register scratch2,
53844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Register heap_number_map,
53944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Label* gc_required);
54044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void AllocateHeapNumberWithValue(Register result,
54144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   FPURegister value,
54244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   Register scratch1,
54344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   Register scratch2,
54444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   Label* gc_required);
54544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
54644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // ---------------------------------------------------------------------------
547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Instruction macros.
5483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
54944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define DEFINE_INSTRUCTION(instr)                                              \
5503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void instr(Register rd, Register rs, const Operand& rt);                     \
5513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void instr(Register rd, Register rs, Register rt) {                          \
5523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    instr(rd, rs, Operand(rt));                                                \
5533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }                                                                            \
5543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void instr(Register rs, Register rt, int32_t j) {                            \
5553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    instr(rs, rt, Operand(j));                                                 \
5563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
5573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
55844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define DEFINE_INSTRUCTION2(instr)                                             \
5593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void instr(Register rs, const Operand& rt);                                  \
5603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void instr(Register rs, Register rt) {                                       \
5613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    instr(rs, Operand(rt));                                                    \
5623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }                                                                            \
5633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void instr(Register rs, int32_t j) {                                         \
5643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    instr(rs, Operand(j));                                                     \
5653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
5663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  DEFINE_INSTRUCTION(Addu);
56844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  DEFINE_INSTRUCTION(Subu);
5693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  DEFINE_INSTRUCTION(Mul);
5703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  DEFINE_INSTRUCTION2(Mult);
5713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  DEFINE_INSTRUCTION2(Multu);
5723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  DEFINE_INSTRUCTION2(Div);
5733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  DEFINE_INSTRUCTION2(Divu);
5743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  DEFINE_INSTRUCTION(And);
5763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  DEFINE_INSTRUCTION(Or);
5773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  DEFINE_INSTRUCTION(Xor);
5783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  DEFINE_INSTRUCTION(Nor);
579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DEFINE_INSTRUCTION2(Neg);
5803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  DEFINE_INSTRUCTION(Slt);
5823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  DEFINE_INSTRUCTION(Sltu);
5833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
58444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // MIPS32 R2 instruction macro.
58544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  DEFINE_INSTRUCTION(Ror);
58644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#undef DEFINE_INSTRUCTION
5883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#undef DEFINE_INSTRUCTION2
5893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ---------------------------------------------------------------------------
592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Pseudo-instructions.
5933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void mov(Register rd, Register rt) { or_(rd, rt, zero_reg); }
5953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load int32 in the rd register.
5973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void li(Register rd, Operand j, LiFlags mode = OPTIMIZE_SIZE);
5983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline void li(Register rd, int32_t j, LiFlags mode = OPTIMIZE_SIZE) {
5993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    li(rd, Operand(j), mode);
6003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
6013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline void li(Register dst, Handle<Object> value,
6023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 LiFlags mode = OPTIMIZE_SIZE) {
6033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    li(dst, Operand(value), mode);
60444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
6053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Push multiple registers on the stack.
6076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Registers are saved in numerical order, with higher numbered registers
608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // saved in higher memory addresses.
6093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void MultiPush(RegList regs);
6103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void MultiPushReversed(RegList regs);
61144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
612589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void MultiPushFPU(RegList regs);
613589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void MultiPushReversedFPU(RegList regs);
614589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Lower case push() for compatibility with arch-independent code.
616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void push(Register src) {
6173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    Addu(sp, sp, Operand(-kPointerSize));
6183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    sw(src, MemOperand(sp, 0));
6193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
62044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Push a handle.
6223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Push(Handle<Object> handle);
6233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Push two registers. Pushes leftmost register first (to highest address).
625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void Push(Register src1, Register src2) {
62644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Subu(sp, sp, Operand(2 * kPointerSize));
62744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(src1, MemOperand(sp, 1 * kPointerSize));
62844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(src2, MemOperand(sp, 0 * kPointerSize));
62944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
63044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Push three registers. Pushes leftmost register first (to highest address).
632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void Push(Register src1, Register src2, Register src3) {
633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Subu(sp, sp, Operand(3 * kPointerSize));
63444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(src1, MemOperand(sp, 2 * kPointerSize));
63544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(src2, MemOperand(sp, 1 * kPointerSize));
63644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(src3, MemOperand(sp, 0 * kPointerSize));
63744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
63844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Push four registers. Pushes leftmost register first (to highest address).
640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void Push(Register src1, Register src2, Register src3, Register src4) {
641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Subu(sp, sp, Operand(4 * kPointerSize));
64244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(src1, MemOperand(sp, 3 * kPointerSize));
64344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(src2, MemOperand(sp, 2 * kPointerSize));
64444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(src3, MemOperand(sp, 1 * kPointerSize));
64544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sw(src4, MemOperand(sp, 0 * kPointerSize));
64644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
64744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void Push(Register src, Condition cond, Register tst1, Register tst2) {
649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Since we don't have conditional execution we use a Branch.
65044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Branch(3, cond, tst1, Operand(tst2));
651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Subu(sp, sp, Operand(kPointerSize));
6523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    sw(src, MemOperand(sp, 0));
6533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
6543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Pops multiple values from the stack and load them in the
6563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // registers specified in regs. Pop order is the opposite as in MultiPush.
6573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void MultiPop(RegList regs);
6583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void MultiPopReversed(RegList regs);
659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
660589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void MultiPopFPU(RegList regs);
661589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void MultiPopReversedFPU(RegList regs);
662589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Lower case pop() for compatibility with arch-independent code.
664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void pop(Register dst) {
6653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    lw(dst, MemOperand(sp, 0));
6663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    Addu(sp, sp, Operand(kPointerSize));
6673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Pop two registers. Pops rightmost register first (from lower address).
670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void Pop(Register src1, Register src2) {
671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(!src1.is(src2));
672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    lw(src2, MemOperand(sp, 0 * kPointerSize));
673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    lw(src1, MemOperand(sp, 1 * kPointerSize));
674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Addu(sp, sp, 2 * kPointerSize);
675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Pop three registers. Pops rightmost register first (from lower address).
6783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Pop(Register src1, Register src2, Register src3) {
6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    lw(src3, MemOperand(sp, 0 * kPointerSize));
6803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    lw(src2, MemOperand(sp, 1 * kPointerSize));
6813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    lw(src1, MemOperand(sp, 2 * kPointerSize));
6823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Addu(sp, sp, 3 * kPointerSize);
6833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
68544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Pop(uint32_t count = 1) {
68644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Addu(sp, sp, Operand(count * kPointerSize));
68744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
68844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
68944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Push and pop the registers that can hold pointers, as defined by the
69044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // RegList constant kSafepointSavedRegisters.
691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void PushSafepointRegisters();
692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void PopSafepointRegisters();
693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void PushSafepointRegistersAndDoubles();
694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void PopSafepointRegistersAndDoubles();
695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Store value in register src in the safepoint stack slot for
696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // register dst.
697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void StoreToSafepointRegisterSlot(Register src, Register dst);
698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void StoreToSafepointRegistersAndDoublesSlot(Register src, Register dst);
699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the value of the src register from its safepoint stack slot
700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // into register dst.
701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void LoadFromSafepointRegisterSlot(Register dst, Register src);
70244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Flush the I-cache from asm code. You should use CPU::FlushICache from C.
7043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Does not handle errors.
7053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void FlushICache(Register address, unsigned instructions);
7063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
70744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // MIPS32 R2 instruction macro.
70844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Ins(Register rt, Register rs, uint16_t pos, uint16_t size);
70944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Ext(Register rt, Register rs, uint16_t pos, uint16_t size);
71044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ---------------------------------------------------------------------------
7123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // FPU macros. These do not handle special cases like NaN or +- inf.
7133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
71444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Convert unsigned word to double.
71569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  void Cvt_d_uw(FPURegister fd, FPURegister fs, FPURegister scratch);
71669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  void Cvt_d_uw(FPURegister fd, Register rs, FPURegister scratch);
71744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
71844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Convert double to unsigned word.
71969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  void Trunc_uw_d(FPURegister fd, FPURegister fs, FPURegister scratch);
72069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  void Trunc_uw_d(FPURegister fd, Register rs, FPURegister scratch);
72144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Trunc_w_d(FPURegister fd, FPURegister fs);
7233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Round_w_d(FPURegister fd, FPURegister fs);
7243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Floor_w_d(FPURegister fd, FPURegister fs);
7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Ceil_w_d(FPURegister fd, FPURegister fs);
7263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Wrapper function for the different cmp/branch types.
7273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void BranchF(Label* target,
7283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Label* nan,
7293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Condition cc,
7303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               FPURegister cmp1,
7313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               FPURegister cmp2,
7323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               BranchDelaySlot bd = PROTECT);
7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Alternate (inline) version for better readability with USE_DELAY_SLOT.
7353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline void BranchF(BranchDelaySlot bd,
7363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Label* target,
7373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Label* nan,
7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Condition cc,
7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      FPURegister cmp1,
7403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      FPURegister cmp2) {
7413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    BranchF(target, nan, cc, cmp1, cmp2, bd);
7423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
74444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Convert the HeapNumber pointed to by source to a 32bits signed integer
74544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // dest. If the HeapNumber does not fit into a 32bits signed integer branch
74644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // to not_int32 label. If FPU is available double_scratch is used but not
74744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // scratch2.
74844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void ConvertToInt32(Register source,
74944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      Register dest,
75044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      Register scratch,
75144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      Register scratch2,
75244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      FPURegister double_scratch,
75344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      Label *not_int32);
75444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Truncates a double using a specific rounding mode.
7563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The except_flag will contain any exceptions caused by the instruction.
7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If check_inexact is kDontCheckForInexactConversion, then the inexacat
7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // exception is masked.
7593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void EmitFPUTruncate(FPURoundingMode rounding_mode,
7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       FPURegister result,
7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       DoubleRegister double_input,
7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       Register scratch1,
7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       Register except_flag,
7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       CheckForInexactConversion check_inexact
7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           = kDontCheckForInexactConversion);
7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Helper for EmitECMATruncate.
768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This will truncate a floating-point value outside of the singed 32bit
769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // integer range to a 32bit signed integer.
770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Expects the double value loaded in input_high and input_low.
771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Exits with the answer in 'result'.
772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Note that this code does not work for values in the 32bit range!
773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void EmitOutOfInt32RangeTruncate(Register result,
774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   Register input_high,
775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   Register input_low,
776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   Register scratch);
777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Performs a truncating conversion of a floating point number as used by
7793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // the JS bitwise operations. See ECMA-262 9.5: ToInt32.
7803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Exits with 'result' holding the answer and all other registers clobbered.
7813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void EmitECMATruncate(Register result,
7823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                        FPURegister double_input,
7833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                        FPURegister single_scratch,
7843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                        Register scratch,
7853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                        Register scratch2,
7863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                        Register scratch3);
7873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
78844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Enter exit frame.
789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // argc - argument count to be dropped by LeaveExitFrame.
790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // save_doubles - saves FPU registers on stack, currently disabled.
791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // stack_space - extra stack space.
792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void EnterExitFrame(bool save_doubles,
793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      int stack_space = 0);
7946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Leave the current exit frame.
7963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void LeaveExitFrame(bool save_doubles,
7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Register arg_count,
7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      bool do_return = false);
7996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
80044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get the actual activation frame alignment for target environment.
80144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static int ActivationFrameAlignment();
8026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Make sure the stack is aligned. Only emits code in debug mode.
804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void AssertStackIsAligned();
805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
80644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void LoadContext(Register dst, int context_chain_length);
8076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Conditionally load the cached Array transitioned map of type
8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // transitioned_kind from the global context if the map in register
8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // map_in_out is the cached Array map in the global context of
8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // expected_kind.
8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void LoadTransitionedArrayMapConditional(
8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ElementsKind expected_kind,
8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ElementsKind transitioned_kind,
8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register map_in_out,
8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register scratch,
8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label* no_map_match);
8183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the initial map for new Arrays from a JSFunction.
8203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void LoadInitialArrayMap(Register function_in,
8213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Register scratch,
8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Register map_out);
8233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
82444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void LoadGlobalFunction(int index, Register function);
82544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
82644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Load the initial map from the global function. The registers
82744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // function and map can be the same, function is then overwritten.
82844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void LoadGlobalFunctionInitialMap(Register function,
82944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    Register map,
83044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    Register scratch);
83144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void InitializeRootRegister() {
8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExternalReference roots_array_start =
8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ExternalReference::roots_array_start(isolate());
8353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    li(kRootRegister, Operand(roots_array_start));
8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
8373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
83844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // -------------------------------------------------------------------------
839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // JavaScript invokes.
840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
8413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up call kind marking in t1. The method takes t1 as an
842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // explicit first parameter to make the code more readable at the
843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // call sites.
844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void SetCallKind(Register dst, CallKind kind);
8456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Invoke the JavaScript function code by either calling or jumping.
8476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void InvokeCode(Register code,
8486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                  const ParameterCount& expected,
8496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                  const ParameterCount& actual,
85044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                  InvokeFlag flag,
8513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                  const CallWrapper& call_wrapper,
8523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                  CallKind call_kind);
8536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void InvokeCode(Handle<Code> code,
8556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                  const ParameterCount& expected,
8566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                  const ParameterCount& actual,
8576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                  RelocInfo::Mode rmode,
858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  InvokeFlag flag,
8593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                  CallKind call_kind);
8606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Invoke the JavaScript function in the given register. Changes the
8626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // current context to the context in the function before invoking.
8636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void InvokeFunction(Register function,
8646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      const ParameterCount& actual,
86544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      InvokeFlag flag,
8663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      const CallWrapper& call_wrapper,
8673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      CallKind call_kind);
86844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void InvokeFunction(Handle<JSFunction> function,
87044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      const ParameterCount& actual,
8713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      InvokeFlag flag,
8723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      const CallWrapper& call_wrapper,
8733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      CallKind call_kind);
8746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
87644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void IsObjectJSObjectType(Register heap_object,
87744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            Register map,
87844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            Register scratch,
87944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            Label* fail);
88044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
88144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void IsInstanceJSObjectType(Register map,
88244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Register scratch,
88344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Label* fail);
88444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
88544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void IsObjectJSStringType(Register object,
88644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            Register scratch,
88744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            Label* fail);
88844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
8896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT
89044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // -------------------------------------------------------------------------
891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Debugger Support.
8926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void DebugBreak();
8946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
8956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
89744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // -------------------------------------------------------------------------
898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Exception handling.
8993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Push a new try handler and link into try handler chain.
9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void PushTryHandler(StackHandler::Kind kind, int handler_index);
9023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Unlink the stack handler on top of the stack from the try handler chain.
9043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Must preserve the result register.
9053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void PopTryHandler();
9063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Passes thrown value to the handler of top of the try handler chain.
908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void Throw(Register value);
909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Propagates an uncatchable exception to the top of the current JS stack's
911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // handler chain.
9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void ThrowUncatchable(Register value);
913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
91444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Copies a fixed number of fields of heap objects from src to dst.
91544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void CopyFields(Register dst, Register src, RegList temps, int field_count);
9163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Copies a number of bytes from src to dst. All registers are clobbered. On
918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // exit src and dst will point to the place just after where the last byte was
919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // read or written and length will be zero.
920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void CopyBytes(Register src,
921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 Register dst,
922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 Register length,
923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 Register scratch);
924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Initialize fields with filler values.  Fields starting at |start_offset|
9263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // not including end_offset are overwritten with the value in |filler|.  At
9273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the end the loop, |start_offset| takes the value of |end_offset|.
9283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void InitializeFieldsWithFiller(Register start_offset,
9293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  Register end_offset,
9303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  Register filler);
9313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
93244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // -------------------------------------------------------------------------
9333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Support functions.
9343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
93544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Try to get function prototype of a function and puts the value in
93644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // the result register. Checks that the function really is a
93744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // function and jumps to the miss label if the fast checks fail. The
93844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // function register will be untouched; the other registers may be
93944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // clobbered.
94044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void TryGetFunctionPrototype(Register function,
94144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Register result,
94244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               Register scratch,
9433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Label* miss,
9443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               bool miss_on_bound_function = false);
94544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
9466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void GetObjectType(Register function,
9476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     Register map,
9486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     Register type_reg);
9496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check if a map for a JSObject indicates that the object has fast elements.
9513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Jump to the specified label if it does not.
9523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void CheckFastElements(Register map,
9533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                         Register scratch,
9543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                         Label* fail);
9553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
9563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if a map for a JSObject indicates that the object can have both smi
9573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // and HeapObject elements.  Jump to the specified label if it does not.
9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CheckFastObjectElements(Register map,
9593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Register scratch,
9603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Label* fail);
9613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if a map for a JSObject indicates that the object has fast smi only
9633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // elements.  Jump to the specified label if it does not.
9643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CheckFastSmiOnlyElements(Register map,
9653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Register scratch,
9663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Label* fail);
9673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check to see if maybe_number can be stored as a double in
9693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // FastDoubleElements. If it can, store it at the index specified by key in
9703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the FastDoubleElements array elements. Otherwise jump to fail, in which
9713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // case scratch2, scratch3 and scratch4 are unmodified.
9723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void StoreNumberToDoubleElements(Register value_reg,
9733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Register key_reg,
9743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Register receiver_reg,
9753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Register elements_reg,
9763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Register scratch1,
9773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Register scratch2,
9783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Register scratch3,
9793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Register scratch4,
9803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Label* fail);
9813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Compare an object's map with the specified map and its transitioned
9833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Jumps to
9843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // "branch_to" if the result of the comparison is "cond". If multiple map
9853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // compares are required, the compare sequences branches to early_success.
9863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CompareMapAndBranch(Register obj,
9873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Register scratch,
9883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Handle<Map> map,
9893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Label* early_success,
9903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Condition cond,
9913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Label* branch_to,
9923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           CompareMapMode mode = REQUIRE_EXACT_MAP);
9933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if the map of an object is equal to a specified map and branch to
9953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // label if not. Skip the smi check if not required (object is known to be a
9963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
9973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // against maps that are ElementsKind transition maps of the specificed map.
99844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void CheckMap(Register obj,
99944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                Register scratch,
100044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                Handle<Map> map,
100144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                Label* fail,
10023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                SmiCheckType smi_check_type,
10033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                CompareMapMode mode = REQUIRE_EXACT_MAP);
10043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
100544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
100644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void CheckMap(Register obj,
100744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                Register scratch,
100844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                Heap::RootListIndex index,
100944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                Label* fail,
1010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                SmiCheckType smi_check_type);
1011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check if the map of an object is equal to a specified map and branch to a
1013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // specified target if equal. Skip the smi check if not required (object is
1014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // known to be a heap object)
1015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void DispatchMap(Register obj,
1016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                   Register scratch,
1017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                   Handle<Map> map,
1018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                   Handle<Code> success,
1019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                   SmiCheckType smi_check_type);
10206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Generates code for reporting that an illegal operation has
10226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // occurred.
10236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void IllegalOperation(int num_arguments);
10246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load and check the instance type of an object for being a string.
10273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Loads the type into the second argument register.
10283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Returns a condition that will be enabled if the object was a string.
10293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Condition IsObjectStringType(Register obj,
10303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Register type,
10313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Register result) {
10323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    lw(type, FieldMemOperand(obj, HeapObject::kMapOffset));
10333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    lbu(type, FieldMemOperand(type, Map::kInstanceTypeOffset));
10343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    And(type, type, Operand(kIsNotStringMask));
10353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT_EQ(0, kStringTag);
10363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return eq;
10373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
10383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
104044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Picks out an array index from the hash field.
104144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Register use:
104244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   hash - holds the index's hash. Clobbered.
104344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   index - holds the overwritten index on exit.
104444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void IndexFromHash(Register hash, Register index);
104544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the number of least significant bits from a register.
1047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits);
1048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits);
1049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
105044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Load the value of a number object into a FPU double register. If the
105144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // object is not a number a jump to the label not_number is performed
105244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // and the FPU double register is unchanged.
105344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void ObjectToDoubleFPURegister(
105444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Register object,
105544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      FPURegister value,
105644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Register scratch1,
105744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Register scratch2,
105844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Register heap_number_map,
105944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Label* not_number,
106044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ObjectToDoubleFlags flags = NO_OBJECT_TO_DOUBLE_FLAGS);
106144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
106244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Load the value of a smi object into a FPU double register. The register
106344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // scratch1 can be the same register as smi in which case smi will hold the
106444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // untagged value afterwards.
106544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void SmiToDoubleFPURegister(Register smi,
106644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              FPURegister value,
106744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Register scratch1);
106844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
106944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // -------------------------------------------------------------------------
1070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Overflow handling functions.
1071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Usage: first call the appropriate arithmetic function, then call one of the
1072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // jump functions with the overflow_dst register as the second parameter.
1073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void AdduAndCheckForOverflow(Register dst,
1075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Register left,
1076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Register right,
1077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Register overflow_dst,
1078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Register scratch = at);
1079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void SubuAndCheckForOverflow(Register dst,
1081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Register left,
1082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Register right,
1083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Register overflow_dst,
1084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               Register scratch = at);
1085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void BranchOnOverflow(Label* label,
1087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        Register overflow_check,
1088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        BranchDelaySlot bd = PROTECT) {
1089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Branch(label, lt, overflow_check, Operand(zero_reg), bd);
1090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void BranchOnNoOverflow(Label* label,
1093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          Register overflow_check,
1094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          BranchDelaySlot bd = PROTECT) {
1095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Branch(label, ge, overflow_check, Operand(zero_reg), bd);
1096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void RetOnOverflow(Register overflow_check, BranchDelaySlot bd = PROTECT) {
1099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Ret(lt, overflow_check, Operand(zero_reg), bd);
1100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void RetOnNoOverflow(Register overflow_check, BranchDelaySlot bd = PROTECT) {
1103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Ret(ge, overflow_check, Operand(zero_reg), bd);
1104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -------------------------------------------------------------------------
1107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Runtime calls.
11083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // See comments at the beginning of CEntryStub::Generate.
11103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline void PrepareCEntryArgs(int num_args) {
11113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    li(s0, num_args);
11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    li(s1, (num_args - 1) * kPointerSize);
11133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
11143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline void PrepareCEntryFunction(const ExternalReference& ref) {
11163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    li(s2, Operand(ref));
11173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
11183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Call a code stub.
11203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CallStub(CodeStub* stub,
11213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Condition cond = cc_always,
11223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Register r1 = zero_reg,
11233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                const Operand& r2 = Operand(zero_reg),
11243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                BranchDelaySlot bd = PROTECT);
11253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
112644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Tail call a code stub (jump).
112744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void TailCallStub(CodeStub* stub);
112844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
112944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void CallJSExitStub(CodeStub* stub);
11303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Call a runtime routine.
113244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void CallRuntime(const Runtime::Function* f, int num_arguments);
113344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void CallRuntimeSaveDoubles(Runtime::FunctionId id);
11343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Convenience function: Same as above, but takes the fid instead.
11363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void CallRuntime(Runtime::FunctionId fid, int num_arguments);
11373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
113844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Convenience function: call an external reference.
113944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void CallExternalReference(const ExternalReference& ext,
11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             int num_arguments,
11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             BranchDelaySlot bd = PROTECT);
114244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
11433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Tail call of a runtime routine (jump).
11446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Like JumpToExternalReference, but also takes care of passing the number
11453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // of parameters.
11466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void TailCallExternalReference(const ExternalReference& ext,
11476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                 int num_arguments,
11486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                 int result_size);
11496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Convenience function: tail call a runtime routine (jump).
11516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void TailCallRuntime(Runtime::FunctionId fid,
11523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                       int num_arguments,
11533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                       int result_size);
11543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int CalculateStackPassedWords(int num_reg_arguments,
11563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                int num_double_arguments);
11573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
115844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Before calling a C-function from generated code, align arguments on stack
115944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // and add space for the four mips argument slots.
116044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // After aligning the frame, non-register arguments must be stored on the
116144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // stack, after the argument-slots using helper: CFunctionArgumentOperand().
116244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // The argument count assumes all arguments are word sized.
116344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Some compilers/platforms require the stack to be aligned when calling
116444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // C++ code.
116544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Needs a scratch register to do some arithmetic. This register will be
116644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // trashed.
11673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void PrepareCallCFunction(int num_reg_arguments,
11683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            int num_double_registers,
11693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            Register scratch);
11703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void PrepareCallCFunction(int num_reg_arguments,
11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            Register scratch);
117244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
117344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Arguments 1-4 are placed in registers a0 thru a3 respectively.
117444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Arguments 5..n are stored to stack using following:
117544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //  sw(t0, CFunctionArgumentOperand(5));
117644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
117744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Calls a C function and cleans up the space for arguments allocated
117844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // by PrepareCallCFunction. The called function is not allowed to trigger a
117944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // garbage collection, since that might move the code and invalidate the
118044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // return address (unless this is somehow accounted for by the called
118144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // function).
118244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void CallCFunction(ExternalReference function, int num_arguments);
11833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CallCFunction(Register function, int num_arguments);
11843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CallCFunction(ExternalReference function,
11853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     int num_reg_arguments,
11863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     int num_double_arguments);
11873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CallCFunction(Register function,
11883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     int num_reg_arguments,
11893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     int num_double_arguments);
1190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void GetCFunctionDoubleResult(const DoubleRegister dst);
1191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // There are two ways of passing double arguments on MIPS, depending on
1193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // whether soft or hard floating point ABI is used. These functions
1194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // abstract parameter passing for the three different ways we call
1195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // C functions from generated code.
1196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void SetCallCDoubleArguments(DoubleRegister dreg);
1197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void SetCallCDoubleArguments(DoubleRegister dreg1, DoubleRegister dreg2);
1198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void SetCallCDoubleArguments(DoubleRegister dreg, Register reg);
1199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
12003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Calls an API function.  Allocates HandleScope, extracts returned value
12013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // from handle and propagates exceptions.  Restores context.  stack_space
12023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // - space to be unwound on exit (includes the call JS arguments space and
12033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the additional space allocated for the fast call).
12043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CallApiFunctionAndReturn(ExternalReference function, int stack_space);
120544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
12063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Jump to the builtin routine.
12073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void JumpToExternalReference(const ExternalReference& builtin,
12083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               BranchDelaySlot bd = PROTECT);
12093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Invoke specified builtin JavaScript function. Adds an entry to
12113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // the unresolved list if the name does not resolve.
121244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void InvokeBuiltin(Builtins::JavaScript id,
1213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     InvokeFlag flag,
1214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     const CallWrapper& call_wrapper = NullCallWrapper());
12153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Store the code object for the given builtin in the target register and
121744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // setup the function in a1.
12183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void GetBuiltinEntry(Register target, Builtins::JavaScript id);
12193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
122044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Store the function for the given builtin in the target register.
122144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void GetBuiltinFunction(Register target, Builtins::JavaScript id);
122244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
12233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  struct Unresolved {
12243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    int pc;
1225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    uint32_t flags;  // See Bootstrapper::FixupFlags decoders/encoders.
12263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    const char* name;
12273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  };
12283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Object> CodeObject() {
1230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(!code_object_.is_null());
1231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return code_object_;
1232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
12333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
123444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // -------------------------------------------------------------------------
1235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // StatsCounter support.
12363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void SetCounter(StatsCounter* counter, int value,
12383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                  Register scratch1, Register scratch2);
12393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void IncrementCounter(StatsCounter* counter, int value,
12403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                        Register scratch1, Register scratch2);
12413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void DecrementCounter(StatsCounter* counter, int value,
12423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                        Register scratch1, Register scratch2);
12433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
124544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // -------------------------------------------------------------------------
1246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Debugging.
12473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Calls Abort(msg) if the condition cc is not satisfied.
12493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Use --debug_code to enable.
12503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void Assert(Condition cc, const char* msg, Register rs, Operand rt);
125144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void AssertRegisterIsRoot(Register reg, Heap::RootListIndex index);
125244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void AssertFastElements(Register elements);
12533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Like Assert(), but always enabled.
12553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void Check(Condition cc, const char* msg, Register rs, Operand rt);
12563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Print a message to stdout and abort execution.
12583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void Abort(const char* msg);
12593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Verify restrictions about code generated in stubs.
12613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void set_generating_stub(bool value) { generating_stub_ = value; }
12623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  bool generating_stub() { return generating_stub_; }
12633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
12643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  bool allow_stub_calls() { return allow_stub_calls_; }
12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void set_has_frame(bool value) { has_frame_ = value; }
12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool has_frame() { return has_frame_; }
12673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline bool AllowThisStubCall(CodeStub* stub);
12683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
126944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // ---------------------------------------------------------------------------
1270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Number utilities.
127144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
127244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check whether the value of reg is a power of two and not zero. If not
127344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // control continues at the label not_power_of_two. If reg is a power of two
127444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // the register scratch contains the value of (reg - 1) when control falls
127544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // through.
127644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void JumpIfNotPowerOfTwoOrZero(Register reg,
127744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 Register scratch,
127844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 Label* not_power_of_two_or_zero);
127944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
128044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // -------------------------------------------------------------------------
1281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Smi utilities.
128244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
128344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void SmiTag(Register reg) {
128444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Addu(reg, reg, reg);
128544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
128644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Test for overflow < 0: use BranchOnOverflow() or BranchOnNoOverflow().
12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void SmiTagCheckOverflow(Register reg, Register overflow);
12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void SmiTagCheckOverflow(Register dst, Register src, Register overflow);
12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
129144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void SmiTag(Register dst, Register src) {
129244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Addu(dst, src, src);
129344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
129444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
129544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void SmiUntag(Register reg) {
129644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sra(reg, reg, kSmiTagSize);
129744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
129844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
129944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void SmiUntag(Register dst, Register src) {
130044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sra(dst, src, kSmiTagSize);
130144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
130244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
13033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Untag the source value into destination and jump if source is a smi.
13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Souce and destination can be the same register.
13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case);
13063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Untag the source value into destination and jump if source is not a smi.
13083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Souce and destination can be the same register.
13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case);
13103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
131144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Jump the register contains a smi.
13123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void JumpIfSmi(Register value,
13133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 Label* smi_label,
13143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 Register scratch = at,
13153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 BranchDelaySlot bd = PROTECT);
131644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
131744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Jump if the register contains a non-smi.
13183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void JumpIfNotSmi(Register value,
13193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    Label* not_smi_label,
13203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    Register scratch = at,
13213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    BranchDelaySlot bd = PROTECT);
132244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
132344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Jump if either of the registers contain a non-smi.
132444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi);
132544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Jump if either of the registers contain a smi.
132644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi);
132744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
132844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Abort execution if argument is a smi. Used in debug code.
132944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void AbortIfSmi(Register object);
133044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void AbortIfNotSmi(Register object);
133144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Abort execution if argument is a string. Used in debug code.
1333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void AbortIfNotString(Register object);
1334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
133544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Abort execution if argument is not the root value with the given index.
133644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void AbortIfNotRootValue(Register src,
133744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           Heap::RootListIndex root_value_index,
133844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           const char* message);
133944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
134044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // ---------------------------------------------------------------------------
1341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // HeapNumber utilities.
134244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
134344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void JumpIfNotHeapNumber(Register object,
134444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           Register heap_number_map,
134544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           Register scratch,
134644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           Label* on_not_heap_number);
134744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
134844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // -------------------------------------------------------------------------
1349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // String utilities.
135044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
135144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Checks if both instance types are sequential ASCII strings and jumps to
135244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // label if either is not.
135344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void JumpIfBothInstanceTypesAreNotSequentialAscii(
135444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Register first_object_instance_type,
135544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Register second_object_instance_type,
135644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Register scratch1,
135744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Register scratch2,
135844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Label* failure);
135944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
136044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check if instance type is sequential ASCII string and jump to label if
136144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // it is not.
136244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void JumpIfInstanceTypeIsNotSequentialAscii(Register type,
136344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                              Register scratch,
136444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                              Label* failure);
136544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
136644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Test that both first and second are sequential ASCII strings.
136744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Assume that they are non-smis.
136844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void JumpIfNonSmisNotBothSequentialAsciiStrings(Register first,
136944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  Register second,
137044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  Register scratch1,
137144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  Register scratch2,
137244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  Label* failure);
137344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
137444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Test that both first and second are sequential ASCII strings.
137544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that they are non-smis.
137644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void JumpIfNotBothSequentialAsciiStrings(Register first,
137744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                           Register second,
137844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                           Register scratch1,
137944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                           Register scratch2,
138044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                           Label* failure);
138144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void ClampUint8(Register output_reg, Register input_reg);
13833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void ClampDoubleToUint8(Register result_reg,
13853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          DoubleRegister input_reg,
13863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          DoubleRegister temp_double_reg);
13873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void LoadInstanceDescriptors(Register map, Register descriptors);
1390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
13913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Activation support.
13933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void EnterFrame(StackFrame::Type type);
13943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void LeaveFrame(StackFrame::Type type);
13953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Patch the relocated value (lui/ori pair).
13973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void PatchRelocatedValue(Register li_location,
13983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Register scratch,
13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Register new_value);
14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the relocatad value (loaded data) from the lui/ori pair.
14013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void GetRelocatedValue(Register li_location,
14023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         Register value,
14033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         Register scratch);
14043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Expects object in a0 and returns map with validated enum cache
14063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // in a0.  Assumes that any other register can be used as a scratch.
14073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CheckEnumCache(Register null_value, Label* call_runtime);
14083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu private:
141044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void CallCFunctionHelper(Register function,
14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           int num_reg_arguments,
14123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           int num_double_arguments);
14136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void BranchShort(int16_t offset, BranchDelaySlot bdslot = PROTECT);
14153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void BranchShort(int16_t offset, Condition cond, Register rs,
14163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                   const Operand& rt,
14173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                   BranchDelaySlot bdslot = PROTECT);
14183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void BranchShort(Label* L, BranchDelaySlot bdslot = PROTECT);
14193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void BranchShort(Label* L, Condition cond, Register rs,
14203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                   const Operand& rt,
14213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                   BranchDelaySlot bdslot = PROTECT);
14223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void BranchAndLinkShort(int16_t offset, BranchDelaySlot bdslot = PROTECT);
14233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void BranchAndLinkShort(int16_t offset, Condition cond, Register rs,
14243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
14253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bdslot = PROTECT);
14263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void BranchAndLinkShort(Label* L, BranchDelaySlot bdslot = PROTECT);
14273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void BranchAndLinkShort(Label* L, Condition cond, Register rs,
14283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          const Operand& rt,
14293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          BranchDelaySlot bdslot = PROTECT);
14303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void J(Label* L, BranchDelaySlot bdslot);
14313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Jr(Label* L, BranchDelaySlot bdslot);
14323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Jalr(Label* L, BranchDelaySlot bdslot);
14333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
14346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Helper functions for generating invokes.
14356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void InvokePrologue(const ParameterCount& expected,
14366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      const ParameterCount& actual,
14376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      Handle<Code> code_constant,
14386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      Register code_reg,
14396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      Label* done,
14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      bool* definitely_mismatches,
144144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      InvokeFlag flag,
14423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      const CallWrapper& call_wrapper,
14433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      CallKind call_kind);
14446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Get the code for the given builtin. Returns if able to resolve
14463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // the function in the 'resolved' flag.
14473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Handle<Code> ResolveBuiltin(Builtins::JavaScript id, bool* resolved);
14483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
144944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void InitializeNewString(Register string,
145044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           Register length,
145144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           Heap::RootListIndex map_index,
145244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           Register scratch1,
145344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           Register scratch2);
145444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
14553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
14563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void InNewSpace(Register object,
14573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Register scratch,
14583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Condition cond,  // eq for new space, ne otherwise.
14593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Label* branch);
14603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Helper for finding the mark bits for an address.  Afterwards, the
14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // bitmap register points at the word with the mark bits and the mask
14633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the position of the first bit.  Leaves addr_reg unchanged.
14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline void GetMarkBits(Register addr_reg,
14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          Register bitmap_reg,
14663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          Register mask_reg);
14673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Helper for throwing exceptions.  Compute a handler address and jump to
14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // it.  See the implementation for register usage.
14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void JumpToHandlerEntry();
14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Compute memory operands for safepoint stack slots.
1473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static int SafepointRegisterStackIndex(int reg_code);
1474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  MemOperand SafepointRegisterSlot(Register reg);
1475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  MemOperand SafepointRegistersAndDoublesSlot(Register reg);
147644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
147744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool generating_stub_;
147844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool allow_stub_calls_;
14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool has_frame_;
148044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // This handle will be patched with the code object on installation.
148144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Object> code_object_;
1482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Needs access to SafepointRegisterStackIndex for optimized frame
1484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // traversal.
1485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  friend class OptimizedFrame;
148644f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
148744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
148844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
148944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// The code patcher is used to patch (typically) small parts of code e.g. for
149044f0eee88ff00398ff7f715fab053374d808c90dSteve Block// debugging and other types of instrumentation. When using the code patcher
149144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// the exact number of bytes specified must be emitted. It is not legal to emit
149244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// relocation information. If any of these constraints are violated it causes
149344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// an assertion to fail.
149444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass CodePatcher {
149544f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
149644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CodePatcher(byte* address, int instructions);
149744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  virtual ~CodePatcher();
149844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
149944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Macro assembler to emit code.
150044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  MacroAssembler* masm() { return &masm_; }
150144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
150244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Emit an instruction directly.
1503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void Emit(Instr instr);
150444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
150544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Emit an address directly.
150644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Emit(Address addr);
150744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Change the condition part of an instruction leaving the rest of the current
1509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // instruction unchanged.
1510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void ChangeBranchCondition(Condition cond);
1511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
151244f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
151344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  byte* address_;  // The address of the code being patched.
151444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int instructions_;  // Number of instructions of the expected patch size.
151544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int size_;  // Number of bytes of the expected patch size.
151644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  MacroAssembler masm_;  // Macro assembler used to generate the code.
151744f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
15183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#ifdef GENERATED_CODE_COVERAGE
15223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define CODE_COVERAGE_STRINGIFY(x) #x
15233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
15243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
15253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm->
15263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#else
15273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define ACCESS_MASM(masm) masm->
15283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#endif
15293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} }  // namespace v8::internal
15313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#endif  // V8_MIPS_MACRO_ASSEMBLER_MIPS_H_
1533