1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_MIPS_MACRO_ASSEMBLER_MIPS_H_
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define V8_MIPS_MACRO_ASSEMBLER_MIPS_H_
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/assembler.h"
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/globals.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/mips64/assembler-mips64.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Give alias names to registers for calling conventions.
16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kReturnRegister0 = {Register::kCode_v0};
17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kReturnRegister1 = {Register::kCode_v1};
18109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochconst Register kReturnRegister2 = {Register::kCode_a0};
19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kJSFunctionRegister = {Register::kCode_a1};
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kContextRegister = {Register::kCpRegister};
21bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochconst Register kAllocateSizeRegister = {Register::kCode_a0};
22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kInterpreterAccumulatorRegister = {Register::kCode_v0};
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kInterpreterBytecodeOffsetRegister = {Register::kCode_t0};
24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kInterpreterBytecodeArrayRegister = {Register::kCode_t1};
25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kInterpreterDispatchTableRegister = {Register::kCode_t2};
26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kJavaScriptCallArgCountRegister = {Register::kCode_a0};
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kJavaScriptCallNewTargetRegister = {Register::kCode_a3};
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kRuntimeCallFunctionRegister = {Register::kCode_a1};
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kRuntimeCallArgCountRegister = {Register::kCode_a0};
30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Forward declaration.
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass JumpTarget;
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Reserved Register Usage Summary.
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Registers t8, t9, and at are reserved for use by the MacroAssembler.
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The programmer should know that the MacroAssembler may clobber these three,
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// but won't touch other registers except in special cases.
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Per the MIPS ABI, register t9 must be used for indirect function call
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// via 'jalr t9' or 'jr t9' instructions. This is relied upon by gcc when
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// trying to update gp register for position-independent-code. Whenever
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// MIPS generated code calls C code, it must be via t9 register.
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Flags used for LeaveExitFrame function.
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum LeaveExitFrameMode {
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EMIT_RETURN = true,
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NO_EMIT_RETURN = false
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Flags used for AllocateHeapNumber
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum TaggingMode {
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Tag the result.
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TAG_RESULT,
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Don't tag
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DONT_TAG_RESULT
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Flags used for the ObjectToDoubleFPURegister function.
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum ObjectToDoubleFlags {
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // No special flags.
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NO_OBJECT_TO_DOUBLE_FLAGS = 0,
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Object is known to be a non smi.
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  OBJECT_NOT_SMI = 1 << 0,
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Don't load NaNs or infinities, branch to the non number case instead.
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AVOID_NANS_AND_INFINITIES = 1 << 1
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Allow programmer to use Branch Delay Slot of Branches, Jumps, Calls.
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum BranchDelaySlot {
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  USE_DELAY_SLOT,
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PROTECT
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Flags used for the li macro-assembler function.
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum LiFlags {
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the constant value can be represented in just 16 bits, then
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // optimize the li to use a single instruction, rather than lui/ori/dsll
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // sequence.
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  OPTIMIZE_SIZE = 0,
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Always use 6 instructions (lui/ori/dsll sequence), even if the constant
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // could be loaded with just one, so that this value is patchable later.
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CONSTANT_SIZE = 1,
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For address loads only 4 instruction are required. Used to mark
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // constant load that will be used as address without relocation
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // information. It ensures predictable code size, so specific sites
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // in code are patchable.
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ADDRESS_LOAD  = 2
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum PointersToHereCheck {
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  kPointersToHereMaybeInteresting,
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  kPointersToHereAreAlwaysInteresting
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum RAStatus { kRAHasNotBeenSaved, kRAHasBeenSaved };
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister GetRegisterThatIsNotOneOf(Register reg1,
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register reg2 = no_reg,
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register reg3 = no_reg,
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register reg4 = no_reg,
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register reg5 = no_reg,
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register reg6 = no_reg);
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool AreAliased(Register reg1, Register reg2, Register reg3 = no_reg,
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                Register reg4 = no_reg, Register reg5 = no_reg,
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                Register reg6 = no_reg, Register reg7 = no_reg,
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                Register reg8 = no_reg, Register reg9 = no_reg,
113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                Register reg10 = no_reg);
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// -----------------------------------------------------------------------------
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Static helper functions.
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#if defined(V8_TARGET_LITTLE_ENDIAN)
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define SmiWordOffset(offset) (offset + kPointerSize / 2)
121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#else
122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define SmiWordOffset(offset) offset
123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif
124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochinline MemOperand ContextMemOperand(Register context, int index) {
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return MemOperand(context, Context::SlotOffset(index));
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochinline MemOperand NativeContextMemOperand() {
132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return ContextMemOperand(cp, Context::NATIVE_CONTEXT_INDEX);
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Generate a MemOperand for loading a field from an object.
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline MemOperand FieldMemOperand(Register object, int offset) {
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return MemOperand(object, offset - kHeapObjectTag);
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline MemOperand UntagSmiMemOperand(Register rm, int offset) {
143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Assumes that Smis are shifted by 32 bits.
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kSmiShift == 32);
145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return MemOperand(rm, SmiWordOffset(offset));
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline MemOperand UntagSmiFieldMemOperand(Register rm, int offset) {
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return UntagSmiMemOperand(rm, offset - kHeapObjectTag);
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Generate a MemOperand for storing arguments 5..N on the stack
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// when calling CallCFunction().
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(plind): Currently ONLY used for O32. Should be fixed for
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//              n64, and used in RegExp code, and other places
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//              with more than 8 arguments.
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline MemOperand CFunctionArgumentOperand(int index) {
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(index > kCArgSlotCount);
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Argument 5 takes the slot just past the four Arg-slots.
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int offset = (index - 5) * kPointerSize + kCArgsSlotsSize;
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return MemOperand(sp, offset);
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// MacroAssembler implements a collection of frequently used macros.
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass MacroAssembler: public Assembler {
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MacroAssembler(Isolate* isolate, void* buffer, int size,
171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 CodeObjectRequired create_code_object);
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Arguments macros.
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define COND_TYPED_ARGS Condition cond, Register r1, const Operand& r2
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define COND_ARGS cond, r1, r2
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Cases when relocation is not needed.
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DECLARE_NORELOC_PROTOTYPE(Name, target_type) \
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Name(target_type target, BranchDelaySlot bd = PROTECT); \
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void Name(BranchDelaySlot bd, target_type target) { \
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Name(target, bd); \
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } \
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Name(target_type target, \
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            COND_TYPED_ARGS, \
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            BranchDelaySlot bd = PROTECT); \
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void Name(BranchDelaySlot bd, \
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   target_type target, \
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   COND_TYPED_ARGS) { \
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Name(target, COND_ARGS, bd); \
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define DECLARE_BRANCH_PROTOTYPES(Name)   \
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DECLARE_NORELOC_PROTOTYPE(Name, Label*) \
194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DECLARE_NORELOC_PROTOTYPE(Name, int32_t)
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DECLARE_BRANCH_PROTOTYPES(Branch)
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DECLARE_BRANCH_PROTOTYPES(BranchAndLink)
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DECLARE_BRANCH_PROTOTYPES(BranchShort)
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef DECLARE_BRANCH_PROTOTYPES
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef COND_TYPED_ARGS
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef COND_ARGS
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Jump, Call, and Ret pseudo instructions implementing inter-working.
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define COND_ARGS Condition cond = al, Register rs = zero_reg, \
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Jump(Register target, COND_ARGS);
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Jump(intptr_t target, RelocInfo::Mode rmode, COND_ARGS);
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Jump(Address target, RelocInfo::Mode rmode, COND_ARGS);
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Jump(Handle<Code> code, RelocInfo::Mode rmode, COND_ARGS);
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static int CallSize(Register target, COND_ARGS);
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Call(Register target, COND_ARGS);
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static int CallSize(Address target, RelocInfo::Mode rmode, COND_ARGS);
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Call(Address target, RelocInfo::Mode rmode, COND_ARGS);
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int CallSize(Handle<Code> code,
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               TypeFeedbackId ast_id = TypeFeedbackId::None(),
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               COND_ARGS);
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Call(Handle<Code> code,
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            TypeFeedbackId ast_id = TypeFeedbackId::None(),
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            COND_ARGS);
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Ret(COND_ARGS);
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void Ret(BranchDelaySlot bd, Condition cond = al,
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register rs = zero_reg, const Operand& rt = Operand(zero_reg)) {
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Ret(cond, rs, rt, bd);
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool IsNear(Label* L, Condition cond, int rs_reg);
232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Branch(Label* L,
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              Condition cond,
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              Register rs,
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              Heap::RootListIndex index,
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              BranchDelaySlot bdslot = PROTECT);
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
239109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // GetLabelFunction must be lambda '[](size_t index) -> Label*' or a
240109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // functor/function with 'Label *func(size_t index)' declaration.
241109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  template <typename Func>
242109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void GenerateSwitchTable(Register index, size_t case_count,
243109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                           Func GetLabelFunction);
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef COND_ARGS
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
246f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Emit code that loads |parameter_index|'th parameter from the stack to
247f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // the register according to the CallInterfaceDescriptor definition.
248f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // |sp_to_caller_sp_offset_in_words| specifies the number of words pushed
249f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // below the caller's sp.
250f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  template <class Descriptor>
251f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void LoadParameterFromStack(
252f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      Register reg, typename Descriptor::ParameterIndices parameter_index,
253f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      int sp_to_ra_offset_in_words = 0) {
254f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    DCHECK(Descriptor::kPassLastArgsOnStack);
255f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    UNIMPLEMENTED();
256f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
257f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Emit code to discard a non-negative number of pointer-sized elements
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // from the stack, clobbering only the sp register.
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Drop(int count,
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            Condition cond = cc_always,
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            Register reg = no_reg,
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            const Operand& op = Operand(no_reg));
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Trivial case of DropAndRet that utilizes the delay slot and only emits
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // 2 instructions.
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DropAndRet(int drop);
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DropAndRet(int drop,
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Condition cond,
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Register reg,
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  const Operand& op);
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Swap two registers.  If the scratch register is omitted then a slightly
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // less efficient form using xor instead of mov is emitted.
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Swap(Register reg1, Register reg2, Register scratch = no_reg);
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Call(Label* target);
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline void Move(Register dst, Handle<Object> handle) { li(dst, handle); }
2813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline void Move(Register dst, Smi* smi) { li(dst, Operand(smi)); }
282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void Move(Register dst, Register src) {
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!dst.is(src)) {
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mov(dst, src);
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline void Move_d(FPURegister dst, FPURegister src) {
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!dst.is(src)) {
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mov_d(dst, src);
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline void Move_s(FPURegister dst, FPURegister src) {
2963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (!dst.is(src)) {
2973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      mov_s(dst, src);
2983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
2993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
3003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline void Move(FPURegister dst, FPURegister src) { Move_d(dst, src); }
3023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void Move(Register dst_low, Register dst_high, FPURegister src) {
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mfc1(dst_low, src);
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mfhc1(dst_high, src);
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline void Move(Register dst, FPURegister src) { dmfc1(dst, src); }
3093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline void Move(FPURegister dst, Register src) { dmtc1(src, dst); }
3113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void FmoveHigh(Register dst_high, FPURegister src) {
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mfhc1(dst_high, src);
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void FmoveHigh(FPURegister dst, Register src_high) {
317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mthc1(src_high, dst);
318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void FmoveLow(Register dst_low, FPURegister src) {
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mfc1(dst_low, src);
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void FmoveLow(FPURegister dst, Register src_low);
325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void Move(FPURegister dst, Register src_low, Register src_high) {
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mtc1(src_low, dst);
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mthc1(src_high, dst);
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void Move(FPURegister dst, float imm);
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Move(FPURegister dst, double imm);
333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Conditional move.
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Movz(Register rd, Register rs, Register rt);
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Movn(Register rd, Register rs, Register rt);
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Movt(Register rd, Register rs, uint16_t cc = 0);
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Movf(Register rd, Register rs, uint16_t cc = 0);
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Min, Max macros.
3413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // On pre-r6 these functions may modify at and t8 registers.
3423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void MinNaNCheck_d(FPURegister dst, FPURegister src1, FPURegister src2,
3433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                     Label* nan = nullptr);
3443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void MaxNaNCheck_d(FPURegister dst, FPURegister src1, FPURegister src2,
3453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                     Label* nan = nullptr);
3463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void MinNaNCheck_s(FPURegister dst, FPURegister src1, FPURegister src2,
3473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                     Label* nan = nullptr);
3483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void MaxNaNCheck_s(FPURegister dst, FPURegister src1, FPURegister src2,
3493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                     Label* nan = nullptr);
3503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Clz(Register rd, Register rs);
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Jump unconditionally to given label.
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We NEED a nop in the branch delay slot, as it used by v8, for example in
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // CodeGenerator::ProcessDeferred().
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Currently the branch delay slot is filled by the MacroAssembler.
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Use rather b(Label) for code generation.
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void jmp(Label* L) {
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Branch(L);
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Load(Register dst, const MemOperand& src, Representation r);
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Store(Register src, const MemOperand& dst, Representation r);
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void PushRoot(Heap::RootListIndex index) {
366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LoadRoot(at, index);
367014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(at);
368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Compare the object in a register to a value and jump if they are equal.
371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void JumpIfRoot(Register with, Heap::RootListIndex index, Label* if_equal) {
372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LoadRoot(at, index);
373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Branch(if_equal, eq, with, Operand(at));
374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Compare the object in a register to a value and jump if they are not equal.
377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void JumpIfNotRoot(Register with, Heap::RootListIndex index,
378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     Label* if_not_equal) {
379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LoadRoot(at, index);
380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Branch(if_not_equal, ne, with, Operand(at));
381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load an object from the root table.
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void LoadRoot(Register destination,
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Heap::RootListIndex index);
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void LoadRoot(Register destination,
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Heap::RootListIndex index,
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Condition cond, Register src1, const Operand& src2);
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Store an object to the root table.
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void StoreRoot(Register source,
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 Heap::RootListIndex index);
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void StoreRoot(Register source,
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 Heap::RootListIndex index,
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 Condition cond, Register src1, const Operand& src2);
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ---------------------------------------------------------------------------
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // GC Support
399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void IncrementalMarkingRecordWriteHelper(Register object,
401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register value,
402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register address);
403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum RememberedSetFinalAction {
405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    kReturnAtEnd,
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    kFallThroughAtEnd
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Record in the remembered set the fact that we have a pointer to new space
411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // at the address pointed to by the addr register.  Only works if addr is not
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // in new space.
413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RememberedSetHelper(Register object,  // Used for debug code.
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Register addr,
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Register scratch,
416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           SaveFPRegsMode save_fp,
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           RememberedSetFinalAction and_then);
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CheckPageFlag(Register object,
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     Register scratch,
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     int mask,
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     Condition cc,
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     Label* condition_met);
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if object is in new space.  Jumps if the object is not in new space.
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The register scratch can be object itself, but it will be clobbered.
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfNotInNewSpace(Register object,
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Register scratch,
429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Label* branch) {
430109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    InNewSpace(object, scratch, eq, branch);
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if object is in new space.  Jumps if the object is in new space.
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The register scratch can be object itself, but scratch will be clobbered.
435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfInNewSpace(Register object,
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        Register scratch,
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        Label* branch) {
438109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    InNewSpace(object, scratch, ne, branch);
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if an object has a given incremental marking color.
442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void HasColor(Register object,
443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register scratch0,
444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register scratch1,
445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Label* has_color,
446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                int first_bit,
447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                int second_bit);
448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfBlack(Register object,
450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   Register scratch0,
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   Register scratch1,
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   Label* on_black);
453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Checks the color of an object.  If the object is white we jump to the
455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // incremental marker.
456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void JumpIfWhite(Register value, Register scratch1, Register scratch2,
457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   Register scratch3, Label* value_is_white);
458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Notify the garbage collector that we wrote a pointer into an object.
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // |object| is the object being stored into, |value| is the object being
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // stored.  value and scratch registers are clobbered by the operation.
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The offset is the offset from the start of the object, not the offset from
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the tagged HeapObject pointer.  For use with FieldOperand(reg, off).
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RecordWriteField(
465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register object,
466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int offset,
467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register value,
468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register scratch,
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RAStatus ra_status,
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SaveFPRegsMode save_fp,
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SmiCheck smi_check = INLINE_SMI_CHECK,
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PointersToHereCheck pointers_to_here_check_for_value =
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          kPointersToHereMaybeInteresting);
475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // As above, but the offset has the tag presubtracted.  For use with
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // MemOperand(reg, off).
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void RecordWriteContextSlot(
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register context,
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int offset,
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register value,
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register scratch,
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RAStatus ra_status,
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SaveFPRegsMode save_fp,
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SmiCheck smi_check = INLINE_SMI_CHECK,
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PointersToHereCheck pointers_to_here_check_for_value =
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          kPointersToHereMaybeInteresting) {
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RecordWriteField(context,
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     offset + kHeapObjectTag,
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     value,
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     scratch,
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     ra_status,
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     save_fp,
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     remembered_set_action,
496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     smi_check,
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     pointers_to_here_check_for_value);
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
500109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Notify the garbage collector that we wrote a code entry into a
501109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // JSFunction. Only scratch is clobbered by the operation.
502109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void RecordWriteCodeEntryField(Register js_function, Register code_entry,
503109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                 Register scratch);
504109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RecordWriteForMap(
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register object,
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register map,
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register dst,
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RAStatus ra_status,
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SaveFPRegsMode save_fp);
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For a given |object| notify the garbage collector that the slot |address|
513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // has been written.  |value| is the object being stored. The value and
514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // address registers are clobbered by the operation.
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RecordWrite(
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register object,
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register address,
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register value,
519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RAStatus ra_status,
520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SaveFPRegsMode save_fp,
521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SmiCheck smi_check = INLINE_SMI_CHECK,
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PointersToHereCheck pointers_to_here_check_for_value =
524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          kPointersToHereMaybeInteresting);
525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ---------------------------------------------------------------------------
528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Inline caching support.
529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void GetNumberHash(Register reg0, Register scratch);
531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void MarkCode(NopMarkerTypes type) {
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    nop(type);
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if the given instruction is a 'type' marker.
537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // i.e. check if it is a sll zero_reg, zero_reg, <type> (referenced as
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // nop(type)). These instructions are generated to mark special location in
539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the code, like some special IC code.
540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline bool IsMarkedCode(Instr instr, int type) {
541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER));
542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return IsNop(instr, type);
543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline int GetCodeMarker(Instr instr) {
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t opcode = ((instr & kOpcodeMask));
548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t rt = ((instr & kRtFieldMask) >> kRtShift);
549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t rs = ((instr & kRsFieldMask) >> kRsShift);
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t sa = ((instr & kSaFieldMask) >> kSaShift);
551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Return <n> if we have a sll zero_reg, zero_reg, n
553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // else return -1.
554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool sllzz = (opcode == SLL &&
555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  rt == static_cast<uint32_t>(ToNumber(zero_reg)) &&
556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  rs == static_cast<uint32_t>(ToNumber(zero_reg)));
557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int type =
558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        (sllzz && FIRST_IC_MARKER <= sa && sa < LAST_CODE_MARKER) ? sa : -1;
559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK((type == -1) ||
560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)));
561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return type;
562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ---------------------------------------------------------------------------
567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocation support.
568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allocate an object in new space or old space. The object_size is
570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // specified either in bytes or in words if the allocation flag SIZE_IN_WORDS
571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // is passed. If the space is exhausted control continues at the gc_required
572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // label. The allocated object is returned in result. If the flag
573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // tag_allocated_object is true the result is tagged as as a heap object.
574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // All registers are clobbered also when control continues at the gc_required
575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // label.
576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Allocate(int object_size,
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register result,
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register scratch1,
579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register scratch2,
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Label* gc_required,
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                AllocationFlags flags);
582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Allocate(Register object_size, Register result, Register result_end,
584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                Register scratch, Label* gc_required, AllocationFlags flags);
585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
586bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // FastAllocate is right now only used for folded allocations. It just
587bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // increments the top pointer without checking against limit. This can only
588bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // be done if it was proved earlier that the allocation will succeed.
589bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void FastAllocate(int object_size, Register result, Register scratch1,
590bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                    Register scratch2, AllocationFlags flags);
591bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
592bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void FastAllocate(Register object_size, Register result, Register result_new,
593bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                    Register scratch, AllocationFlags flags);
594bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AllocateTwoByteString(Register result,
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             Register length,
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             Register scratch1,
598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             Register scratch2,
599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             Register scratch3,
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             Label* gc_required);
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AllocateOneByteString(Register result, Register length,
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             Register scratch1, Register scratch2,
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             Register scratch3, Label* gc_required);
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AllocateTwoByteConsString(Register result,
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register length,
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register scratch1,
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register scratch2,
608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Label* gc_required);
609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AllocateOneByteConsString(Register result, Register length,
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register scratch1, Register scratch2,
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Label* gc_required);
612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AllocateTwoByteSlicedString(Register result,
613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register length,
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register scratch1,
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register scratch2,
616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Label* gc_required);
617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AllocateOneByteSlicedString(Register result, Register length,
618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register scratch1, Register scratch2,
619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Label* gc_required);
620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocates a heap number or jumps to the gc_required label if the young
622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // space is full and a scavenge is needed. All registers are clobbered also
623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // when control continues at the gc_required label.
624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AllocateHeapNumber(Register result,
625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          Register scratch1,
626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          Register scratch2,
627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          Register heap_number_map,
628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          Label* gc_required,
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          MutableMode mode = IMMUTABLE);
630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AllocateHeapNumberWithValue(Register result,
632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   FPURegister value,
633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register scratch1,
634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register scratch2,
635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Label* gc_required);
636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allocate and initialize a JSValue wrapper with the specified {constructor}
638014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // and {value}.
639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void AllocateJSValue(Register result, Register constructor, Register value,
640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       Register scratch1, Register scratch2,
641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       Label* gc_required);
642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ---------------------------------------------------------------------------
644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instruction macros.
645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DEFINE_INSTRUCTION(instr)                                              \
647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void instr(Register rd, Register rs, const Operand& rt);                     \
648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void instr(Register rd, Register rs, Register rt) {                          \
649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    instr(rd, rs, Operand(rt));                                                \
650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }                                                                            \
651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void instr(Register rs, Register rt, int32_t j) {                            \
652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    instr(rs, rt, Operand(j));                                                 \
653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DEFINE_INSTRUCTION2(instr)                                             \
656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void instr(Register rs, const Operand& rt);                                  \
657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void instr(Register rs, Register rt) {                                       \
658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    instr(rs, Operand(rt));                                                    \
659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }                                                                            \
660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void instr(Register rs, int32_t j) {                                         \
661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    instr(rs, Operand(j));                                                     \
662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION(Addu);
665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION(Daddu);
666958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DEFINE_INSTRUCTION(Div);
667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DEFINE_INSTRUCTION(Divu);
668958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DEFINE_INSTRUCTION(Ddivu);
669958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DEFINE_INSTRUCTION(Mod);
670958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DEFINE_INSTRUCTION(Modu);
671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION(Ddiv);
672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION(Subu);
673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION(Dsubu);
674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION(Dmod);
675958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DEFINE_INSTRUCTION(Dmodu);
676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION(Mul);
677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION(Mulh);
678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DEFINE_INSTRUCTION(Mulhu);
679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION(Dmul);
680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION(Dmulh);
681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION2(Mult);
682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION2(Dmult);
683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION2(Multu);
684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION2(Dmultu);
685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION2(Div);
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION2(Ddiv);
687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION2(Divu);
688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION2(Ddivu);
689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION(And);
691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION(Or);
692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION(Xor);
693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION(Nor);
694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION2(Neg);
695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION(Slt);
697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION(Sltu);
698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // MIPS32 R2 instruction macro.
700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION(Ror);
701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DEFINE_INSTRUCTION(Dror);
702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef DEFINE_INSTRUCTION
704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef DEFINE_INSTRUCTION2
705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef DEFINE_INSTRUCTION3
706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
7073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Load Scaled Address instructions. Parameter sa (shift argument) must be
7083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // between [1, 31] (inclusive). On pre-r6 architectures the scratch register
7093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // may be clobbered.
710014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Lsa(Register rd, Register rs, Register rt, uint8_t sa,
711014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           Register scratch = at);
712014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Dlsa(Register rd, Register rs, Register rt, uint8_t sa,
713014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Register scratch = at);
714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Pref(int32_t hint, const MemOperand& rs);
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ---------------------------------------------------------------------------
719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Pseudo-instructions.
720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
72113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Change endianness
722f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void ByteSwapSigned(Register dest, Register src, int operand_size);
723f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void ByteSwapUnsigned(Register dest, Register src, int operand_size);
72413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void mov(Register rd, Register rt) { or_(rd, rt, zero_reg); }
726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
727bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void Ulh(Register rd, const MemOperand& rs);
728bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void Ulhu(Register rd, const MemOperand& rs);
729bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void Ush(Register rd, const MemOperand& rs, Register scratch);
730bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Ulw(Register rd, const MemOperand& rs);
732bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void Ulwu(Register rd, const MemOperand& rs);
733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Usw(Register rd, const MemOperand& rs);
734bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
735bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void Uld(Register rd, const MemOperand& rs);
736bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void Usd(Register rd, const MemOperand& rs);
737bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
738bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void Ulwc1(FPURegister fd, const MemOperand& rs, Register scratch);
739bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void Uswc1(FPURegister fd, const MemOperand& rs, Register scratch);
740bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
741bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void Uldc1(FPURegister fd, const MemOperand& rs, Register scratch);
742bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void Usdc1(FPURegister fd, const MemOperand& rs, Register scratch);
743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LoadWordPair(Register rd, const MemOperand& rs, Register scratch = at);
745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void StoreWordPair(Register rd, const MemOperand& rs, Register scratch = at);
746014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load int32 in the rd register.
748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void li(Register rd, Operand j, LiFlags mode = OPTIMIZE_SIZE);
749109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline bool LiLower32BitHelper(Register rd, Operand j);
750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void li(Register rd, int64_t j, LiFlags mode = OPTIMIZE_SIZE) {
751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    li(rd, Operand(j), mode);
752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void li(Register dst, Handle<Object> value, LiFlags mode = OPTIMIZE_SIZE);
754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push multiple registers on the stack.
756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Registers are saved in numerical order, with higher numbered registers
757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // saved in higher memory addresses.
758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MultiPush(RegList regs);
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MultiPushReversed(RegList regs);
760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MultiPushFPU(RegList regs);
762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MultiPushReversedFPU(RegList regs);
763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void push(Register src) {
765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Daddu(sp, sp, Operand(-kPointerSize));
766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sd(src, MemOperand(sp, 0));
767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Push(Register src) { push(src); }
769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push a handle.
771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Push(Handle<Object> handle);
772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); }
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push two registers. Pushes leftmost register first (to highest address).
775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Push(Register src1, Register src2) {
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Dsubu(sp, sp, Operand(2 * kPointerSize));
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sd(src1, MemOperand(sp, 1 * kPointerSize));
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sd(src2, MemOperand(sp, 0 * kPointerSize));
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push three registers. Pushes leftmost register first (to highest address).
782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Push(Register src1, Register src2, Register src3) {
783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Dsubu(sp, sp, Operand(3 * kPointerSize));
784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sd(src1, MemOperand(sp, 2 * kPointerSize));
785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sd(src2, MemOperand(sp, 1 * kPointerSize));
786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sd(src3, MemOperand(sp, 0 * kPointerSize));
787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push four registers. Pushes leftmost register first (to highest address).
790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Push(Register src1, Register src2, Register src3, Register src4) {
791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Dsubu(sp, sp, Operand(4 * kPointerSize));
792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sd(src1, MemOperand(sp, 3 * kPointerSize));
793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sd(src2, MemOperand(sp, 2 * kPointerSize));
794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sd(src3, MemOperand(sp, 1 * kPointerSize));
795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sd(src4, MemOperand(sp, 0 * kPointerSize));
796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
798014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Push five registers. Pushes leftmost register first (to highest address).
799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Push(Register src1, Register src2, Register src3, Register src4,
800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Register src5) {
801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Dsubu(sp, sp, Operand(5 * kPointerSize));
802014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    sd(src1, MemOperand(sp, 4 * kPointerSize));
803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    sd(src2, MemOperand(sp, 3 * kPointerSize));
804014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    sd(src3, MemOperand(sp, 2 * kPointerSize));
805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    sd(src4, MemOperand(sp, 1 * kPointerSize));
806014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    sd(src5, MemOperand(sp, 0 * kPointerSize));
807014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
808014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Push(Register src, Condition cond, Register tst1, Register tst2) {
810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Since we don't have conditional execution we use a Branch.
811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Branch(3, cond, tst1, Operand(tst2));
812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Dsubu(sp, sp, Operand(kPointerSize));
813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sd(src, MemOperand(sp, 0));
814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void PushRegisterAsTwoSmis(Register src, Register scratch = at);
817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void PopRegisterAsTwoSmis(Register dst, Register scratch = at);
818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Pops multiple values from the stack and load them in the
820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // registers specified in regs. Pop order is the opposite as in MultiPush.
821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MultiPop(RegList regs);
822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MultiPopReversed(RegList regs);
823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MultiPopFPU(RegList regs);
825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MultiPopReversedFPU(RegList regs);
826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void pop(Register dst) {
828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ld(dst, MemOperand(sp, 0));
829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Daddu(sp, sp, Operand(kPointerSize));
830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Pop(Register dst) { pop(dst); }
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Pop two registers. Pops rightmost register first (from lower address).
834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Pop(Register src1, Register src2) {
835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!src1.is(src2));
836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ld(src2, MemOperand(sp, 0 * kPointerSize));
837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ld(src1, MemOperand(sp, 1 * kPointerSize));
838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Daddu(sp, sp, 2 * kPointerSize);
839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Pop three registers. Pops rightmost register first (from lower address).
842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Pop(Register src1, Register src2, Register src3) {
843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ld(src3, MemOperand(sp, 0 * kPointerSize));
844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ld(src2, MemOperand(sp, 1 * kPointerSize));
845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ld(src1, MemOperand(sp, 2 * kPointerSize));
846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Daddu(sp, sp, 3 * kPointerSize);
847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Pop(uint32_t count = 1) {
850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Daddu(sp, sp, Operand(count * kPointerSize));
851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Push a fixed frame, consisting of ra, fp.
8543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void PushCommonFrame(Register marker_reg = no_reg);
8553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
8563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Push a standard frame, consisting of ra, fp, context and JS function.
8573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void PushStandardFrame(Register function_reg);
8583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
8593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void PopCommonFrame(Register marker_reg = no_reg);
8603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push and pop the registers that can hold pointers, as defined by the
862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // RegList constant kSafepointSavedRegisters.
863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void PushSafepointRegisters();
864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void PopSafepointRegisters();
865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Store value in register src in the safepoint stack slot for
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // register dst.
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void StoreToSafepointRegisterSlot(Register src, Register dst);
868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the value of the src register from its safepoint stack slot
869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // into register dst.
870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void LoadFromSafepointRegisterSlot(Register dst, Register src);
871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // MIPS64 R2 instruction macro.
873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Ins(Register rt, Register rs, uint16_t pos, uint16_t size);
874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Dins(Register rt, Register rs, uint16_t pos, uint16_t size);
875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Ext(Register rt, Register rs, uint16_t pos, uint16_t size);
876c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
877c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void ExtractBits(Register rt, Register rs, uint16_t pos, uint16_t size);
878c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
879958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void Dext(Register rt, Register rs, uint16_t pos, uint16_t size);
880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Dextm(Register rt, Register rs, uint16_t pos, uint16_t size);
881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Dextu(Register rt, Register rs, uint16_t pos, uint16_t size);
882f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void Neg_s(FPURegister fd, FPURegister fs);
883f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void Neg_d(FPURegister fd, FPURegister fs);
884f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
885f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // MIPS64 R6 instruction macros.
886f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void Bovc(Register rt, Register rs, Label* L);
887f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void Bnvc(Register rt, Register rs, Label* L);
888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ---------------------------------------------------------------------------
890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // FPU macros. These do not handle special cases like NaN or +- inf.
891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Convert unsigned word to double.
893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Cvt_d_uw(FPURegister fd, FPURegister fs);
894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Cvt_d_uw(FPURegister fd, Register rs);
895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Convert unsigned long to double.
897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Cvt_d_ul(FPURegister fd, FPURegister fs);
898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Cvt_d_ul(FPURegister fd, Register rs);
899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
900109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Convert unsigned word to float.
901109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void Cvt_s_uw(FPURegister fd, FPURegister fs);
902109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void Cvt_s_uw(FPURegister fd, Register rs);
903109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Convert unsigned long to float.
905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Cvt_s_ul(FPURegister fd, FPURegister fs);
906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Cvt_s_ul(FPURegister fd, Register rs);
907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Convert double to unsigned long.
909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Trunc_l_ud(FPURegister fd, FPURegister fs, FPURegister scratch);
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Trunc_l_d(FPURegister fd, FPURegister fs);
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Round_l_d(FPURegister fd, FPURegister fs);
913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Floor_l_d(FPURegister fd, FPURegister fs);
914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Ceil_l_d(FPURegister fd, FPURegister fs);
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Convert double to unsigned word.
917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Trunc_uw_d(FPURegister fd, FPURegister fs, FPURegister scratch);
918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Trunc_uw_d(FPURegister fd, Register rs, FPURegister scratch);
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
920109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Convert single to unsigned word.
921109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void Trunc_uw_s(FPURegister fd, FPURegister fs, FPURegister scratch);
922109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void Trunc_uw_s(FPURegister fd, Register rs, FPURegister scratch);
923109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Convert double to unsigned long.
925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Trunc_ul_d(FPURegister fd, FPURegister fs, FPURegister scratch,
926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                  Register result = no_reg);
927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Trunc_ul_d(FPURegister fd, Register rs, FPURegister scratch,
928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                  Register result = no_reg);
929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Convert single to unsigned long.
931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Trunc_ul_s(FPURegister fd, FPURegister fs, FPURegister scratch,
932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                  Register result = no_reg);
933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Trunc_ul_s(FPURegister fd, Register rs, FPURegister scratch,
934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                  Register result = no_reg);
935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Trunc_w_d(FPURegister fd, FPURegister fs);
937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Round_w_d(FPURegister fd, FPURegister fs);
938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Floor_w_d(FPURegister fd, FPURegister fs);
939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Ceil_w_d(FPURegister fd, FPURegister fs);
940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
94113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Preserve value of a NaN operand
94213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  void SubNanPreservePayloadAndSign_s(FPURegister fd, FPURegister fs,
94313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                      FPURegister ft);
94413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  void SubNanPreservePayloadAndSign_d(FPURegister fd, FPURegister fs,
94513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                      FPURegister ft);
94613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Madd_d(FPURegister fd,
948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              FPURegister fr,
949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              FPURegister fs,
950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              FPURegister ft,
951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              FPURegister scratch);
952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Wrapper functions for the different cmp/branch types.
954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void BranchF32(Label* target, Label* nan, Condition cc,
955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        FPURegister cmp1, FPURegister cmp2,
956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        BranchDelaySlot bd = PROTECT) {
957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchFCommon(S, target, nan, cc, cmp1, cmp2, bd);
958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void BranchF64(Label* target, Label* nan, Condition cc,
961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        FPURegister cmp1, FPURegister cmp2,
962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        BranchDelaySlot bd = PROTECT) {
963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchFCommon(D, target, nan, cc, cmp1, cmp2, bd);
964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Alternate (inline) version for better readability with USE_DELAY_SLOT.
967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void BranchF64(BranchDelaySlot bd, Label* target, Label* nan,
968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        Condition cc, FPURegister cmp1, FPURegister cmp2) {
969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchF64(target, nan, cc, cmp1, cmp2, bd);
970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void BranchF32(BranchDelaySlot bd, Label* target, Label* nan,
973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        Condition cc, FPURegister cmp1, FPURegister cmp2) {
974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchF32(target, nan, cc, cmp1, cmp2, bd);
975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Alias functions for backward compatibility.
978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void BranchF(Label* target, Label* nan, Condition cc, FPURegister cmp1,
979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      FPURegister cmp2, BranchDelaySlot bd = PROTECT) {
980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchF64(target, nan, cc, cmp1, cmp2, bd);
981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void BranchF(BranchDelaySlot bd, Label* target, Label* nan,
984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      Condition cc, FPURegister cmp1, FPURegister cmp2) {
985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BranchF64(bd, target, nan, cc, cmp1, cmp2);
986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Truncates a double using a specific rounding mode, and writes the value
989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to the result register.
990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The except_flag will contain any exceptions caused by the instruction.
991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If check_inexact is kDontCheckForInexactConversion, then the inexact
992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // exception is masked.
993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmitFPUTruncate(FPURoundingMode rounding_mode,
994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       Register result,
995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       DoubleRegister double_input,
996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       Register scratch,
997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       DoubleRegister double_scratch,
998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       Register except_flag,
999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       CheckForInexactConversion check_inexact
1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           = kDontCheckForInexactConversion);
1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Performs a truncating conversion of a floating point number as used by
1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it
1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // succeeds, otherwise falls through if result is saturated. On return
1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // 'result' either holds answer, or is clobbered on fall through.
1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Only public for the test code in test-code-stubs-arm.cc.
1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TryInlineTruncateDoubleToI(Register result,
1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  DoubleRegister input,
1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  Label* done);
1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Performs a truncating conversion of a floating point number as used by
1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the JS bitwise operations. See ECMA-262 9.5: ToInt32.
1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Exits with 'result' holding the answer.
1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TruncateDoubleToI(Register result, DoubleRegister double_input);
1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Performs a truncating conversion of a heap number as used by
1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 'result' and 'input'
1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // must be different registers. Exits with 'result' holding the answer.
1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TruncateHeapNumberToI(Register result, Register object);
1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Converts the smi or heap number in object to an int32 using the rules
1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // for ToInt32 as described in ECMAScript 9.5.: the value is truncated
1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // and brought into the range -2^31 .. +2^31 - 1. 'result' and 'input' must be
1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // different registers.
1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TruncateNumberToI(Register object,
1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register result,
1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register heap_number_map,
1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register scratch,
1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Label* not_int32);
1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loads the number from object into dst register.
1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If |object| is neither smi nor heap number, |not_number| is jumped to
1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // with |object| still intact.
1035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void LoadNumber(Register object,
1036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  FPURegister dst,
1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Register heap_number_map,
1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Register scratch,
1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Label* not_number);
1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loads the number from object into double_dst in the double format.
1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Control will jump to not_int32 if the value cannot be exactly represented
1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // by a 32-bit integer.
1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Floating point value in the 32-bit integer range that are not exact integer
1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // won't be loaded.
1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void LoadNumberAsInt32Double(Register object,
1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               DoubleRegister double_dst,
1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register heap_number_map,
1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register scratch1,
1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register scratch2,
1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               FPURegister double_scratch,
1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* not_int32);
1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loads the number from object into dst as a 32-bit integer.
1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Control will jump to not_int32 if the object cannot be exactly represented
1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // by a 32-bit integer.
1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Floating point value in the 32-bit integer range that are not exact integer
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // won't be converted.
1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void LoadNumberAsInt32(Register object,
1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register dst,
1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register heap_number_map,
1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register scratch1,
1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register scratch2,
1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         FPURegister double_scratch0,
1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         FPURegister double_scratch1,
1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Label* not_int32);
1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Enter exit frame.
1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // argc - argument count to be dropped by LeaveExitFrame.
1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // save_doubles - saves FPU registers on stack, currently disabled.
1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // stack_space - extra stack space.
1072f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void EnterExitFrame(bool save_doubles, int stack_space = 0,
1073f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                      StackFrame::Type frame_type = StackFrame::EXIT);
1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Leave the current exit frame.
1076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LeaveExitFrame(bool save_doubles, Register arg_count,
1077014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      bool restore_context, bool do_return = NO_EMIT_RETURN,
1078014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      bool argument_count_is_length = false);
1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the actual activation frame alignment for target environment.
1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static int ActivationFrameAlignment();
1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Make sure the stack is aligned. Only emits code in debug mode.
1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AssertStackIsAligned();
1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void LoadContext(Register dst, int context_chain_length);
1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load the global object from the current context.
1089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LoadGlobalObject(Register dst) {
1090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LoadNativeContextSlot(Context::EXTENSION_INDEX, dst);
1091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load the global proxy from the current context.
1094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LoadGlobalProxy(Register dst) {
1095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LoadNativeContextSlot(Context::GLOBAL_PROXY_INDEX, dst);
1096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Conditionally load the cached Array transitioned map of type
1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // transitioned_kind from the native context if the map in register
1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // map_in_out is the cached Array map in the native context of
1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // expected_kind.
1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void LoadTransitionedArrayMapConditional(
1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ElementsKind expected_kind,
1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ElementsKind transitioned_kind,
1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register map_in_out,
1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register scratch,
1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label* no_map_match);
1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LoadNativeContextSlot(int index, Register dst);
1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the initial map from the global function. The registers
1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // function and map can be the same, function is then overwritten.
1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void LoadGlobalFunctionInitialMap(Register function,
1114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    Register map,
1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    Register scratch);
1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void InitializeRootRegister() {
1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExternalReference roots_array_start =
1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ExternalReference::roots_array_start(isolate());
1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    li(kRootRegister, Operand(roots_array_start));
1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -------------------------------------------------------------------------
1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // JavaScript invokes.
1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
11263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Removes current frame and its arguments from the stack preserving
11273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // the arguments and a return address pushed to the stack for the next call.
11283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Both |callee_args_count| and |caller_args_count_reg| do not include
11293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // receiver. |callee_args_count| is not modified, |caller_args_count_reg|
11303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // is trashed.
11313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void PrepareForTailCall(const ParameterCount& callee_args_count,
11323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                          Register caller_args_count_reg, Register scratch0,
11333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                          Register scratch1);
11343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Invoke the JavaScript function code by either calling or jumping.
1136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void InvokeFunctionCode(Register function, Register new_target,
1137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                          const ParameterCount& expected,
1138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                          const ParameterCount& actual, InvokeFlag flag,
1139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                          const CallWrapper& call_wrapper);
1140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void FloodFunctionIfStepping(Register fun, Register new_target,
1142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               const ParameterCount& expected,
1143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               const ParameterCount& actual);
1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Invoke the JavaScript function in the given register. Changes the
1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // current context to the context in the function before invoking.
1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void InvokeFunction(Register function,
1148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      Register new_target,
1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const ParameterCount& actual,
1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      InvokeFlag flag,
1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const CallWrapper& call_wrapper);
1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void InvokeFunction(Register function,
1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const ParameterCount& expected,
1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const ParameterCount& actual,
1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      InvokeFlag flag,
1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const CallWrapper& call_wrapper);
1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void InvokeFunction(Handle<JSFunction> function,
1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const ParameterCount& expected,
1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const ParameterCount& actual,
1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      InvokeFlag flag,
1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const CallWrapper& call_wrapper);
1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void IsObjectJSStringType(Register object,
1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Register scratch,
1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Label* fail);
1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void IsObjectNameType(Register object,
1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        Register scratch,
1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        Label* fail);
1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -------------------------------------------------------------------------
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Debugger Support.
1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DebugBreak();
1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -------------------------------------------------------------------------
1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Exception handling.
1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Push a new stack handler and link into stack handler chain.
1183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void PushStackHandler();
1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Unlink the stack handler on top of the stack from the stack handler chain.
1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Must preserve the result register.
1187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void PopStackHandler();
1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Initialize fields with filler values.  Fields starting at |current_address|
1190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // not including |end_address| are overwritten with the value in |filler|.  At
1191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // the end the loop, |current_address| takes the value of |end_address|.
1192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void InitializeFieldsWithFiller(Register current_address,
1193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  Register end_address, Register filler);
1194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -------------------------------------------------------------------------
1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Support functions.
1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Machine code version of Map::GetConstructor().
1199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // |temp| holds |result|'s map when done, and |temp2| its instance type.
1200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void GetMapConstructor(Register result, Register map, Register temp,
1201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         Register temp2);
1202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Try to get function prototype of a function and puts the value in
1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the result register. Checks that the function really is a
1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // function and jumps to the miss label if the fast checks fail. The
1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // function register will be untouched; the other registers may be
1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // clobbered.
1208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void TryGetFunctionPrototype(Register function, Register result,
1209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               Register scratch, Label* miss);
1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void GetObjectType(Register function,
1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     Register map,
1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     Register type_reg);
1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1215109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void GetInstanceType(Register object_map, Register object_instance_type) {
1216109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    lbu(object_instance_type,
1217109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        FieldMemOperand(object_map, Map::kInstanceTypeOffset));
1218109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
1219109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if a map for a JSObject indicates that the object can have both smi
1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // and HeapObject elements.  Jump to the specified label if it does not.
1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CheckFastObjectElements(Register map,
1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register scratch,
1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* fail);
1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if a map for a JSObject indicates that the object has fast smi only
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // elements.  Jump to the specified label if it does not.
1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CheckFastSmiElements(Register map,
1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Register scratch,
1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Label* fail);
1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check to see if maybe_number can be stored as a double in
1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // FastDoubleElements. If it can, store it at the index specified by key in
1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the FastDoubleElements array elements. Otherwise jump to fail.
1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void StoreNumberToDoubleElements(Register value_reg,
1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register key_reg,
1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register elements_reg,
1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register scratch1,
1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register scratch2,
1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Label* fail,
1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   int elements_offset = 0);
1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compare an object's map with the specified map and its transitioned
1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Jumps to
1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // "branch_to" if the result of the comparison is "cond". If multiple map
1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // compares are required, the compare sequences branches to early_success.
1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CompareMapAndBranch(Register obj,
1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Register scratch,
1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Handle<Map> map,
1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Label* early_success,
1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Condition cond,
1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Label* branch_to);
1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // As above, but the map of the object is already loaded into the register
1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // which is preserved by the code generated.
1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CompareMapAndBranch(Register obj_map,
1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Handle<Map> map,
1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Label* early_success,
1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Condition cond,
1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Label* branch_to);
1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if the map of an object is equal to a specified map and branch to
1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // label if not. Skip the smi check if not required (object is known to be a
1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // against maps that are ElementsKind transition maps of the specificed map.
1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CheckMap(Register obj,
1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register scratch,
1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Handle<Map> map,
1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Label* fail,
1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                SmiCheckType smi_check_type);
1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CheckMap(Register obj,
1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register scratch,
1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Heap::RootListIndex index,
1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Label* fail,
1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                SmiCheckType smi_check_type);
1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check if the map of an object is equal to a specified weak map and branch
1280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // to a specified target if equal. Skip the smi check if not required
1281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // (object is known to be a heap object)
1282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DispatchWeakMap(Register obj, Register scratch1, Register scratch2,
1283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       Handle<WeakCell> cell, Handle<Code> success,
1284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       SmiCheckType smi_check_type);
1285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // If the value is a NaN, canonicalize the value else, do nothing.
1287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void FPUCanonicalizeNaN(const DoubleRegister dst, const DoubleRegister src);
1288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Get value of the weak cell.
1291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void GetWeakValue(Register value, Handle<WeakCell> cell);
1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Load the value of the weak cell in the value register. Branch to the
1294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // given miss label is the weak cell was cleared.
1295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void LoadWeakValue(Register value, Handle<WeakCell> cell, Label* miss);
1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load and check the instance type of an object for being a string.
1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loads the type into the second argument register.
1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Returns a condition that will be enabled if the object was a string.
1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition IsObjectStringType(Register obj,
1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register type,
1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register result) {
1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ld(type, FieldMemOperand(obj, HeapObject::kMapOffset));
1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    lbu(type, FieldMemOperand(type, Map::kInstanceTypeOffset));
1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    And(type, type, Operand(kIsNotStringMask));
1306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_EQ(0u, kStringTag);
1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return eq;
1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the number of least significant bits from a register.
1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits);
1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits);
1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the value of a number object into a FPU double register. If the
1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // object is not a number a jump to the label not_number is performed
1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // and the FPU double register is unchanged.
1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ObjectToDoubleFPURegister(
1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register object,
1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FPURegister value,
1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register scratch1,
1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register scratch2,
1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register heap_number_map,
1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label* not_number,
1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ObjectToDoubleFlags flags = NO_OBJECT_TO_DOUBLE_FLAGS);
1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the value of a smi object into a FPU double register. The register
1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // scratch1 can be the same register as smi in which case smi will hold the
1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // untagged value afterwards.
1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SmiToDoubleFPURegister(Register smi,
1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              FPURegister value,
1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register scratch1);
1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -------------------------------------------------------------------------
1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Overflow handling functions.
1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Usage: first call the appropriate arithmetic function, then call one of the
1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // jump functions with the overflow_dst register as the second parameter.
1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline void AddBranchOvf(Register dst, Register left, const Operand& right,
13393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                           Label* overflow_label, Register scratch = at) {
13403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    AddBranchOvf(dst, left, right, overflow_label, nullptr, scratch);
13413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
13423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
13433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline void AddBranchNoOvf(Register dst, Register left, const Operand& right,
13443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                             Label* no_overflow_label, Register scratch = at) {
13453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    AddBranchOvf(dst, left, right, nullptr, no_overflow_label, scratch);
13463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void AddBranchOvf(Register dst, Register left, const Operand& right,
13493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                    Label* overflow_label, Label* no_overflow_label,
13503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                    Register scratch = at);
1351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
13523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void AddBranchOvf(Register dst, Register left, Register right,
13533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                    Label* overflow_label, Label* no_overflow_label,
13543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                    Register scratch = at);
1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
13563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline void SubBranchOvf(Register dst, Register left, const Operand& right,
13573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                           Label* overflow_label, Register scratch = at) {
13583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    SubBranchOvf(dst, left, right, overflow_label, nullptr, scratch);
13593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
1360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
13613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline void SubBranchNoOvf(Register dst, Register left, const Operand& right,
13623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                             Label* no_overflow_label, Register scratch = at) {
13633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    SubBranchOvf(dst, left, right, nullptr, no_overflow_label, scratch);
13643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
1365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
13663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void SubBranchOvf(Register dst, Register left, const Operand& right,
13673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                    Label* overflow_label, Label* no_overflow_label,
13683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                    Register scratch = at);
13693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
13703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void SubBranchOvf(Register dst, Register left, Register right,
13713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                    Label* overflow_label, Label* no_overflow_label,
13723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                    Register scratch = at);
1373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1374f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  inline void MulBranchOvf(Register dst, Register left, const Operand& right,
1375f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                           Label* overflow_label, Register scratch = at) {
1376f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    MulBranchOvf(dst, left, right, overflow_label, nullptr, scratch);
1377f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1378f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1379f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  inline void MulBranchNoOvf(Register dst, Register left, const Operand& right,
1380f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                             Label* no_overflow_label, Register scratch = at) {
1381f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    MulBranchOvf(dst, left, right, nullptr, no_overflow_label, scratch);
1382f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1383f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1384f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void MulBranchOvf(Register dst, Register left, const Operand& right,
1385f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                    Label* overflow_label, Label* no_overflow_label,
1386f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                    Register scratch = at);
1387f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1388f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void MulBranchOvf(Register dst, Register left, Register right,
1389f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                    Label* overflow_label, Label* no_overflow_label,
1390f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                    Register scratch = at);
1391f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void DaddBranchOvf(Register dst, Register left, const Operand& right,
1393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                            Label* overflow_label, Register scratch = at) {
1394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DaddBranchOvf(dst, left, right, overflow_label, nullptr, scratch);
1395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void DaddBranchNoOvf(Register dst, Register left, const Operand& right,
1398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              Label* no_overflow_label, Register scratch = at) {
1399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DaddBranchOvf(dst, left, right, nullptr, no_overflow_label, scratch);
1400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void DaddBranchOvf(Register dst, Register left, const Operand& right,
1403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     Label* overflow_label, Label* no_overflow_label,
1404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     Register scratch = at);
1405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void DaddBranchOvf(Register dst, Register left, Register right,
1407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     Label* overflow_label, Label* no_overflow_label,
1408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     Register scratch = at);
1409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void DsubBranchOvf(Register dst, Register left, const Operand& right,
1411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                            Label* overflow_label, Register scratch = at) {
1412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DsubBranchOvf(dst, left, right, overflow_label, nullptr, scratch);
1413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void DsubBranchNoOvf(Register dst, Register left, const Operand& right,
1416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              Label* no_overflow_label, Register scratch = at) {
1417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DsubBranchOvf(dst, left, right, nullptr, no_overflow_label, scratch);
1418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void DsubBranchOvf(Register dst, Register left, const Operand& right,
1421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     Label* overflow_label, Label* no_overflow_label,
1422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     Register scratch = at);
1423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void DsubBranchOvf(Register dst, Register left, Register right,
1425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     Label* overflow_label, Label* no_overflow_label,
1426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     Register scratch = at);
1427958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void BranchOnOverflow(Label* label,
1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        Register overflow_check,
1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        BranchDelaySlot bd = PROTECT) {
1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Branch(label, lt, overflow_check, Operand(zero_reg), bd);
1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void BranchOnNoOverflow(Label* label,
1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          Register overflow_check,
1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          BranchDelaySlot bd = PROTECT) {
1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Branch(label, ge, overflow_check, Operand(zero_reg), bd);
1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RetOnOverflow(Register overflow_check, BranchDelaySlot bd = PROTECT) {
1441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Ret(lt, overflow_check, Operand(zero_reg), bd);
1442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RetOnNoOverflow(Register overflow_check, BranchDelaySlot bd = PROTECT) {
1445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Ret(ge, overflow_check, Operand(zero_reg), bd);
1446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -------------------------------------------------------------------------
1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Runtime calls.
1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // See comments at the beginning of CEntryStub::Generate.
1452958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  inline void PrepareCEntryArgs(int num_args) { li(a0, num_args); }
1453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void PrepareCEntryFunction(const ExternalReference& ref) {
1455958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    li(a1, Operand(ref));
1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define COND_ARGS Condition cond = al, Register rs = zero_reg, \
1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Call a code stub.
1462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CallStub(CodeStub* stub,
1463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                TypeFeedbackId ast_id = TypeFeedbackId::None(),
1464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                COND_ARGS);
1465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Tail call a code stub (jump).
1467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TailCallStub(CodeStub* stub, COND_ARGS);
1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef COND_ARGS
1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CallJSExitStub(CodeStub* stub);
1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Call a runtime routine.
1474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void CallRuntime(const Runtime::Function* f, int num_arguments,
1475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   SaveFPRegsMode save_doubles = kDontSaveFPRegs,
1476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   BranchDelaySlot bd = PROTECT);
1477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void CallRuntimeSaveDoubles(Runtime::FunctionId fid) {
1478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    const Runtime::Function* function = Runtime::FunctionForId(fid);
1479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallRuntime(function, function->nargs, kSaveFPRegs);
1480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Convenience function: Same as above, but takes the fid instead.
1483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void CallRuntime(Runtime::FunctionId fid,
1484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   SaveFPRegsMode save_doubles = kDontSaveFPRegs,
1485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   BranchDelaySlot bd = PROTECT) {
1486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    const Runtime::Function* function = Runtime::FunctionForId(fid);
1487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallRuntime(function, function->nargs, save_doubles, bd);
1488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Convenience function: Same as above, but takes the fid instead.
1491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void CallRuntime(Runtime::FunctionId fid, int num_arguments,
1492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   SaveFPRegsMode save_doubles = kDontSaveFPRegs,
1493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   BranchDelaySlot bd = PROTECT) {
1494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallRuntime(Runtime::FunctionForId(fid), num_arguments, save_doubles, bd);
1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Convenience function: call an external reference.
1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CallExternalReference(const ExternalReference& ext,
1499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             int num_arguments,
1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             BranchDelaySlot bd = PROTECT);
1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Convenience function: tail call a runtime routine (jump).
1503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void TailCallRuntime(Runtime::FunctionId fid);
1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int CalculateStackPassedWords(int num_reg_arguments,
1506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                int num_double_arguments);
1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Before calling a C-function from generated code, align arguments on stack
1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // and add space for the four mips argument slots.
1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // After aligning the frame, non-register arguments must be stored on the
1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // stack, after the argument-slots using helper: CFunctionArgumentOperand().
1512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The argument count assumes all arguments are word sized.
1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Some compilers/platforms require the stack to be aligned when calling
1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // C++ code.
1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Needs a scratch register to do some arithmetic. This register will be
1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // trashed.
1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void PrepareCallCFunction(int num_reg_arguments,
1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            int num_double_registers,
1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Register scratch);
1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void PrepareCallCFunction(int num_reg_arguments,
1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Register scratch);
1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Arguments 1-4 are placed in registers a0 thru a3 respectively.
1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Arguments 5..n are stored to stack using following:
1525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  sw(a4, CFunctionArgumentOperand(5));
1526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calls a C function and cleans up the space for arguments allocated
1528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // by PrepareCallCFunction. The called function is not allowed to trigger a
1529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // garbage collection, since that might move the code and invalidate the
1530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // return address (unless this is somehow accounted for by the called
1531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // function).
1532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CallCFunction(ExternalReference function, int num_arguments);
1533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CallCFunction(Register function, int num_arguments);
1534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CallCFunction(ExternalReference function,
1535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     int num_reg_arguments,
1536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     int num_double_arguments);
1537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CallCFunction(Register function,
1538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     int num_reg_arguments,
1539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     int num_double_arguments);
1540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MovFromFloatResult(DoubleRegister dst);
1541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MovFromFloatParameter(DoubleRegister dst);
1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // There are two ways of passing double arguments on MIPS, depending on
1544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // whether soft or hard floating point ABI is used. These functions
1545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // abstract parameter passing for the three different ways we call
1546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // C functions from generated code.
1547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MovToFloatParameter(DoubleRegister src);
1548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MovToFloatParameters(DoubleRegister src1, DoubleRegister src2);
1549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MovToFloatResult(DoubleRegister src);
1550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Jump to the builtin routine.
1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpToExternalReference(const ExternalReference& builtin,
1553f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                               BranchDelaySlot bd = PROTECT,
1554f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                               bool builtin_exit_frame = false);
1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  struct Unresolved {
1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int pc;
1558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t flags;  // See Bootstrapper::FixupFlags decoders/encoders.
1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const char* name;
1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Object> CodeObject() {
1563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!code_object_.is_null());
1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return code_object_;
1565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Emit code for a truncating division by a constant. The dividend register is
1568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // unchanged and at gets clobbered. Dividend and result must be different.
1569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TruncatingDiv(Register result, Register dividend, int32_t divisor);
1570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -------------------------------------------------------------------------
1572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // StatsCounter support.
1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SetCounter(StatsCounter* counter, int value,
1575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Register scratch1, Register scratch2);
1576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void IncrementCounter(StatsCounter* counter, int value,
1577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        Register scratch1, Register scratch2);
1578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DecrementCounter(StatsCounter* counter, int value,
1579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        Register scratch1, Register scratch2);
1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -------------------------------------------------------------------------
1583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Debugging.
1584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calls Abort(msg) if the condition cc is not satisfied.
1586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Use --debug_code to enable.
1587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Assert(Condition cc, BailoutReason reason, Register rs, Operand rt);
1588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AssertFastElements(Register elements);
1589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Like Assert(), but always enabled.
1591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Check(Condition cc, BailoutReason reason, Register rs, Operand rt);
1592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Print a message to stdout and abort execution.
1594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Abort(BailoutReason msg);
1595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Verify restrictions about code generated in stubs.
1597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void set_generating_stub(bool value) { generating_stub_ = value; }
1598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool generating_stub() { return generating_stub_; }
1599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void set_has_frame(bool value) { has_frame_ = value; }
1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool has_frame() { return has_frame_; }
1601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline bool AllowThisStubCall(CodeStub* stub);
1602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ---------------------------------------------------------------------------
1604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Number utilities.
1605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check whether the value of reg is a power of two and not zero. If not
1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // control continues at the label not_power_of_two. If reg is a power of two
1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the register scratch contains the value of (reg - 1) when control falls
1609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // through.
1610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfNotPowerOfTwoOrZero(Register reg,
1611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register scratch,
1612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Label* not_power_of_two_or_zero);
1613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -------------------------------------------------------------------------
1615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Smi utilities.
1616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test for overflow < 0: use BranchOnOverflow() or BranchOnNoOverflow().
1618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SmiTagCheckOverflow(Register reg, Register overflow);
1619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SmiTagCheckOverflow(Register dst, Register src, Register overflow);
1620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SmiTag(Register dst, Register src) {
1622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (SmiValuesAre32Bits()) {
1624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      STATIC_ASSERT(kSmiShift == 32);
1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      dsll32(dst, src, 0);
1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Addu(dst, src, src);
1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SmiTag(Register reg) {
1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiTag(reg, reg);
1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Try to convert int32 to smi. If the value is to large, preserve
1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the original value and jump to not_a_smi. Destroys scratch and
1637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // sets flags.
1638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TrySmiTag(Register reg, Register scratch, Label* not_a_smi) {
1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TrySmiTag(reg, reg, scratch, not_a_smi);
1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TrySmiTag(Register dst,
1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 Register src,
1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 Register scratch,
1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 Label* not_a_smi) {
1646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (SmiValuesAre32Bits()) {
1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SmiTag(dst, src);
1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SmiTagCheckOverflow(at, src, scratch);
1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      BranchOnOverflow(not_a_smi, scratch);
1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mov(dst, at);
1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SmiUntag(Register dst, Register src) {
1656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (SmiValuesAre32Bits()) {
1657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      STATIC_ASSERT(kSmiShift == 32);
1658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      dsra32(dst, src, 0);
1659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sra(dst, src, kSmiTagSize);
1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SmiUntag(Register reg) {
1665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiUntag(reg, reg);
1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Left-shifted from int32 equivalent of Smi.
1669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SmiScale(Register dst, Register src, int scale) {
1670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (SmiValuesAre32Bits()) {
1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // The int portion is upper 32-bits of 64-bit word.
1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      dsra(dst, src, kSmiShift - scale);
1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(scale >= kSmiTagSize);
1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sll(dst, src, scale - kSmiTagSize);
1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Combine load with untagging or scaling.
1680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SmiLoadUntag(Register dst, MemOperand src);
1681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SmiLoadScale(Register dst, MemOperand src, int scale);
1683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Returns 2 values: the Smi and a scaled version of the int within the Smi.
1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SmiLoadWithScale(Register d_smi,
1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        Register d_scaled,
1687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        MemOperand src,
1688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        int scale);
1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Returns 2 values: the untagged Smi (int32) and scaled version of that int.
1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SmiLoadUntagWithScale(Register d_int,
1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             Register d_scaled,
1693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             MemOperand src,
1694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             int scale);
1695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test if the register contains a smi.
1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void SmiTst(Register value, Register scratch) {
1699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    And(scratch, value, Operand(kSmiTagMask));
1700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void NonNegativeSmiTst(Register value, Register scratch) {
1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    And(scratch, value, Operand(kSmiTagMask | kSmiSignMask));
1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Untag the source value into destination and jump if source is a smi.
1706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Source and destination can be the same register.
1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case);
1708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Untag the source value into destination and jump if source is not a smi.
1710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Source and destination can be the same register.
1711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case);
1712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Jump the register contains a smi.
1714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfSmi(Register value,
1715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 Label* smi_label,
1716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 Register scratch = at,
1717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 BranchDelaySlot bd = PROTECT);
1718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Jump if the register contains a non-smi.
1720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfNotSmi(Register value,
1721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    Label* not_smi_label,
1722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    Register scratch = at,
1723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    BranchDelaySlot bd = PROTECT);
1724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Jump if either of the registers contain a non-smi.
1726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi);
1727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Jump if either of the registers contain a smi.
1728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi);
1729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Abort execution if argument is a number, enabled via --debug-code.
17313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void AssertNotNumber(Register object);
17323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Abort execution if argument is a smi, enabled via --debug-code.
1734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AssertNotSmi(Register object);
1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AssertSmi(Register object);
1736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Abort execution if argument is not a string, enabled via --debug-code.
1738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AssertString(Register object);
1739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Abort execution if argument is not a name, enabled via --debug-code.
1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AssertName(Register object);
1742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1743014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Abort execution if argument is not a JSFunction, enabled via --debug-code.
1744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void AssertFunction(Register object);
1745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1746014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Abort execution if argument is not a JSBoundFunction,
1747014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // enabled via --debug-code.
1748014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void AssertBoundFunction(Register object);
1749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1750bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Abort execution if argument is not a JSGeneratorObject,
1751bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // enabled via --debug-code.
1752bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void AssertGeneratorObject(Register object);
1753bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1754109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Abort execution if argument is not a JSReceiver, enabled via --debug-code.
1755109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void AssertReceiver(Register object);
1756109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Abort execution if argument is not undefined or an AllocationSite, enabled
1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // via --debug-code.
1759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AssertUndefinedOrAllocationSite(Register object, Register scratch);
1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Abort execution if reg is not the root value with the given index,
1762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // enabled via --debug-code.
1763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AssertIsRoot(Register reg, Heap::RootListIndex index);
1764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ---------------------------------------------------------------------------
1766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // HeapNumber utilities.
1767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfNotHeapNumber(Register object,
1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Register heap_number_map,
1770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Register scratch,
1771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Label* on_not_heap_number);
1772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -------------------------------------------------------------------------
1774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // String utilities.
1775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Checks if both instance types are sequential one-byte strings and jumps to
1777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // label if either is not.
1778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfBothInstanceTypesAreNotSequentialOneByte(
1779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register first_object_instance_type, Register second_object_instance_type,
1780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register scratch1, Register scratch2, Label* failure);
1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if instance type is sequential one-byte string and jump to label if
1783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // it is not.
1784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfInstanceTypeIsNotSequentialOneByte(Register type, Register scratch,
1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                Label* failure);
1786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfNotUniqueNameInstanceType(Register reg, Label* not_unique_name);
1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmitSeqStringSetCharCheck(Register string,
1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register index,
1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register value,
1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register scratch,
1793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 uint32_t encoding_mask);
1794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Checks if both objects are sequential one-byte strings and jumps to label
1796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // if either is not. Assumes that neither object is a smi.
1797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfNonSmisNotBothSequentialOneByteStrings(Register first,
1798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                    Register second,
1799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                    Register scratch1,
1800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                    Register scratch2,
1801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                    Label* failure);
1802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Checks if both objects are sequential one-byte strings and jumps to label
1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // if either is not.
1805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfNotBothSequentialOneByteStrings(Register first, Register second,
1806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             Register scratch1,
1807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             Register scratch2,
1808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             Label* not_flat_one_byte_strings);
1809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ClampUint8(Register output_reg, Register input_reg);
1811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ClampDoubleToUint8(Register result_reg,
1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          DoubleRegister input_reg,
1814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          DoubleRegister temp_double_reg);
1815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void LoadInstanceDescriptors(Register map, Register descriptors);
1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EnumLength(Register dst, Register map);
1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void NumberOfOwnDescriptors(Register dst, Register map);
1820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LoadAccessor(Register dst, Register holder, int accessor_index,
1821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    AccessorComponent accessor);
1822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<typename Field>
1824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DecodeField(Register dst, Register src) {
1825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Ext(dst, src, Field::kShift, Field::kSize);
1826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<typename Field>
1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DecodeField(Register reg) {
1830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DecodeField<Field>(reg, reg);
1831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<typename Field>
1834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DecodeFieldToSmi(Register dst, Register src) {
1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static const int shift = Field::kShift;
1836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static const int mask = Field::kMask >> shift;
1837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    dsrl(dst, src, shift);
1838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    And(dst, dst, Operand(mask));
1839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    dsll32(dst, dst, 0);
1840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<typename Field>
1843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DecodeFieldToSmi(Register reg) {
1844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DecodeField<Field>(reg, reg);
1845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Generates function and stub prologue code.
18473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void StubPrologue(StackFrame::Type type);
1848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Prologue(bool code_pre_aging);
1849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1850014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load the type feedback vector from a JavaScript frame.
1851014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void EmitLoadTypeFeedbackVector(Register vector);
1852014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Activation support.
1854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EnterFrame(StackFrame::Type type);
1855958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg);
1856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void LeaveFrame(StackFrame::Type type);
1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1858f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void EnterBuiltinFrame(Register context, Register target, Register argc);
1859f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void LeaveBuiltinFrame(Register context, Register target, Register argc);
1860f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Expects object in a0 and returns map with validated enum cache
1862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // in a0.  Assumes that any other register can be used as a scratch.
1863109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void CheckEnumCache(Label* call_runtime);
1864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // AllocationMemento support. Arrays may have an associated AllocationMemento
18663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // object that can be checked for in order to pretransition to another type.
18673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // On entry, receiver_reg should point to the array object. scratch_reg gets
18683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // clobbered. If no info is present jump to no_memento_found, otherwise fall
18693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // through.
18703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void TestJSArrayForAllocationMemento(Register receiver_reg,
18713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                       Register scratch_reg,
18723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                       Label* no_memento_found);
1873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfJSArrayHasAllocationMemento(Register receiver_reg,
1875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Register scratch_reg,
1876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Label* memento_found) {
1877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label no_memento_found;
1878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TestJSArrayForAllocationMemento(receiver_reg, scratch_reg,
18793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                    &no_memento_found);
18803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Branch(memento_found);
1881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&no_memento_found);
1882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Jumps to found label if a prototype map has dictionary elements.
1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfDictionaryInPrototypeChain(Register object, Register scratch0,
1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Register scratch1, Label* found);
1887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool IsDoubleZeroRegSet() { return has_double_zero_reg_set_; }
1889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
1891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CallCFunctionHelper(Register function,
1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           int num_reg_arguments,
1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           int num_double_arguments);
1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline Register GetRtAsRegisterHelper(const Operand& rt, Register scratch);
1896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline int32_t GetOffset(int32_t offset, Label* L, OffsetSize bits);
1897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BranchShortHelperR6(int32_t offset, Label* L);
1898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BranchShortHelper(int16_t offset, Label* L, BranchDelaySlot bdslot);
1899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool BranchShortHelperR6(int32_t offset, Label* L, Condition cond,
1900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                           Register rs, const Operand& rt);
1901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool BranchShortHelper(int16_t offset, Label* L, Condition cond, Register rs,
1902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         const Operand& rt, BranchDelaySlot bdslot);
1903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool BranchShortCheck(int32_t offset, Label* L, Condition cond, Register rs,
1904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        const Operand& rt, BranchDelaySlot bdslot);
1905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BranchAndLinkShortHelperR6(int32_t offset, Label* L);
1907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BranchAndLinkShortHelper(int16_t offset, Label* L,
1908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                BranchDelaySlot bdslot);
1909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BranchAndLinkShort(int32_t offset, BranchDelaySlot bdslot = PROTECT);
1910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void BranchAndLinkShort(Label* L, BranchDelaySlot bdslot = PROTECT);
1911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool BranchAndLinkShortHelperR6(int32_t offset, Label* L, Condition cond,
1912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  Register rs, const Operand& rt);
1913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool BranchAndLinkShortHelper(int16_t offset, Label* L, Condition cond,
1914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                Register rs, const Operand& rt,
1915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                BranchDelaySlot bdslot);
1916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool BranchAndLinkShortCheck(int32_t offset, Label* L, Condition cond,
1917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               Register rs, const Operand& rt,
1918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               BranchDelaySlot bdslot);
1919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BranchLong(Label* L, BranchDelaySlot bdslot);
1920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BranchAndLinkLong(Label* L, BranchDelaySlot bdslot);
1921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Common implementation of BranchF functions for the different formats.
1923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BranchFCommon(SecondaryField sizeField, Label* target, Label* nan,
1924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     Condition cc, FPURegister cmp1, FPURegister cmp2,
1925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     BranchDelaySlot bd = PROTECT);
1926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BranchShortF(SecondaryField sizeField, Label* target, Condition cc,
1928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    FPURegister cmp1, FPURegister cmp2,
1929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    BranchDelaySlot bd = PROTECT);
1930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Helper functions for generating invokes.
1933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void InvokePrologue(const ParameterCount& expected,
1934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const ParameterCount& actual,
1935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      Label* done,
1936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      bool* definitely_mismatches,
1937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      InvokeFlag flag,
1938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const CallWrapper& call_wrapper);
1939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void InitializeNewString(Register string,
1941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Register length,
1942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Heap::RootListIndex map_index,
1943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Register scratch1,
1944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Register scratch2);
1945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
1947109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void InNewSpace(Register object, Register scratch,
1948109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                  Condition cond,  // ne for new space, eq otherwise.
1949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Label* branch);
1950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Helper for finding the mark bits for an address.  Afterwards, the
1952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // bitmap register points at the word with the mark bits and the mask
1953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the position of the first bit.  Leaves addr_reg unchanged.
1954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void GetMarkBits(Register addr_reg,
1955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          Register bitmap_reg,
1956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          Register mask_reg);
1957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compute memory operands for safepoint stack slots.
1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static int SafepointRegisterStackIndex(int reg_code);
1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemOperand SafepointRegisterSlot(Register reg);
1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemOperand SafepointRegistersAndDoublesSlot(Register reg);
1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool generating_stub_;
1964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool has_frame_;
1965958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool has_double_zero_reg_set_;
1966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This handle will be patched with the code object on installation.
1967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Object> code_object_;
1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Needs access to SafepointRegisterStackIndex for compiled frame
1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // traversal.
1971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class StandardFrame;
1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The code patcher is used to patch (typically) small parts of code e.g. for
1976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// debugging and other types of instrumentation. When using the code patcher
1977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the exact number of bytes specified must be emitted. It is not legal to emit
1978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// relocation information. If any of these constraints are violated it causes
1979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// an assertion to fail.
1980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass CodePatcher {
1981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum FlushICache {
1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FLUSH,
1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DONT_FLUSH
1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
1986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CodePatcher(Isolate* isolate, byte* address, int instructions,
1988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              FlushICache flush_cache = FLUSH);
1989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ~CodePatcher();
1990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Macro assembler to emit code.
1992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MacroAssembler* masm() { return &masm_; }
1993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Emit an instruction directly.
1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Emit(Instr instr);
1996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Emit an address directly.
1998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Emit(Address addr);
1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Change the condition part of an instruction leaving the rest of the current
2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // instruction unchanged.
2002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void ChangeBranchCondition(Instr current_instr, uint32_t new_opcode);
2003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
2005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  byte* address_;  // The address of the code being patched.
2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size_;  // Number of bytes of the expected patch size.
2007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MacroAssembler masm_;  // Macro assembler used to generate the code.
2008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FlushICache flush_cache_;  // Whether to flush the I cache after patching.
2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2011109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochtemplate <typename Func>
2012109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid MacroAssembler::GenerateSwitchTable(Register index, size_t case_count,
2013109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                         Func GetLabelFunction) {
2014109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Ensure that dd-ed labels following this instruction use 8 bytes aligned
2015109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // addresses.
2016109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (kArchVariant >= kMips64r6) {
2017109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    BlockTrampolinePoolFor(static_cast<int>(case_count) * 2 + 6);
2018109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Opposite of Align(8) as we have odd number of instructions in this case.
2019109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if ((pc_offset() & 7) == 0) {
2020109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      nop();
2021109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
2022109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    addiupc(at, 5);
20233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Dlsa(at, at, index, kPointerSizeLog2);
2024109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    ld(at, MemOperand(at));
2025109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
2026109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Label here;
20273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    BlockTrampolinePoolFor(static_cast<int>(case_count) * 2 + 11);
2028109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Align(8);
20293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    push(ra);
2030109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    bal(&here);
2031109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    dsll(at, index, kPointerSizeLog2);  // Branch delay slot.
2032109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    bind(&here);
2033109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    daddu(at, at, ra);
20343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    pop(ra);
20353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    ld(at, MemOperand(at, 6 * v8::internal::Assembler::kInstrSize));
2036109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
2037109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  jr(at);
2038109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  nop();  // Branch delay slot nop.
2039109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  for (size_t index = 0; index < case_count; ++index) {
2040109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    dd(GetLabelFunction(index));
2041109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
2042109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ACCESS_MASM(masm) masm->
2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
2047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_MIPS_MACRO_ASSEMBLER_MIPS_H_
2050