13ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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.
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_ARM_MACRO_ASSEMBLER_ARM_H_
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/assembler.h"
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/bailout-reason.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/frames.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/globals.h"
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Give alias names to registers for calling conventions.
17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kReturnRegister0 = {Register::kCode_r0};
18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kReturnRegister1 = {Register::kCode_r1};
19109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochconst Register kReturnRegister2 = {Register::kCode_r2};
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kJSFunctionRegister = {Register::kCode_r1};
21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kContextRegister = {Register::kCode_r7};
22bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochconst Register kAllocateSizeRegister = {Register::kCode_r1};
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kInterpreterAccumulatorRegister = {Register::kCode_r0};
24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kInterpreterBytecodeOffsetRegister = {Register::kCode_r5};
25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kInterpreterBytecodeArrayRegister = {Register::kCode_r6};
26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kInterpreterDispatchTableRegister = {Register::kCode_r8};
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kJavaScriptCallArgCountRegister = {Register::kCode_r0};
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kJavaScriptCallNewTargetRegister = {Register::kCode_r3};
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kRuntimeCallFunctionRegister = {Register::kCode_r1};
30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kRuntimeCallArgCountRegister = {Register::kCode_r0};
31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// ----------------------------------------------------------------------------
333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Static helper functions
343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Generate a MemOperand for loading a field from an object.
363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline MemOperand FieldMemOperand(Register object, int offset) {
373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  return MemOperand(object, offset - kHeapObjectTag);
383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Give alias names to registers
42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register cp = {Register::kCode_r7};  // JavaScript context pointer.
43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register pp = {Register::kCode_r8};  // Constant pool pointer.
44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Register kRootRegister = {Register::kCode_r10};  // Roots array pointer.
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Flags used for AllocateHeapNumber
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum TaggingMode {
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Tag the result.
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TAG_RESULT,
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Don't tag
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DONT_TAG_RESULT
528defd9ff6930b4e24729971a61cf7469daf119beSteve Block};
538defd9ff6930b4e24729971a61cf7469daf119beSteve Block
548defd9ff6930b4e24729971a61cf7469daf119beSteve Block
553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum PointersToHereCheck {
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  kPointersToHereMaybeInteresting,
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  kPointersToHereAreAlwaysInteresting
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochenum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved };
623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister GetRegisterThatIsNotOneOf(Register reg1,
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register reg2 = no_reg,
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register reg3 = no_reg,
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register reg4 = no_reg,
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register reg5 = no_reg,
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register reg6 = no_reg);
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool AreAliased(Register reg1,
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg2,
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg3 = no_reg,
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg4 = no_reg,
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg5 = no_reg,
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg6 = no_reg,
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg7 = no_reg,
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register reg8 = no_reg);
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum TargetAddressStorageMode {
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CAN_INLINE_TARGET_ADDRESS,
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NEVER_INLINE_TARGET_ADDRESS
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// MacroAssembler implements a collection of frequently used macros.
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass MacroAssembler: public Assembler {
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MacroAssembler(Isolate* isolate, void* buffer, int size,
93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 CodeObjectRequired create_code_object);
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Returns the size of a call in instructions. Note, the value returned is
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // only valid as long as no entries are added to the constant pool between
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // checking the call size and emitting the actual call.
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static int CallSize(Register target, Condition cond = al);
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int CallSize(Address target, RelocInfo::Mode rmode, Condition cond = al);
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int CallStubSize(CodeStub* stub,
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   TypeFeedbackId ast_id = TypeFeedbackId::None(),
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   Condition cond = al);
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Jump, Call, and Ret pseudo instructions implementing inter-working.
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Jump(Register target, Condition cond = al);
1073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Jump(Address target, RelocInfo::Mode rmode, Condition cond = al);
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Call(Register target, Condition cond = al);
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Call(Address target, RelocInfo::Mode rmode,
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            Condition cond = al,
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS);
11313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  void Call(Handle<Code> code, RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
11413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch            TypeFeedbackId ast_id = TypeFeedbackId::None(), Condition cond = al,
11513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch            TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS);
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int CallSize(Handle<Code> code,
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               TypeFeedbackId ast_id = TypeFeedbackId::None(),
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               Condition cond = al);
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Ret(Condition cond = al);
121e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
12213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Used for patching in calls to the deoptimizer.
12313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  void CallDeoptimizer(Address target);
12413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static int CallDeoptimizerSize();
12513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
126f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Emit code that loads |parameter_index|'th parameter from the stack to
127f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // the register according to the CallInterfaceDescriptor definition.
128f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // |sp_to_caller_sp_offset_in_words| specifies the number of words pushed
129f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // below the caller's sp.
130f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  template <class Descriptor>
131f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void LoadParameterFromStack(
132f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      Register reg, typename Descriptor::ParameterIndices parameter_index,
133f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      int sp_to_ra_offset_in_words = 0) {
134f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    DCHECK(Descriptor::kPassLastArgsOnStack);
135f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    UNIMPLEMENTED();
136f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
137f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
138e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit code to discard a non-negative number of pointer-sized elements
139e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // from the stack, clobbering only the sp register.
140e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void Drop(int count, Condition cond = al);
141109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void Drop(Register count, Condition cond = al);
142e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void Ret(int drop, Condition cond = al);
1446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Swap two registers.  If the scratch register is omitted then a slightly
1466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // less efficient form using xor instead of mov is emitted.
1477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  void Swap(Register reg1,
1487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            Register reg2,
1497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            Register scratch = no_reg,
1507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            Condition cond = al);
1516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Mls(Register dst, Register src1, Register src2, Register srcA,
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           Condition cond = al);
1549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  void And(Register dst, Register src1, const Operand& src2,
1559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen           Condition cond = al);
1569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  void Ubfx(Register dst, Register src, int lsb, int width,
1579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen            Condition cond = al);
1589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  void Sbfx(Register dst, Register src, int lsb, int width,
1599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen            Condition cond = al);
160e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // The scratch register is not used for ARMv7.
161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // scratch can be the same register as src (in which case it is trashed), but
162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // not the same as dst.
163e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void Bfi(Register dst,
164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch           Register src,
165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch           Register scratch,
166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch           int lsb,
167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch           int width,
168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch           Condition cond = al);
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Bfc(Register dst, Register src, int lsb, int width, Condition cond = al);
1709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
171e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void Call(Label* target);
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Push(Register src) { push(src); }
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Pop(Register dst) { pop(dst); }
174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Register move. May do nothing if the registers are identical.
176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Move(Register dst, Smi* smi) { mov(dst, Operand(smi)); }
177e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void Move(Register dst, Handle<Object> value);
1783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Move(Register dst, Register src, Condition cond = al);
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Move(Register dst, const Operand& src, SBit sbit = LeaveCC,
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            Condition cond = al) {
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!src.is_reg() || !src.rm().is(dst) || sbit != LeaveCC) {
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mov(dst, src, sbit, cond);
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
185f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void Move(SwVfpRegister dst, SwVfpRegister src, Condition cond = al);
186f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void Move(DwVfpRegister dst, DwVfpRegister src, Condition cond = al);
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Load(Register dst, const MemOperand& src, Representation r);
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Store(Register src, const MemOperand& dst, Representation r);
190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load an object from the root table.
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void LoadRoot(Register destination,
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                Heap::RootListIndex index,
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                Condition cond = al);
19525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // Store an object to the root table.
19625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  void StoreRoot(Register source,
19725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                 Heap::RootListIndex index,
19825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                 Condition cond = al);
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ---------------------------------------------------------------------------
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // GC Support
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void IncrementalMarkingRecordWriteHelper(Register object,
2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           Register value,
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           Register address);
2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  enum RememberedSetFinalAction {
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    kReturnAtEnd,
2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    kFallThroughAtEnd
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Record in the remembered set the fact that we have a pointer to new space
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // at the address pointed to by the addr register.  Only works if addr is not
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // in new space.
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void RememberedSetHelper(Register object,  // Used for debug code.
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Register addr,
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Register scratch,
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           SaveFPRegsMode save_fp,
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           RememberedSetFinalAction and_then);
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CheckPageFlag(Register object,
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     Register scratch,
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     int mask,
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     Condition cc,
2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     Label* condition_met);
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if object is in new space.  Jumps if the object is not in new space.
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The register scratch can be object itself, but scratch will be clobbered.
2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void JumpIfNotInNewSpace(Register object,
2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Register scratch,
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Label* branch) {
232109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    InNewSpace(object, scratch, eq, branch);
2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if object is in new space.  Jumps if the object is in new space.
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The register scratch can be object itself, but it will be clobbered.
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void JumpIfInNewSpace(Register object,
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register scratch,
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Label* branch) {
240109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    InNewSpace(object, scratch, ne, branch);
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if an object has a given incremental marking color.
2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void HasColor(Register object,
2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Register scratch0,
2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Register scratch1,
2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Label* has_color,
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                int first_bit,
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                int second_bit);
2508defd9ff6930b4e24729971a61cf7469daf119beSteve Block
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void JumpIfBlack(Register object,
2529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                   Register scratch0,
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   Register scratch1,
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   Label* on_black);
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Checks the color of an object.  If the object is white we jump to the
257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // incremental marker.
258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void JumpIfWhite(Register value, Register scratch1, Register scratch2,
259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   Register scratch3, Label* value_is_white);
2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Notify the garbage collector that we wrote a pointer into an object.
2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // |object| is the object being stored into, |value| is the object being
2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // stored.  value and scratch registers are clobbered by the operation.
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The offset is the offset from the start of the object, not the offset from
265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // the tagged HeapObject pointer.  For use with FieldMemOperand(reg, off).
2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void RecordWriteField(
2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register object,
2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int offset,
2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register value,
2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register scratch,
2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      LinkRegisterStatus lr_status,
2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SaveFPRegsMode save_fp,
2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SmiCheck smi_check = INLINE_SMI_CHECK,
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PointersToHereCheck pointers_to_here_check_for_value =
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          kPointersToHereMaybeInteresting);
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // As above, but the offset has the tag presubtracted.  For use with
2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // MemOperand(reg, off).
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline void RecordWriteContextSlot(
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register context,
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int offset,
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register value,
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register scratch,
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      LinkRegisterStatus lr_status,
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SaveFPRegsMode save_fp,
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SmiCheck smi_check = INLINE_SMI_CHECK,
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PointersToHereCheck pointers_to_here_check_for_value =
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          kPointersToHereMaybeInteresting) {
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RecordWriteField(context,
2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     offset + kHeapObjectTag,
2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     value,
2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     scratch,
2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     lr_status,
2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     save_fp,
2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     remembered_set_action,
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     smi_check,
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     pointers_to_here_check_for_value);
3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
301592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
302109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Notify the garbage collector that we wrote a code entry into a
303109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // JSFunction. Only scratch is clobbered by the operation.
304109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void RecordWriteCodeEntryField(Register js_function, Register code_entry,
305109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                 Register scratch);
306109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RecordWriteForMap(
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register object,
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register map,
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register dst,
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      LinkRegisterStatus lr_status,
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SaveFPRegsMode save_fp);
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // For a given |object| notify the garbage collector that the slot |address|
3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // has been written.  |value| is the object being stored. The value and
3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // address registers are clobbered by the operation.
3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void RecordWrite(
3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register object,
3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register address,
3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register value,
3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      LinkRegisterStatus lr_status,
3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SaveFPRegsMode save_fp,
3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SmiCheck smi_check = INLINE_SMI_CHECK,
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PointersToHereCheck pointers_to_here_check_for_value =
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          kPointersToHereMaybeInteresting);
3278defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Push a handle.
3293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Push(Handle<Object> handle);
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); }
3313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Push two registers.  Pushes leftmost register first (to highest address).
3336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Push(Register src1, Register src2, Condition cond = al) {
3346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (src1.code() > src2.code()) {
3356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      stm(db_w, sp, src1.bit() | src2.bit(), cond);
3366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
3376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      str(src1, MemOperand(sp, 4, NegPreIndex), cond);
3386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      str(src2, MemOperand(sp, 4, NegPreIndex), cond);
3396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
3406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Push three registers.  Pushes leftmost register first (to highest address).
3436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Push(Register src1, Register src2, Register src3, Condition cond = al) {
3446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (src1.code() > src2.code()) {
3456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (src2.code() > src3.code()) {
3466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
3476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
3486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        stm(db_w, sp, src1.bit() | src2.bit(), cond);
3496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        str(src3, MemOperand(sp, 4, NegPreIndex), cond);
3506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
3516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
3526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      str(src1, MemOperand(sp, 4, NegPreIndex), cond);
3536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Push(src2, src3, cond);
3546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
3556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Push four registers.  Pushes leftmost register first (to highest address).
3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Push(Register src1,
3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Register src2,
3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Register src3,
3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Register src4,
3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Condition cond = al) {
3636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (src1.code() > src2.code()) {
3646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (src2.code() > src3.code()) {
3656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (src3.code() > src4.code()) {
3666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          stm(db_w,
3676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              sp,
3686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              src1.bit() | src2.bit() | src3.bit() | src4.bit(),
3696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              cond);
3706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        } else {
3716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
3726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          str(src4, MemOperand(sp, 4, NegPreIndex), cond);
3736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
3746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
3756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        stm(db_w, sp, src1.bit() | src2.bit(), cond);
3766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Push(src3, src4, cond);
3776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
3786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
3796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      str(src1, MemOperand(sp, 4, NegPreIndex), cond);
3806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Push(src2, src3, src4, cond);
3816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
3826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Push five registers.  Pushes leftmost register first (to highest address).
385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Push(Register src1, Register src2, Register src3, Register src4,
386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Register src5, Condition cond = al) {
387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (src1.code() > src2.code()) {
388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (src2.code() > src3.code()) {
389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (src3.code() > src4.code()) {
390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (src4.code() > src5.code()) {
391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            stm(db_w, sp,
392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                src1.bit() | src2.bit() | src3.bit() | src4.bit() | src5.bit(),
393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                cond);
394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else {
395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            stm(db_w, sp, src1.bit() | src2.bit() | src3.bit() | src4.bit(),
396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                cond);
397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            str(src5, MemOperand(sp, 4, NegPreIndex), cond);
398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else {
400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Push(src4, src5, cond);
402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        stm(db_w, sp, src1.bit() | src2.bit(), cond);
405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Push(src3, src4, src5, cond);
406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      str(src1, MemOperand(sp, 4, NegPreIndex), cond);
409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(src2, src3, src4, src5, cond);
410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
413e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Pop two registers. Pops rightmost register first (from lower address).
414e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void Pop(Register src1, Register src2, Condition cond = al) {
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!src1.is(src2));
416e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (src1.code() > src2.code()) {
417e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
418e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
419e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ldr(src2, MemOperand(sp, 4, PostIndex), cond);
420e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ldr(src1, MemOperand(sp, 4, PostIndex), cond);
421e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
423e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Pop three registers.  Pops rightmost register first (from lower address).
4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Pop(Register src1, Register src2, Register src3, Condition cond = al) {
426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!AreAliased(src1, src2, src3));
4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (src1.code() > src2.code()) {
4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (src2.code() > src3.code()) {
4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ldr(src3, MemOperand(sp, 4, PostIndex), cond);
4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Pop(src2, src3, cond);
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ldr(src1, MemOperand(sp, 4, PostIndex), cond);
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Pop four registers.  Pops rightmost register first (from lower address).
4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Pop(Register src1,
4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Register src2,
4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Register src3,
4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Register src4,
4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Condition cond = al) {
446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!AreAliased(src1, src2, src3, src4));
4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (src1.code() > src2.code()) {
4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (src2.code() > src3.code()) {
4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (src3.code() > src4.code()) {
4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ldm(ia_w,
4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              sp,
4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              src1.bit() | src2.bit() | src3.bit() | src4.bit(),
4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              cond);
4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ldr(src4, MemOperand(sp, 4, PostIndex), cond);
4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Pop(src3, src4, cond);
4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Pop(src2, src3, src4, cond);
4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ldr(src1, MemOperand(sp, 4, PostIndex), cond);
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push a fixed frame, consisting of lr, fp, constant pool (if
4693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // FLAG_enable_embedded_constant_pool)
4703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void PushCommonFrame(Register marker_reg = no_reg);
4713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
4723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Push a standard frame, consisting of lr, fp, constant pool (if
4733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // FLAG_enable_embedded_constant_pool), context and JS function
4743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void PushStandardFrame(Register function_reg);
4753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
4763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void PopCommonFrame(Register marker_reg = no_reg);
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Push and pop the registers that can hold pointers, as defined by the
479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // RegList constant kSafepointSavedRegisters.
480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void PushSafepointRegisters();
481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void PopSafepointRegisters();
482e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Store value in register src in the safepoint stack slot for
483e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // register dst.
484e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void StoreToSafepointRegisterSlot(Register src, Register dst);
485e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Load the value of the src register from its safepoint stack slot
486e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // into register dst.
487e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void LoadFromSafepointRegisterSlot(Register dst, Register src);
488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load two consecutive registers with two consecutive memory locations.
490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  void Ldrd(Register dst1,
491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            Register dst2,
492f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            const MemOperand& src,
493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            Condition cond = al);
494f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Store two consecutive registers to two consecutive memory locations.
496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  void Strd(Register src1,
497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            Register src2,
498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            const MemOperand& dst,
499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            Condition cond = al);
500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the value is a NaN, canonicalize the value else, do nothing.
502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VFPCanonicalizeNaN(const DwVfpRegister dst,
503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          const DwVfpRegister src,
504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          const Condition cond = al);
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VFPCanonicalizeNaN(const DwVfpRegister value,
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          const Condition cond = al) {
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VFPCanonicalizeNaN(value, value, cond);
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
509b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Compare single values and move the result to the normal condition flags.
511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void VFPCompareAndSetFlags(const SwVfpRegister src1, const SwVfpRegister src2,
512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                             const Condition cond = al);
513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void VFPCompareAndSetFlags(const SwVfpRegister src1, const float src2,
514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                             const Condition cond = al);
515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
516b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Compare double values and move the result to the normal condition flags.
517b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void VFPCompareAndSetFlags(const DwVfpRegister src1,
518b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                             const DwVfpRegister src2,
519b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                             const Condition cond = al);
520b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void VFPCompareAndSetFlags(const DwVfpRegister src1,
521b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                             const double src2,
522b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                             const Condition cond = al);
523b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Compare single values and then load the fpscr flags to a register.
525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void VFPCompareAndLoadFlags(const SwVfpRegister src1,
526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              const SwVfpRegister src2,
527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              const Register fpscr_flags,
528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              const Condition cond = al);
529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void VFPCompareAndLoadFlags(const SwVfpRegister src1, const float src2,
530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              const Register fpscr_flags,
531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              const Condition cond = al);
532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
533b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Compare double values and then load the fpscr flags to a register.
534b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void VFPCompareAndLoadFlags(const DwVfpRegister src1,
535b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              const DwVfpRegister src2,
536b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              const Register fpscr_flags,
537b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              const Condition cond = al);
538b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void VFPCompareAndLoadFlags(const DwVfpRegister src1,
539b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              const double src2,
540b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              const Register fpscr_flags,
541b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              const Condition cond = al);
542b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
5433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Vmov(const DwVfpRegister dst,
5443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            const double imm,
545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            const Register scratch = no_reg);
546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VmovHigh(Register dst, DwVfpRegister src);
548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VmovHigh(DwVfpRegister dst, Register src);
549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VmovLow(Register dst, DwVfpRegister src);
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VmovLow(DwVfpRegister dst, Register src);
551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
552c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Simulate s-register moves for imaginary s32 - s63 registers.
553c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void VmovExtended(Register dst, int src_code);
554c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void VmovExtended(int dst_code, Register src);
555c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Move between s-registers and imaginary s-registers.
556c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void VmovExtended(int dst_code, int src_code, Register scratch);
557c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void VmovExtended(int dst_code, const MemOperand& src, Register scratch);
558c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void VmovExtended(const MemOperand& dst, int src_code, Register scratch);
559c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
5603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void LslPair(Register dst_low, Register dst_high, Register src_low,
5613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch               Register src_high, Register scratch, Register shift);
5623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void LslPair(Register dst_low, Register dst_high, Register src_low,
5633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch               Register src_high, uint32_t shift);
5643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void LsrPair(Register dst_low, Register dst_high, Register src_low,
5653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch               Register src_high, Register scratch, Register shift);
5663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void LsrPair(Register dst_low, Register dst_high, Register src_low,
5673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch               Register src_high, uint32_t shift);
5683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void AsrPair(Register dst_low, Register dst_high, Register src_low,
5693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch               Register src_high, Register scratch, Register shift);
5703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void AsrPair(Register dst_low, Register dst_high, Register src_low,
5713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch               Register src_high, uint32_t shift);
5723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loads the number from object into dst register.
574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If |object| is neither smi nor heap number, |not_number| is jumped to
575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // with |object| still intact.
576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void LoadNumber(Register object,
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  LowDwVfpRegister dst,
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Register heap_number_map,
579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Register scratch,
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Label* not_number);
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loads the number from object into double_dst in the double format.
583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Control will jump to not_int32 if the value cannot be exactly represented
584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // by a 32-bit integer.
585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Floating point value in the 32-bit integer range that are not exact integer
586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // won't be loaded.
587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void LoadNumberAsInt32Double(Register object,
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               DwVfpRegister double_dst,
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register heap_number_map,
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register scratch,
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               LowDwVfpRegister double_scratch,
592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* not_int32);
593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loads the number from object into dst as a 32-bit integer.
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Control will jump to not_int32 if the object cannot be exactly represented
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // by a 32-bit integer.
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Floating point value in the 32-bit integer range that are not exact integer
598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // won't be converted.
599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void LoadNumberAsInt32(Register object,
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register dst,
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register heap_number_map,
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register scratch,
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         DwVfpRegister double_scratch0,
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         LowDwVfpRegister double_scratch1,
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Label* not_int32);
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Generates function and stub prologue code.
6083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void StubPrologue(StackFrame::Type type);
609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Prologue(bool code_pre_aging);
6103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
61180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Enter exit frame.
6121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // stack_space - extra stack space, used for alignment before call to C.
613f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void EnterExitFrame(bool save_doubles, int stack_space = 0,
614f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                      StackFrame::Type frame_type = StackFrame::EXIT);
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Leave the current exit frame. Expects the return value in r0.
617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Expect the number of values, pushed prior to the exit frame, to
618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // remove in a register (or no_reg, if there is nothing to remove).
619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LeaveExitFrame(bool save_doubles, Register argument_count,
620014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      bool restore_context,
621014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      bool argument_count_is_length = false);
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the actual activation frame alignment for target environment.
6246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static int ActivationFrameAlignment();
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void LoadContext(Register dst, int context_chain_length);
627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load the global object from the current context.
629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LoadGlobalObject(Register dst) {
630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LoadNativeContextSlot(Context::EXTENSION_INDEX, dst);
631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load the global proxy from the current context.
634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LoadGlobalProxy(Register dst) {
635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LoadNativeContextSlot(Context::GLOBAL_PROXY_INDEX, dst);
636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
6383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Conditionally load the cached Array transitioned map of type
639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // transitioned_kind from the native context if the map in register
640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // map_in_out is the cached Array map in the native context of
6413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // expected_kind.
6423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void LoadTransitionedArrayMapConditional(
6433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ElementsKind expected_kind,
6443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ElementsKind transitioned_kind,
6453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register map_in_out,
6463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register scratch,
6473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label* no_map_match);
6483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
649014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LoadNativeContextSlot(int index, Register dst);
6508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the initial map from the global function. The registers
6528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // function and map can be the same, function is then overwritten.
6538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  void LoadGlobalFunctionInitialMap(Register function,
6548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                    Register map,
6558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                    Register scratch);
6568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
657c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  void InitializeRootRegister() {
6583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExternalReference roots_array_start =
6593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ExternalReference::roots_array_start(isolate());
6603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(kRootRegister, Operand(roots_array_start));
661c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  }
662c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // JavaScript invokes
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Removes current frame and its arguments from the stack preserving
6673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // the arguments and a return address pushed to the stack for the next call.
6683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Both |callee_args_count| and |caller_args_count_reg| do not include
6693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // receiver. |callee_args_count| is not modified, |caller_args_count_reg|
6703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // is trashed.
6713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void PrepareForTailCall(const ParameterCount& callee_args_count,
6723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                          Register caller_args_count_reg, Register scratch0,
6733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                          Register scratch1);
6743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the JavaScript function code by either calling or jumping.
676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void InvokeFunctionCode(Register function, Register new_target,
677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                          const ParameterCount& expected,
678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                          const ParameterCount& actual, InvokeFlag flag,
679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                          const CallWrapper& call_wrapper);
680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void FloodFunctionIfStepping(Register fun, Register new_target,
682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               const ParameterCount& expected,
683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               const ParameterCount& actual);
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the JavaScript function in the given register. Changes the
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // current context to the context in the function before invoking.
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void InvokeFunction(Register function,
688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      Register new_target,
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      const ParameterCount& actual,
690b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                      InvokeFlag flag,
691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const CallWrapper& call_wrapper);
692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void InvokeFunction(Register function,
694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const ParameterCount& expected,
695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const ParameterCount& actual,
696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      InvokeFlag flag,
697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const CallWrapper& call_wrapper);
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void InvokeFunction(Handle<JSFunction> function,
700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const ParameterCount& expected,
701402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                      const ParameterCount& actual,
702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      InvokeFlag flag,
703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const CallWrapper& call_wrapper);
704402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void IsObjectJSStringType(Register object,
706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            Register scratch,
707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            Label* fail);
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void IsObjectNameType(Register object,
710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        Register scratch,
711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        Label* fail);
712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Debugger Support
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
716402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void DebugBreak();
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Exception handling
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Push a new stack handler and link into stack handler chain.
722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void PushStackHandler();
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Unlink the stack handler on top of the stack from the stack handler chain.
725e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Must preserve the result register.
726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void PopStackHandler();
727e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Inline caching support
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
731c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  void GetNumberHash(Register t0, Register scratch);
7323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  inline void MarkCode(NopMarkerTypes type) {
7348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    nop(type);
7358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
7368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
7378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check if the given instruction is a 'type' marker.
7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // i.e. check if is is a mov r<type>, r<type> (referenced as nop(type))
7398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // These instructions are generated to mark special location in the code,
7408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // like some special IC code.
7418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  static inline bool IsMarkedCode(Instr instr, int type) {
742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER));
7438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    return IsNop(instr, type);
7448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
7458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
7468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
7478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  static inline int GetCodeMarker(Instr instr) {
7488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    int dst_reg_offset = 12;
7498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    int dst_mask = 0xf << dst_reg_offset;
7508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    int src_mask = 0xf;
7518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    int dst_reg = (instr & dst_mask) >> dst_reg_offset;
7528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    int src_reg = instr & src_mask;
7538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    uint32_t non_register_mask = ~(dst_mask | src_mask);
7548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    uint32_t mov_mask = al | 13 << 21;
7558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
7568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    // Return <n> if we have a mov rn rn, else return -1.
7578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    int type = ((instr & non_register_mask) == mov_mask) &&
7588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang               (dst_reg == src_reg) &&
7598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang               (FIRST_IC_MARKER <= dst_reg) && (dst_reg < LAST_CODE_MARKER)
7608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                   ? src_reg
7618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                   : -1;
762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK((type == -1) ||
7638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang           ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)));
7648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    return type;
7658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
7668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocation support
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
771014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allocate an object in new space or old space. The object_size is
772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // specified either in bytes or in words if the allocation flag SIZE_IN_WORDS
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // is passed. If the space is exhausted control continues at the gc_required
774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // label. The allocated object is returned in result. If the flag
775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // tag_allocated_object is true the result is tagged as as a heap object.
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // All registers are clobbered also when control continues at the gc_required
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // label.
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Allocate(int object_size,
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register result,
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register scratch1,
781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register scratch2,
782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Label* gc_required,
783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                AllocationFlags flags);
784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Allocate(Register object_size, Register result, Register result_end,
786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                Register scratch, Label* gc_required, AllocationFlags flags);
7873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
788bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // FastAllocate is right now only used for folded allocations. It just
789bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // increments the top pointer without checking against limit. This can only
790bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // be done if it was proved earlier that the allocation will succeed.
791bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void FastAllocate(int object_size, Register result, Register scratch1,
792bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                    Register scratch2, AllocationFlags flags);
793bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
794bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void FastAllocate(Register object_size, Register result, Register result_end,
795bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                    Register scratch, AllocationFlags flags);
796bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
7973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void AllocateTwoByteString(Register result,
7983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                             Register length,
7993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                             Register scratch1,
8003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                             Register scratch2,
8013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                             Register scratch3,
8023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                             Label* gc_required);
803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AllocateOneByteString(Register result, Register length,
804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             Register scratch1, Register scratch2,
805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             Register scratch3, Label* gc_required);
8063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void AllocateTwoByteConsString(Register result,
8073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 Register length,
8083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 Register scratch1,
8093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 Register scratch2,
8103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                 Label* gc_required);
811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AllocateOneByteConsString(Register result, Register length,
812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register scratch1, Register scratch2,
813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Label* gc_required);
814589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void AllocateTwoByteSlicedString(Register result,
815589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                   Register length,
816589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                   Register scratch1,
817589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                   Register scratch2,
818589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                   Label* gc_required);
819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AllocateOneByteSlicedString(Register result, Register length,
820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register scratch1, Register scratch2,
821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Label* gc_required);
8223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
82325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // Allocates a heap number or jumps to the gc_required label if the young
82425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // space is full and a scavenge is needed. All registers are clobbered also
82525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // when control continues at the gc_required label.
8266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void AllocateHeapNumber(Register result,
8276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                          Register scratch1,
8286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                          Register scratch2,
8299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                          Register heap_number_map,
830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          Label* gc_required,
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          MutableMode mode = IMMUTABLE);
8328defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void AllocateHeapNumberWithValue(Register result,
8338defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   DwVfpRegister value,
8348defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Register scratch1,
8358defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Register scratch2,
8368defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Register heap_number_map,
8378defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Label* gc_required);
8388defd9ff6930b4e24729971a61cf7469daf119beSteve Block
839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allocate and initialize a JSValue wrapper with the specified {constructor}
840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // and {value}.
841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void AllocateJSValue(Register result, Register constructor, Register value,
842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       Register scratch1, Register scratch2,
843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       Label* gc_required);
8443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Initialize fields with filler values.  Fields starting at |current_address|
846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // not including |end_address| are overwritten with the value in |filler|.  At
847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // the end the loop, |current_address| takes the value of |end_address|.
848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void InitializeFieldsWithFiller(Register current_address,
849014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  Register end_address, Register filler);
8503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Support functions.
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Machine code version of Map::GetConstructor().
855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // |temp| holds |result|'s map when done, and |temp2| its instance type.
856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void GetMapConstructor(Register result, Register map, Register temp,
857014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         Register temp2);
858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Try to get function prototype of a function and puts the value in
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the result register. Checks that the function really is a
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // function and jumps to the miss label if the fast checks fail. The
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // function register will be untouched; the other registers may be
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // clobbered.
864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void TryGetFunctionPrototype(Register function, Register result,
865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               Register scratch, Label* miss);
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compare object type for heap object.  heap_object contains a non-Smi
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // whose object type should be compared with the given type.  This both
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sets the flags and leaves the object type in the type_reg register.
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // It leaves the map in the map register (unless the type_reg and map register
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // are the same register).  It leaves the heap object in the heap_object
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // register unless the heap_object register is the same register as one of the
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // other registers.
874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Type_reg can be no_reg. In that case ip is used.
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CompareObjectType(Register heap_object,
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         Register map,
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         Register type_reg,
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         InstanceType type);
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compare instance type in a map.  map contains a valid map object whose
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object type should be compared with the given type.  This both
882589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // sets the flags and leaves the object type in the type_reg register.
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CompareInstanceType(Register map,
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           Register type_reg,
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           InstanceType type);
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if a map for a JSObject indicates that the object can have both smi
8883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // and HeapObject elements.  Jump to the specified label if it does not.
8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CheckFastObjectElements(Register map,
8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Register scratch,
8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Label* fail);
8923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if a map for a JSObject indicates that the object has fast smi only
8943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // elements.  Jump to the specified label if it does not.
895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CheckFastSmiElements(Register map,
896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Register scratch,
897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Label* fail);
8983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check to see if maybe_number can be stored as a double in
9003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // FastDoubleElements. If it can, store it at the index specified by key in
901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the FastDoubleElements array elements. Otherwise jump to fail.
9023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void StoreNumberToDoubleElements(Register value_reg,
9033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Register key_reg,
9043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Register elements_reg,
9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Register scratch1,
906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   LowDwVfpRegister double_scratch,
907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Label* fail,
908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   int elements_offset = 0);
9093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Compare an object's map with the specified map and its transitioned
9113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Condition flags are
9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // set with result of map compare. If multiple map compares are required, the
9133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // compare sequences branches to early_success.
9143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CompareMap(Register obj,
9153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Register scratch,
9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Handle<Map> map,
917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Label* early_success);
918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // As above, but the map of the object is already loaded into the register
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // which is preserved by the code generated.
921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CompareMap(Register obj_map,
922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Handle<Map> map,
923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Label* early_success);
9243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if the map of an object is equal to a specified map and branch to
9263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // label if not. Skip the smi check if not required (object is known to be a
9273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
9283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // against maps that are ElementsKind transition maps of the specified map.
9293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void CheckMap(Register obj,
9303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                Register scratch,
9313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                Handle<Map> map,
9323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                Label* fail,
933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                SmiCheckType smi_check_type);
934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
9353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  void CheckMap(Register obj,
9377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                Register scratch,
9387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                Heap::RootListIndex index,
9397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                Label* fail,
940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                SmiCheckType smi_check_type);
941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
943958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check if the map of an object is equal to a specified weak map and branch
944958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // to a specified target if equal. Skip the smi check if not required
945958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // (object is known to be a heap object)
946958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DispatchWeakMap(Register obj, Register scratch1, Register scratch2,
947958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       Handle<WeakCell> cell, Handle<Code> success,
948958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       SmiCheckType smi_check_type);
949958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
950958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Compare the given value and the value of weak cell.
951958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void CmpWeakValue(Register value, Handle<WeakCell> cell, Register scratch);
9527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void GetWeakValue(Register value, Handle<WeakCell> cell);
954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
955958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Load the value of the weak cell in the value register. Branch to the given
956958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // miss label if the weak cell was cleared.
957958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void LoadWeakValue(Register value, Handle<WeakCell> cell, Label* miss);
9587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
959e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Compare the object in a register to a value from the root list.
960e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Uses the ip register as scratch.
961e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void CompareRoot(Register obj, Heap::RootListIndex index);
962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void PushRoot(Heap::RootListIndex index) {
963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LoadRoot(ip, index);
964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(ip);
965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
966e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Compare the object in a register to a value and jump if they are equal.
968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void JumpIfRoot(Register with, Heap::RootListIndex index, Label* if_equal) {
969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CompareRoot(with, index);
970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    b(eq, if_equal);
971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Compare the object in a register to a value and jump if they are not equal.
974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void JumpIfNotRoot(Register with, Heap::RootListIndex index,
975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     Label* if_not_equal) {
976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CompareRoot(with, index);
977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    b(ne, if_not_equal);
978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
979e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
9803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Load and check the instance type of an object for being a string.
9813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Loads the type into the second argument register.
982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Returns a condition that will be enabled if the object was a string
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // and the passed-in condition passed. If the passed-in condition failed
984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // then flags remain unchanged.
9853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Condition IsObjectStringType(Register obj,
986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register type,
987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Condition cond = al) {
988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset), cond);
989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset), cond);
990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    tst(type, Operand(kIsNotStringMask), cond);
991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_EQ(0u, kStringTag);
9923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    return eq;
9933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
9943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Get the number of least significant bits from a register
9973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits);
9981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits);
9993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the value of a smi object into a double register.
1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The register value must be between d0 and d15.
1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SmiToDouble(LowDwVfpRegister value, Register smi);
1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if a double can be exactly represented as a signed 32-bit integer.
1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Z flag set to one if true.
1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TestDoubleIsInt32(DwVfpRegister double_input,
1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         LowDwVfpRegister double_scratch);
1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Try to convert a double to a signed 32-bit integer.
1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Z flag set to one and result assigned if the conversion is exact.
1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TryDoubleToInt32Exact(Register result,
1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             DwVfpRegister double_input,
1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             LowDwVfpRegister double_scratch);
1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Floor a double and writes the value to the result register.
1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Go to exact if the conversion is exact (to be able to test -0),
1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // fall through calling code if an overflow occurred, else go to done.
1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // In return, input_high is loaded with high bits of input.
1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TryInt32Floor(Register result,
1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     DwVfpRegister double_input,
1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     Register input_high,
1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     LowDwVfpRegister double_scratch,
1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     Label* done,
1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     Label* exact);
1025d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Performs a truncating conversion of a floating point number as used by
1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it
1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // succeeds, otherwise falls through if result is saturated. On return
1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // 'result' either holds answer, or is clobbered on fall through.
1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Only public for the test code in test-code-stubs-arm.cc.
1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TryInlineTruncateDoubleToI(Register result,
1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  DwVfpRegister input,
1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  Label* done);
103544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
103644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Performs a truncating conversion of a floating point number as used by
103744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // the JS bitwise operations. See ECMA-262 9.5: ToInt32.
1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Exits with 'result' holding the answer.
1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TruncateDoubleToI(Register result, DwVfpRegister double_input);
1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Performs a truncating conversion of a heap number as used by
1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 'result' and 'input'
1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // must be different registers.  Exits with 'result' holding the answer.
1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TruncateHeapNumberToI(Register result, Register object);
1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Converts the smi or heap number in object to an int32 using the rules
1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // for ToInt32 as described in ECMAScript 9.5.: the value is truncated
1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // and brought into the range -2^31 .. +2^31 - 1. 'result' and 'input' must be
1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // different registers.
1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TruncateNumberToI(Register object,
1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register result,
1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register heap_number_map,
1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register scratch1,
1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Label* not_int32);
1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check whether d16-d31 are available on the CPU. The result is given by the
1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Z condition flag: Z==0 if d16-d31 available, Z==1 otherwise.
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CheckFor32DRegs(Register scratch);
1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Does a runtime check for 16/32 FP registers. Either way, pushes 32 double
1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // values to location, saving [d0..(d15|d31)].
1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SaveFPRegs(Register location, Register scratch);
1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Does a runtime check for 16/32 FP registers. Either way, pops 32 double
1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // values to location, restoring [d0..(d15|d31)].
1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RestoreFPRegs(Register location, Register scratch);
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1068f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Perform a floating-point min or max operation with the
1069f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // (IEEE-754-compatible) semantics of ARM64's fmin/fmax. Some cases, typically
1070f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // NaNs or +/-0.0, are expected to be rare and are handled in out-of-line
1071f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // code. The specific behaviour depends on supported instructions.
1072f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  //
1073f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // These functions assume (and assert) that !left.is(right). It is permitted
1074f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // for the result to alias either input register.
1075f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMax(SwVfpRegister result, SwVfpRegister left, SwVfpRegister right,
1076f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                Label* out_of_line);
1077f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMin(SwVfpRegister result, SwVfpRegister left, SwVfpRegister right,
1078f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                Label* out_of_line);
1079f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMax(DwVfpRegister result, DwVfpRegister left, DwVfpRegister right,
1080f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                Label* out_of_line);
1081f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMin(DwVfpRegister result, DwVfpRegister left, DwVfpRegister right,
1082f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                Label* out_of_line);
1083f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1084f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Generate out-of-line cases for the macros above.
1085f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMaxOutOfLine(SwVfpRegister result, SwVfpRegister left,
1086f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                         SwVfpRegister right);
1087f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMinOutOfLine(SwVfpRegister result, SwVfpRegister left,
1088f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                         SwVfpRegister right);
1089f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMaxOutOfLine(DwVfpRegister result, DwVfpRegister left,
1090f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                         DwVfpRegister right);
1091f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMinOutOfLine(DwVfpRegister result, DwVfpRegister left,
1092f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                         DwVfpRegister right);
1093f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Runtime calls
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call a code stub.
1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CallStub(CodeStub* stub,
1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                TypeFeedbackId ast_id = TypeFeedbackId::None(),
1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Condition cond = al);
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Call a code stub.
11033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void TailCallStub(CodeStub* stub, Condition cond = al);
11043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call a runtime routine.
1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CallRuntime(const Runtime::Function* f,
1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   int num_arguments,
1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   SaveFPRegsMode save_doubles = kDontSaveFPRegs);
1109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void CallRuntimeSaveDoubles(Runtime::FunctionId fid) {
1110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    const Runtime::Function* function = Runtime::FunctionForId(fid);
1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallRuntime(function, function->nargs, kSaveFPRegs);
1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Convenience function: Same as above, but takes the fid instead.
1115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void CallRuntime(Runtime::FunctionId fid,
1116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   SaveFPRegsMode save_doubles = kDontSaveFPRegs) {
1117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    const Runtime::Function* function = Runtime::FunctionForId(fid);
1118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallRuntime(function, function->nargs, save_doubles);
1119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Convenience function: Same as above, but takes the fid instead.
1122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void CallRuntime(Runtime::FunctionId fid, int num_arguments,
1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   SaveFPRegsMode save_doubles = kDontSaveFPRegs) {
1124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallRuntime(Runtime::FunctionForId(fid), num_arguments, save_doubles);
1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1127402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Convenience function: call an external reference.
1128402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void CallExternalReference(const ExternalReference& ext,
1129402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                             int num_arguments);
1130402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
11316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Convenience function: tail call a runtime routine (jump).
1132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void TailCallRuntime(Runtime::FunctionId fid);
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int CalculateStackPassedWords(int num_reg_arguments,
1135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                int num_double_arguments);
1136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Before calling a C-function from generated code, align arguments on stack.
11386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // After aligning the frame, non-register arguments must be stored in
11396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments
1140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // are word sized. If double arguments are used, this function assumes that
1141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // all double arguments are stored before core registers; otherwise the
1142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // correct alignment of the double values is not guaranteed.
11436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Some compilers/platforms require the stack to be aligned when calling
11446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // C++ code.
11456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Needs a scratch register to do some arithmetic. This register will be
11466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // trashed.
1147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void PrepareCallCFunction(int num_reg_arguments,
1148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            int num_double_registers,
1149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register scratch);
1150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void PrepareCallCFunction(int num_reg_arguments,
1151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register scratch);
1152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // There are two ways of passing double arguments on ARM, depending on
1154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // whether soft or hard floating point ABI is used. These functions
1155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // abstract parameter passing for the three different ways we call
1156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // C functions from generated code.
1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MovToFloatParameter(DwVfpRegister src);
1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MovToFloatParameters(DwVfpRegister src1, DwVfpRegister src2);
1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MovToFloatResult(DwVfpRegister src);
11606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Calls a C function and cleans up the space for arguments allocated
11626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // by PrepareCallCFunction. The called function is not allowed to trigger a
11636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // garbage collection, since that might move the code and invalidate the
11646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // return address (unless this is somehow accounted for by the called
11656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // function).
11666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void CallCFunction(ExternalReference function, int num_arguments);
11673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CallCFunction(Register function, int num_arguments);
1168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void CallCFunction(ExternalReference function,
1169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     int num_reg_arguments,
1170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     int num_double_arguments);
11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CallCFunction(Register function,
1172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     int num_reg_arguments,
1173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     int num_double_arguments);
11746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MovFromFloatParameter(DwVfpRegister dst);
1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MovFromFloatResult(DwVfpRegister dst);
1177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to a runtime routine.
1179f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void JumpToExternalReference(const ExternalReference& builtin,
1180f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                               bool builtin_exit_frame = false);
1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<Object> CodeObject() {
1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!code_object_.is_null());
11848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return code_object_;
11858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Emit code for a truncating division by a constant. The dividend register is
1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // unchanged and ip gets clobbered. Dividend and result must be different.
1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TruncatingDiv(Register result, Register dividend, int32_t divisor);
1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // StatsCounter support
1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void SetCounter(StatsCounter* counter, int value,
1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  Register scratch1, Register scratch2);
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void IncrementCounter(StatsCounter* counter, int value,
1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        Register scratch1, Register scratch2);
1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void DecrementCounter(StatsCounter* counter, int value,
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        Register scratch1, Register scratch2);
1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Debugging
1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Calls Abort(msg) if the condition cond is not satisfied.
1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use --debug_code to enable.
1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Assert(Condition cond, BailoutReason reason);
1209756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void AssertFastElements(Register elements);
1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Like Assert(), but always enabled.
1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Check(Condition cond, BailoutReason reason);
1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print a message to stdout and abort execution.
1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Abort(BailoutReason msg);
1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Verify restrictions about code generated in stubs.
1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void set_generating_stub(bool value) { generating_stub_ = value; }
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool generating_stub() { return generating_stub_; }
12203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void set_has_frame(bool value) { has_frame_ = value; }
12213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool has_frame() { return has_frame_; }
12223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline bool AllowThisStubCall(CodeStub* stub);
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // EABI variant for double arguments in use.
1225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool use_eabi_hardfloat() {
1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef __arm__
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return base::OS::ArmUsingHardFloat();
1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#elif USE_EABI_HARDFLOAT
1229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return true;
1230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#else
1231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return false;
1232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
1233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1235d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // ---------------------------------------------------------------------------
12361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Number utilities
12371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check whether the value of reg is a power of two and not zero. If not
12391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // control continues at the label not_power_of_two. If reg is a power of two
12401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // the register scratch contains the value of (reg - 1) when control falls
12411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // through.
12421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void JumpIfNotPowerOfTwoOrZero(Register reg,
12431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                 Register scratch,
12441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                 Label* not_power_of_two_or_zero);
124544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check whether the value of reg is a power of two and not zero.
124644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Control falls through if it is, with scratch containing the mask
124744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // value (reg - 1).
124844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Otherwise control jumps to the 'zero_and_neg' label if the value of reg is
124944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // zero or negative, or jumps to the 'not_power_of_two' label if the value is
125044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // strictly positive but not a power of two.
125144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg,
125244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       Register scratch,
125344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       Label* zero_and_neg,
125444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       Label* not_power_of_two);
12551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ---------------------------------------------------------------------------
12573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Smi utilities
12583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void SmiTag(Register reg, SBit s = LeaveCC) {
1260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    add(reg, reg, Operand(reg), s);
1261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
12621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void SmiTag(Register dst, Register src, SBit s = LeaveCC) {
12631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    add(dst, src, Operand(src), s);
12641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1266b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Try to convert int32 to smi. If the value is to large, preserve
1267b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // the original value and jump to not_a_smi. Destroys scratch and
1268b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // sets flags.
1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TrySmiTag(Register reg, Label* not_a_smi) {
1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TrySmiTag(reg, reg, not_a_smi);
1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TrySmiTag(Register reg, Register src, Label* not_a_smi) {
1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiTag(ip, src, SetCC);
1274b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    b(vs, not_a_smi);
1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(reg, ip);
1276b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1277b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1279e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void SmiUntag(Register reg, SBit s = LeaveCC) {
1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(reg, Operand::SmiUntag(reg), s);
1281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1282e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void SmiUntag(Register dst, Register src, SBit s = LeaveCC) {
1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, Operand::SmiUntag(src), s);
12841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
12863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Untag the source value into destination and jump if source is a smi.
12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Souce and destination can be the same register.
12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case);
12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Untag the source value into destination and jump if source is not a smi.
12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Souce and destination can be the same register.
12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case);
12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test if the register contains a smi (Z == 0 (eq) if true).
1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void SmiTst(Register value) {
1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    tst(value, Operand(kSmiTagMask));
1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void NonNegativeSmiTst(Register value) {
1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    tst(value, Operand(kSmiTagMask | kSmiSignMask));
1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Jump if the register contains a smi.
13021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  inline void JumpIfSmi(Register value, Label* smi_label) {
13031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    tst(value, Operand(kSmiTagMask));
13041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    b(eq, smi_label);
13051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
13061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Jump if either of the registers contain a non-smi.
13071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  inline void JumpIfNotSmi(Register value, Label* not_smi_label) {
13081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    tst(value, Operand(kSmiTagMask));
13091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    b(ne, not_smi_label);
13101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
13113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Jump if either of the registers contain a non-smi.
13123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi);
13133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Jump if either of the registers contain a smi.
13143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi);
13153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Abort execution if argument is a number, enabled via --debug-code.
13173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void AssertNotNumber(Register object);
13183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Abort execution if argument is a smi, enabled via --debug-code.
1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AssertNotSmi(Register object);
1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AssertSmi(Register object);
1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Abort execution if argument is not a string, enabled via --debug-code.
1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AssertString(Register object);
13251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Abort execution if argument is not a name, enabled via --debug-code.
1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AssertName(Register object);
1328e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Abort execution if argument is not a JSFunction, enabled via --debug-code.
1330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void AssertFunction(Register object);
1331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Abort execution if argument is not a JSBoundFunction,
1333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // enabled via --debug-code.
1334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void AssertBoundFunction(Register object);
1335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1336bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Abort execution if argument is not a JSGeneratorObject,
1337bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // enabled via --debug-code.
1338bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void AssertGeneratorObject(Register object);
1339bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1340109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Abort execution if argument is not a JSReceiver, enabled via --debug-code.
1341109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void AssertReceiver(Register object);
1342109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Abort execution if argument is not undefined or an AllocationSite, enabled
1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // via --debug-code.
1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AssertUndefinedOrAllocationSite(Register object, Register scratch);
1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Abort execution if reg is not the root value with the given index,
1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // enabled via --debug-code.
1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AssertIsRoot(Register reg, Heap::RootListIndex index);
13501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
13511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ---------------------------------------------------------------------------
13521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // HeapNumber utilities
13531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
13541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void JumpIfNotHeapNumber(Register object,
13551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                           Register heap_number_map,
13561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                           Register scratch,
13571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                           Label* on_not_heap_number);
1358756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
13593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // ---------------------------------------------------------------------------
1360d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // String utilities
1361d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Checks if both objects are sequential one-byte strings and jumps to label
1363d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // if either is not. Assumes that neither object is a smi.
1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfNonSmisNotBothSequentialOneByteStrings(Register object1,
1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                    Register object2,
1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                    Register scratch1,
1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                    Register scratch2,
1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                    Label* failure);
1369d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Checks if both objects are sequential one-byte strings and jumps to label
1371d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // if either is not.
1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfNotBothSequentialOneByteStrings(Register first, Register second,
1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             Register scratch1,
1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             Register scratch2,
1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             Label* not_flat_one_byte_strings);
1376d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Checks if both instance types are sequential one-byte strings and jumps to
13786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // label if either is not.
1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfBothInstanceTypesAreNotSequentialOneByte(
1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register first_object_instance_type, Register second_object_instance_type,
1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register scratch1, Register scratch2, Label* failure);
1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if instance type is sequential one-byte string and jump to label if
13846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // it is not.
1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfInstanceTypeIsNotSequentialOneByte(Register type, Register scratch,
1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                Label* failure);
1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfNotUniqueNameInstanceType(Register reg, Label* not_unique_name);
13896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmitSeqStringSetCharCheck(Register string,
1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register index,
1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register value,
1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 uint32_t encoding_mask);
13946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void ClampUint8(Register output_reg, Register input_reg);
1397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void ClampDoubleToUint8(Register result_reg,
1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          DwVfpRegister input_reg,
1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          LowDwVfpRegister double_scratch);
1401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void LoadInstanceDescriptors(Register map, Register descriptors);
1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EnumLength(Register dst, Register map);
1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void NumberOfOwnDescriptors(Register dst, Register map);
1406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LoadAccessor(Register dst, Register holder, int accessor_index,
1407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    AccessorComponent accessor);
1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<typename Field>
1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DecodeField(Register dst, Register src) {
1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Ubfx(dst, src, Field::kShift, Field::kSize);
1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<typename Field>
1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DecodeField(Register reg) {
1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DecodeField<Field>(reg, reg);
1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<typename Field>
1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DecodeFieldToSmi(Register dst, Register src) {
1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static const int shift = Field::kShift;
1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static const int mask = Field::kMask >> shift << kSmiTagSize;
1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT((mask & (0x80000000u >> (kSmiTagSize - 1))) == 0);
1424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (shift < kSmiTagSize) {
1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mov(dst, Operand(src, LSL, kSmiTagSize - shift));
1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      and_(dst, dst, Operand(mask));
1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (shift > kSmiTagSize) {
1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mov(dst, Operand(src, LSR, shift - kSmiTagSize));
1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      and_(dst, dst, Operand(mask));
1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      and_(dst, src, Operand(mask));
1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<typename Field>
1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DecodeFieldToSmi(Register reg) {
1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DecodeField<Field>(reg, reg);
1439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load the type feedback vector from a JavaScript frame.
1442014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void EmitLoadTypeFeedbackVector(Register vector);
1443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
14443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Activation support.
1445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void EnterFrame(StackFrame::Type type,
1446958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                  bool load_constant_pool_pointer_reg = false);
1447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Returns the pc offset at which the frame ends.
1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int LeaveFrame(StackFrame::Type type);
14493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1450f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void EnterBuiltinFrame(Register context, Register target, Register argc);
1451f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void LeaveBuiltinFrame(Register context, Register target, Register argc);
1452f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
14533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Expects object in r0 and returns map with validated enum cache
14543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // in r0.  Assumes that any other register can be used as a scratch.
1455109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void CheckEnumCache(Label* call_runtime);
14563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // AllocationMemento support. Arrays may have an associated
1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // AllocationMemento object that can be checked for in order to pretransition
1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to another type.
1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // On entry, receiver_reg should point to the array object.
1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // scratch_reg gets clobbered.
1462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If allocation info is present, condition flags are set to eq.
1463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TestJSArrayForAllocationMemento(Register receiver_reg,
1464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Register scratch_reg,
1465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Label* no_memento_found);
1466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfJSArrayHasAllocationMemento(Register receiver_reg,
1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Register scratch_reg,
1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Label* memento_found) {
1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label no_memento_found;
1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TestJSArrayForAllocationMemento(receiver_reg, scratch_reg,
1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    &no_memento_found);
1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    b(eq, memento_found);
1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bind(&no_memento_found);
1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Jumps to found label if a prototype map has dictionary elements.
1478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfDictionaryInPrototypeChain(Register object, Register scratch0,
1479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Register scratch1, Label* found);
1480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Loads the constant pool pointer (pp) register.
1482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LoadConstantPoolPointerRegisterFromCodeTargetAddress(
1483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Register code_target_address);
1484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LoadConstantPoolPointerRegister();
1485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
148744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void CallCFunctionHelper(Register function,
1488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           int num_reg_arguments,
1489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           int num_double_arguments);
149044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
14913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Helper functions for generating invokes.
1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void InvokePrologue(const ParameterCount& expected,
1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      const ParameterCount& actual,
1496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Label* done,
14973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      bool* definitely_mismatches,
1498b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                      InvokeFlag flag,
1499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const CallWrapper& call_wrapper);
1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void InitializeNewString(Register string,
15026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Register length,
15036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Heap::RootListIndex map_index,
15046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Register scratch1,
15056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Register scratch2);
15066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
15083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void InNewSpace(Register object,
15093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Register scratch,
15103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Condition cond,  // eq for new space, ne otherwise.
15113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Label* branch);
15123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Helper for finding the mark bits for an address.  Afterwards, the
15143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // bitmap register points at the word with the mark bits and the mask
15153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the position of the first bit.  Leaves addr_reg unchanged.
15163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline void GetMarkBits(Register addr_reg,
15173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          Register bitmap_reg,
15183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          Register mask_reg);
15193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1520e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Compute memory operands for safepoint stack slots.
1521e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  static int SafepointRegisterStackIndex(int reg_code);
1522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  MemOperand SafepointRegisterSlot(Register reg);
1523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  MemOperand SafepointRegistersAndDoublesSlot(Register reg);
1524e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1525f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Implementation helpers for FloatMin and FloatMax.
1526f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  template <typename T>
1527f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMaxHelper(T result, T left, T right, Label* out_of_line);
1528f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  template <typename T>
1529f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMinHelper(T result, T left, T right, Label* out_of_line);
1530f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  template <typename T>
1531f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMaxOutOfLineHelper(T result, T left, T right);
1532f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  template <typename T>
1533f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMinOutOfLineHelper(T result, T left, T right);
1534f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
15353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  bool generating_stub_;
15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool has_frame_;
15373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // This handle will be patched with the code object on installation.
15383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Handle<Object> code_object_;
1539e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Needs access to SafepointRegisterStackIndex for compiled frame
1541e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // traversal.
1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class StandardFrame;
1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The code patcher is used to patch (typically) small parts of code e.g. for
1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// debugging and other types of instrumentation. When using the code patcher
1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the exact number of bytes specified must be emitted. It is not legal to emit
1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// relocation information. If any of these constraints are violated it causes
1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// an assertion to fail.
1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CodePatcher {
1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum FlushICache {
1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FLUSH,
1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DONT_FLUSH
1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CodePatcher(Isolate* isolate, byte* address, int instructions,
1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              FlushICache flush_cache = FLUSH);
1560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ~CodePatcher();
1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Macro assembler to emit code.
1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MacroAssembler* masm() { return &masm_; }
1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit an instruction directly.
15661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void Emit(Instr instr);
1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit an address directly.
1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Emit(Address addr);
1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Emit the condition part of an instruction leaving the rest of the current
15721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // instruction unchanged.
15731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void EmitCondition(Condition cond);
15741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* address_;  // The address of the code being patched.
1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int size_;  // Number of bytes of the expected patch size.
1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MacroAssembler masm_;  // Macro assembler used to generate the code.
1579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FlushICache flush_cache_;  // Whether to flush the I cache after patching.
1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
1581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Static helper functions.
1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochinline MemOperand ContextMemOperand(Register context, int index = 0) {
15878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return MemOperand(context, Context::SlotOffset(index));
15888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
15898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochinline MemOperand NativeContextMemOperand() {
1592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return ContextMemOperand(cp, Context::NATIVE_CONTEXT_INDEX);
15938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
15948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define ACCESS_MASM(masm) masm->
1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
1598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_ARM_MACRO_ASSEMBLER_ARM_H_
1601