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);
18762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void Move(QwNeonRegister dst, QwNeonRegister src);
18862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Register swap.
18962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void Swap(DwVfpRegister srcdst0, DwVfpRegister srcdst1);
19062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void Swap(QwNeonRegister srcdst0, QwNeonRegister srcdst1);
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Load(Register dst, const MemOperand& src, Representation r);
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Store(Register src, const MemOperand& dst, Representation r);
194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load an object from the root table.
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void LoadRoot(Register destination,
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                Heap::RootListIndex index,
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                Condition cond = al);
19925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // Store an object to the root table.
20025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  void StoreRoot(Register source,
20125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                 Heap::RootListIndex index,
20225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                 Condition cond = al);
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ---------------------------------------------------------------------------
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // GC Support
2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void IncrementalMarkingRecordWriteHelper(Register object,
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           Register value,
2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           Register address);
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  enum RememberedSetFinalAction {
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    kReturnAtEnd,
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    kFallThroughAtEnd
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Record in the remembered set the fact that we have a pointer to new space
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // at the address pointed to by the addr register.  Only works if addr is not
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // in new space.
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void RememberedSetHelper(Register object,  // Used for debug code.
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Register addr,
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Register scratch,
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           SaveFPRegsMode save_fp,
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           RememberedSetFinalAction and_then);
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CheckPageFlag(Register object,
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     Register scratch,
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     int mask,
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     Condition cc,
2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     Label* condition_met);
2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if object is in new space.  Jumps if the object is not in new space.
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The register scratch can be object itself, but scratch will be clobbered.
2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void JumpIfNotInNewSpace(Register object,
2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Register scratch,
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Label* branch) {
236109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    InNewSpace(object, scratch, eq, branch);
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if object is in new space.  Jumps if the object is in new space.
2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The register scratch can be object itself, but it will be clobbered.
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void JumpIfInNewSpace(Register object,
2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register scratch,
2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Label* branch) {
244109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    InNewSpace(object, scratch, ne, branch);
2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if an object has a given incremental marking color.
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void HasColor(Register object,
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Register scratch0,
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Register scratch1,
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Label* has_color,
2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                int first_bit,
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                int second_bit);
2548defd9ff6930b4e24729971a61cf7469daf119beSteve Block
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void JumpIfBlack(Register object,
2569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                   Register scratch0,
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   Register scratch1,
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   Label* on_black);
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Checks the color of an object.  If the object is white we jump to the
261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // incremental marker.
262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void JumpIfWhite(Register value, Register scratch1, Register scratch2,
263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   Register scratch3, Label* value_is_white);
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Notify the garbage collector that we wrote a pointer into an object.
2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // |object| is the object being stored into, |value| is the object being
2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // stored.  value and scratch registers are clobbered by the operation.
2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The offset is the offset from the start of the object, not the offset from
269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // the tagged HeapObject pointer.  For use with FieldMemOperand(reg, off).
2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void RecordWriteField(
2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register object,
2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int offset,
2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register value,
2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register scratch,
2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      LinkRegisterStatus lr_status,
2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SaveFPRegsMode save_fp,
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SmiCheck smi_check = INLINE_SMI_CHECK,
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PointersToHereCheck pointers_to_here_check_for_value =
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          kPointersToHereMaybeInteresting);
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // As above, but the offset has the tag presubtracted.  For use with
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // MemOperand(reg, off).
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline void RecordWriteContextSlot(
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register context,
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int offset,
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register value,
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register scratch,
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      LinkRegisterStatus lr_status,
2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SaveFPRegsMode save_fp,
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SmiCheck smi_check = INLINE_SMI_CHECK,
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PointersToHereCheck pointers_to_here_check_for_value =
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          kPointersToHereMaybeInteresting) {
2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RecordWriteField(context,
2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     offset + kHeapObjectTag,
2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     value,
2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     scratch,
2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     lr_status,
3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     save_fp,
3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     remembered_set_action,
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     smi_check,
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     pointers_to_here_check_for_value);
3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
305592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
306109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Notify the garbage collector that we wrote a code entry into a
307109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // JSFunction. Only scratch is clobbered by the operation.
308109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void RecordWriteCodeEntryField(Register js_function, Register code_entry,
309109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                 Register scratch);
310109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RecordWriteForMap(
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register object,
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register map,
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register dst,
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      LinkRegisterStatus lr_status,
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SaveFPRegsMode save_fp);
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // For a given |object| notify the garbage collector that the slot |address|
3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // has been written.  |value| is the object being stored. The value and
3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // address registers are clobbered by the operation.
3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void RecordWrite(
3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register object,
3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register address,
3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register value,
3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      LinkRegisterStatus lr_status,
3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SaveFPRegsMode save_fp,
3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SmiCheck smi_check = INLINE_SMI_CHECK,
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PointersToHereCheck pointers_to_here_check_for_value =
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          kPointersToHereMaybeInteresting);
3318defd9ff6930b4e24729971a61cf7469daf119beSteve Block
3323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Push a handle.
3333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Push(Handle<Object> handle);
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); }
3353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Push two registers.  Pushes leftmost register first (to highest address).
3376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Push(Register src1, Register src2, Condition cond = al) {
3386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (src1.code() > src2.code()) {
3396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      stm(db_w, sp, src1.bit() | src2.bit(), cond);
3406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
3416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      str(src1, MemOperand(sp, 4, NegPreIndex), cond);
3426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      str(src2, MemOperand(sp, 4, NegPreIndex), cond);
3436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
3446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Push three registers.  Pushes leftmost register first (to highest address).
3476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Push(Register src1, Register src2, Register src3, Condition cond = al) {
3486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (src1.code() > src2.code()) {
3496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (src2.code() > src3.code()) {
3506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
3516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
3526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        stm(db_w, sp, src1.bit() | src2.bit(), cond);
3536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        str(src3, MemOperand(sp, 4, NegPreIndex), cond);
3546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
3556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
3566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      str(src1, MemOperand(sp, 4, NegPreIndex), cond);
3576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Push(src2, src3, cond);
3586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
3596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Push four registers.  Pushes leftmost register first (to highest address).
3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Push(Register src1,
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Register src2,
3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Register src3,
3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Register src4,
3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Condition cond = al) {
3676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (src1.code() > src2.code()) {
3686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (src2.code() > src3.code()) {
3696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (src3.code() > src4.code()) {
3706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          stm(db_w,
3716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              sp,
3726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              src1.bit() | src2.bit() | src3.bit() | src4.bit(),
3736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              cond);
3746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        } else {
3756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
3766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          str(src4, MemOperand(sp, 4, NegPreIndex), cond);
3776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
3786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
3796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        stm(db_w, sp, src1.bit() | src2.bit(), cond);
3806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Push(src3, src4, cond);
3816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
3826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
3836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      str(src1, MemOperand(sp, 4, NegPreIndex), cond);
3846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Push(src2, src3, src4, cond);
3856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
3866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Push five registers.  Pushes leftmost register first (to highest address).
389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Push(Register src1, Register src2, Register src3, Register src4,
390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Register src5, Condition cond = al) {
391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (src1.code() > src2.code()) {
392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (src2.code() > src3.code()) {
393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (src3.code() > src4.code()) {
394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (src4.code() > src5.code()) {
395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            stm(db_w, sp,
396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                src1.bit() | src2.bit() | src3.bit() | src4.bit() | src5.bit(),
397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                cond);
398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else {
399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            stm(db_w, sp, src1.bit() | src2.bit() | src3.bit() | src4.bit(),
400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                cond);
401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            str(src5, MemOperand(sp, 4, NegPreIndex), cond);
402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else {
404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Push(src4, src5, cond);
406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        stm(db_w, sp, src1.bit() | src2.bit(), cond);
409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Push(src3, src4, src5, cond);
410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      str(src1, MemOperand(sp, 4, NegPreIndex), cond);
413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Push(src2, src3, src4, src5, cond);
414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
417e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Pop two registers. Pops rightmost register first (from lower address).
418e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void Pop(Register src1, Register src2, Condition cond = al) {
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!src1.is(src2));
420e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (src1.code() > src2.code()) {
421e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
423e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ldr(src2, MemOperand(sp, 4, PostIndex), cond);
424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ldr(src1, MemOperand(sp, 4, PostIndex), cond);
425e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
426e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
427e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Pop three registers.  Pops rightmost register first (from lower address).
4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Pop(Register src1, Register src2, Register src3, Condition cond = al) {
430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!AreAliased(src1, src2, src3));
4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (src1.code() > src2.code()) {
4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (src2.code() > src3.code()) {
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ldr(src3, MemOperand(sp, 4, PostIndex), cond);
4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Pop(src2, src3, cond);
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ldr(src1, MemOperand(sp, 4, PostIndex), cond);
4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Pop four registers.  Pops rightmost register first (from lower address).
4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Pop(Register src1,
4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Register src2,
4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Register src3,
4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Register src4,
4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Condition cond = al) {
450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!AreAliased(src1, src2, src3, src4));
4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (src1.code() > src2.code()) {
4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (src2.code() > src3.code()) {
4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (src3.code() > src4.code()) {
4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ldm(ia_w,
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              sp,
4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              src1.bit() | src2.bit() | src3.bit() | src4.bit(),
4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              cond);
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ldr(src4, MemOperand(sp, 4, PostIndex), cond);
4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Pop(src3, src4, cond);
4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Pop(src2, src3, src4, cond);
4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ldr(src1, MemOperand(sp, 4, PostIndex), cond);
4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push a fixed frame, consisting of lr, fp, constant pool (if
4733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // FLAG_enable_embedded_constant_pool)
4743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void PushCommonFrame(Register marker_reg = no_reg);
4753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
4763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Push a standard frame, consisting of lr, fp, constant pool (if
4773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // FLAG_enable_embedded_constant_pool), context and JS function
4783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void PushStandardFrame(Register function_reg);
4793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
4803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void PopCommonFrame(Register marker_reg = no_reg);
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Push and pop the registers that can hold pointers, as defined by the
483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // RegList constant kSafepointSavedRegisters.
484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void PushSafepointRegisters();
485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void PopSafepointRegisters();
486e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Store value in register src in the safepoint stack slot for
487e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // register dst.
488e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void StoreToSafepointRegisterSlot(Register src, Register dst);
489e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Load the value of the src register from its safepoint stack slot
490e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // into register dst.
491e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void LoadFromSafepointRegisterSlot(Register dst, Register src);
492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Load two consecutive registers with two consecutive memory locations.
494f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  void Ldrd(Register dst1,
495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            Register dst2,
496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            const MemOperand& src,
497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            Condition cond = al);
498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Store two consecutive registers to two consecutive memory locations.
500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  void Strd(Register src1,
501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            Register src2,
502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            const MemOperand& dst,
503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            Condition cond = al);
504f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the value is a NaN, canonicalize the value else, do nothing.
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VFPCanonicalizeNaN(const DwVfpRegister dst,
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          const DwVfpRegister src,
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          const Condition cond = al);
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VFPCanonicalizeNaN(const DwVfpRegister value,
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          const Condition cond = al) {
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VFPCanonicalizeNaN(value, value, cond);
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
513b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Compare single values and move the result to the normal condition flags.
515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void VFPCompareAndSetFlags(const SwVfpRegister src1, const SwVfpRegister src2,
516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                             const Condition cond = al);
517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void VFPCompareAndSetFlags(const SwVfpRegister src1, const float src2,
518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                             const Condition cond = al);
519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
520b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Compare double values and move the result to the normal condition flags.
521b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void VFPCompareAndSetFlags(const DwVfpRegister src1,
522b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                             const DwVfpRegister src2,
523b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                             const Condition cond = al);
524b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void VFPCompareAndSetFlags(const DwVfpRegister src1,
525b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                             const double src2,
526b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                             const Condition cond = al);
527b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Compare single values and then load the fpscr flags to a register.
529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void VFPCompareAndLoadFlags(const SwVfpRegister src1,
530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              const SwVfpRegister src2,
531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              const Register fpscr_flags,
532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              const Condition cond = al);
533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void VFPCompareAndLoadFlags(const SwVfpRegister src1, const float src2,
534014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              const Register fpscr_flags,
535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              const Condition cond = al);
536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
537b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Compare double values and then load the fpscr flags to a register.
538b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void VFPCompareAndLoadFlags(const DwVfpRegister src1,
539b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              const DwVfpRegister src2,
540b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              const Register fpscr_flags,
541b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              const Condition cond = al);
542b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void VFPCompareAndLoadFlags(const DwVfpRegister src1,
543b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              const double src2,
544b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              const Register fpscr_flags,
545b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                              const Condition cond = al);
546b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
5473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Vmov(const DwVfpRegister dst,
5483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            const double imm,
549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            const Register scratch = no_reg);
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VmovHigh(Register dst, DwVfpRegister src);
552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VmovHigh(DwVfpRegister dst, Register src);
553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VmovLow(Register dst, DwVfpRegister src);
554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VmovLow(DwVfpRegister dst, Register src);
555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
556c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Simulate s-register moves for imaginary s32 - s63 registers.
557c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void VmovExtended(Register dst, int src_code);
558c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void VmovExtended(int dst_code, Register src);
559c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Move between s-registers and imaginary s-registers.
560c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void VmovExtended(int dst_code, int src_code, Register scratch);
561c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void VmovExtended(int dst_code, const MemOperand& src, Register scratch);
562c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void VmovExtended(const MemOperand& dst, int src_code, Register scratch);
563c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
56462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void ExtractLane(Register dst, QwNeonRegister src, NeonDataType dt, int lane);
56562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void ExtractLane(SwVfpRegister dst, QwNeonRegister src, Register scratch,
56662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                   int lane);
56762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void ReplaceLane(QwNeonRegister dst, QwNeonRegister src, Register src_lane,
56862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                   NeonDataType dt, int lane);
56962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void ReplaceLane(QwNeonRegister dst, QwNeonRegister src,
57062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                   SwVfpRegister src_lane, Register scratch, int lane);
57162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void Swizzle(QwNeonRegister dst, QwNeonRegister src, Register scratch,
57262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch               NeonSize size, uint32_t lanes);
57362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
5743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void LslPair(Register dst_low, Register dst_high, Register src_low,
5753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch               Register src_high, Register scratch, Register shift);
5763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void LslPair(Register dst_low, Register dst_high, Register src_low,
5773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch               Register src_high, uint32_t shift);
5783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void LsrPair(Register dst_low, Register dst_high, Register src_low,
5793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch               Register src_high, Register scratch, Register shift);
5803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void LsrPair(Register dst_low, Register dst_high, Register src_low,
5813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch               Register src_high, uint32_t shift);
5823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void AsrPair(Register dst_low, Register dst_high, Register src_low,
5833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch               Register src_high, Register scratch, Register shift);
5843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void AsrPair(Register dst_low, Register dst_high, Register src_low,
5853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch               Register src_high, uint32_t shift);
5863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loads the number from object into dst register.
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If |object| is neither smi nor heap number, |not_number| is jumped to
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // with |object| still intact.
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void LoadNumber(Register object,
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  LowDwVfpRegister dst,
592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Register heap_number_map,
593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Register scratch,
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Label* not_number);
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loads the number from object into double_dst in the double format.
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Control will jump to not_int32 if the value cannot be exactly represented
598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // by a 32-bit integer.
599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Floating point value in the 32-bit integer range that are not exact integer
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // won't be loaded.
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void LoadNumberAsInt32Double(Register object,
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               DwVfpRegister double_dst,
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register heap_number_map,
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register scratch,
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               LowDwVfpRegister double_scratch,
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* not_int32);
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loads the number from object into dst as a 32-bit integer.
609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Control will jump to not_int32 if the object cannot be exactly represented
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // by a 32-bit integer.
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Floating point value in the 32-bit integer range that are not exact integer
612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // won't be converted.
613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void LoadNumberAsInt32(Register object,
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register dst,
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register heap_number_map,
616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register scratch,
617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         DwVfpRegister double_scratch0,
618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         LowDwVfpRegister double_scratch1,
619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Label* not_int32);
620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Generates function and stub prologue code.
6223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void StubPrologue(StackFrame::Type type);
623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Prologue(bool code_pre_aging);
6243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
62580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Enter exit frame.
6261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // stack_space - extra stack space, used for alignment before call to C.
627f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void EnterExitFrame(bool save_doubles, int stack_space = 0,
628f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                      StackFrame::Type frame_type = StackFrame::EXIT);
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Leave the current exit frame. Expects the return value in r0.
631e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Expect the number of values, pushed prior to the exit frame, to
632e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // remove in a register (or no_reg, if there is nothing to remove).
633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LeaveExitFrame(bool save_doubles, Register argument_count,
634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      bool restore_context,
635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      bool argument_count_is_length = false);
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the actual activation frame alignment for target environment.
6386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static int ActivationFrameAlignment();
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
640d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void LoadContext(Register dst, int context_chain_length);
641d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load the global object from the current context.
643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LoadGlobalObject(Register dst) {
644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LoadNativeContextSlot(Context::EXTENSION_INDEX, dst);
645014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
646014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load the global proxy from the current context.
648014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LoadGlobalProxy(Register dst) {
649014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LoadNativeContextSlot(Context::GLOBAL_PROXY_INDEX, dst);
650014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
651014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
652014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LoadNativeContextSlot(int index, Register dst);
6538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the initial map from the global function. The registers
6558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // function and map can be the same, function is then overwritten.
6568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  void LoadGlobalFunctionInitialMap(Register function,
6578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                    Register map,
6588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                    Register scratch);
6598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
660c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  void InitializeRootRegister() {
6613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExternalReference roots_array_start =
6623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ExternalReference::roots_array_start(isolate());
6633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mov(kRootRegister, Operand(roots_array_start));
664c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  }
665c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // JavaScript invokes
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Removes current frame and its arguments from the stack preserving
6703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // the arguments and a return address pushed to the stack for the next call.
6713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Both |callee_args_count| and |caller_args_count_reg| do not include
6723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // receiver. |callee_args_count| is not modified, |caller_args_count_reg|
6733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // is trashed.
6743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void PrepareForTailCall(const ParameterCount& callee_args_count,
6753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                          Register caller_args_count_reg, Register scratch0,
6763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                          Register scratch1);
6773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the JavaScript function code by either calling or jumping.
679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void InvokeFunctionCode(Register function, Register new_target,
680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                          const ParameterCount& expected,
681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                          const ParameterCount& actual, InvokeFlag flag,
682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                          const CallWrapper& call_wrapper);
683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
68462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // On function call, call into the debugger if necessary.
68562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void CheckDebugHook(Register fun, Register new_target,
68662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      const ParameterCount& expected,
68762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      const ParameterCount& actual);
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the JavaScript function in the given register. Changes the
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // current context to the context in the function before invoking.
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void InvokeFunction(Register function,
692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      Register new_target,
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      const ParameterCount& actual,
694b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                      InvokeFlag flag,
695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const CallWrapper& call_wrapper);
696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void InvokeFunction(Register function,
698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const ParameterCount& expected,
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const ParameterCount& actual,
700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      InvokeFlag flag,
701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const CallWrapper& call_wrapper);
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void InvokeFunction(Handle<JSFunction> function,
704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const ParameterCount& expected,
705402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                      const ParameterCount& actual,
706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      InvokeFlag flag,
707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const CallWrapper& call_wrapper);
708402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void IsObjectJSStringType(Register object,
710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            Register scratch,
711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            Label* fail);
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void IsObjectNameType(Register object,
714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        Register scratch,
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        Label* fail);
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
71762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Frame restart support
71862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void MaybeDropFrames();
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Exception handling
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Push a new stack handler and link into stack handler chain.
723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void PushStackHandler();
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Unlink the stack handler on top of the stack from the stack handler chain.
726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Must preserve the result register.
727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void PopStackHandler();
728e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Inline caching support
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
732c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  void GetNumberHash(Register t0, Register scratch);
7333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  inline void MarkCode(NopMarkerTypes type) {
7358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    nop(type);
7368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
7378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
7388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check if the given instruction is a 'type' marker.
7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // i.e. check if is is a mov r<type>, r<type> (referenced as nop(type))
7408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // These instructions are generated to mark special location in the code,
7418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // like some special IC code.
7428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  static inline bool IsMarkedCode(Instr instr, int type) {
743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER));
7448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    return IsNop(instr, type);
7458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
7468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
7478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
7488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  static inline int GetCodeMarker(Instr instr) {
7498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    int dst_reg_offset = 12;
7508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    int dst_mask = 0xf << dst_reg_offset;
7518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    int src_mask = 0xf;
7528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    int dst_reg = (instr & dst_mask) >> dst_reg_offset;
7538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    int src_reg = instr & src_mask;
7548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    uint32_t non_register_mask = ~(dst_mask | src_mask);
7558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    uint32_t mov_mask = al | 13 << 21;
7568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
7578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    // Return <n> if we have a mov rn rn, else return -1.
7588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    int type = ((instr & non_register_mask) == mov_mask) &&
7598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang               (dst_reg == src_reg) &&
7608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang               (FIRST_IC_MARKER <= dst_reg) && (dst_reg < LAST_CODE_MARKER)
7618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                   ? src_reg
7628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                   : -1;
763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK((type == -1) ||
7648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang           ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)));
7658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    return type;
7668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
7678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocation support
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
772014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allocate an object in new space or old space. The object_size is
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // specified either in bytes or in words if the allocation flag SIZE_IN_WORDS
774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // is passed. If the space is exhausted control continues at the gc_required
775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // label. The allocated object is returned in result. If the flag
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // tag_allocated_object is true the result is tagged as as a heap object.
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // All registers are clobbered also when control continues at the gc_required
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // label.
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Allocate(int object_size,
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register result,
781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register scratch1,
782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Register scratch2,
783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Label* gc_required,
784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                AllocationFlags flags);
785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Allocate(Register object_size, Register result, Register result_end,
787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                Register scratch, Label* gc_required, AllocationFlags flags);
7883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
789bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // FastAllocate is right now only used for folded allocations. It just
790bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // increments the top pointer without checking against limit. This can only
791bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // be done if it was proved earlier that the allocation will succeed.
792bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void FastAllocate(int object_size, Register result, Register scratch1,
793bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                    Register scratch2, AllocationFlags flags);
794bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
795bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void FastAllocate(Register object_size, Register result, Register result_end,
796bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                    Register scratch, AllocationFlags flags);
797bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
79825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // Allocates a heap number or jumps to the gc_required label if the young
79925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // space is full and a scavenge is needed. All registers are clobbered also
80025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // when control continues at the gc_required label.
8016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void AllocateHeapNumber(Register result,
8026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                          Register scratch1,
8036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                          Register scratch2,
8049dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                          Register heap_number_map,
805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          Label* gc_required,
806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          MutableMode mode = IMMUTABLE);
8078defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void AllocateHeapNumberWithValue(Register result,
8088defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   DwVfpRegister value,
8098defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Register scratch1,
8108defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Register scratch2,
8118defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Register heap_number_map,
8128defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Label* gc_required);
8138defd9ff6930b4e24729971a61cf7469daf119beSteve Block
814014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allocate and initialize a JSValue wrapper with the specified {constructor}
815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // and {value}.
816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void AllocateJSValue(Register result, Register constructor, Register value,
817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       Register scratch1, Register scratch2,
818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       Label* gc_required);
8193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Initialize fields with filler values.  Fields starting at |current_address|
821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // not including |end_address| are overwritten with the value in |filler|.  At
822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // the end the loop, |current_address| takes the value of |end_address|.
823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void InitializeFieldsWithFiller(Register current_address,
824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  Register end_address, Register filler);
8253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Support functions.
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Machine code version of Map::GetConstructor().
830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // |temp| holds |result|'s map when done, and |temp2| its instance type.
831014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void GetMapConstructor(Register result, Register map, Register temp,
832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         Register temp2);
833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compare object type for heap object.  heap_object contains a non-Smi
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // whose object type should be compared with the given type.  This both
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sets the flags and leaves the object type in the type_reg register.
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // It leaves the map in the map register (unless the type_reg and map register
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // are the same register).  It leaves the heap object in the heap_object
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // register unless the heap_object register is the same register as one of the
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // other registers.
841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Type_reg can be no_reg. In that case ip is used.
842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CompareObjectType(Register heap_object,
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         Register map,
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         Register type_reg,
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         InstanceType type);
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compare instance type in a map.  map contains a valid map object whose
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object type should be compared with the given type.  This both
849589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // sets the flags and leaves the object type in the type_reg register.
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CompareInstanceType(Register map,
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           Register type_reg,
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           InstanceType type);
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Compare an object's map with the specified map and its transitioned
8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Condition flags are
8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // set with result of map compare. If multiple map compares are required, the
8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // compare sequences branches to early_success.
8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CompareMap(Register obj,
8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Register scratch,
8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Handle<Map> map,
861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Label* early_success);
862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // As above, but the map of the object is already loaded into the register
864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // which is preserved by the code generated.
865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CompareMap(Register obj_map,
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Handle<Map> map,
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  Label* early_success);
8683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if the map of an object is equal to a specified map and branch to
8703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // label if not. Skip the smi check if not required (object is known to be a
8713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
8723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // against maps that are ElementsKind transition maps of the specified map.
8733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void CheckMap(Register obj,
8743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                Register scratch,
8753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                Handle<Map> map,
8763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                Label* fail,
877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                SmiCheckType smi_check_type);
878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
8793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
8807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  void CheckMap(Register obj,
8817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                Register scratch,
8827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                Heap::RootListIndex index,
8837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                Label* fail,
884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                SmiCheckType smi_check_type);
885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
887958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check if the map of an object is equal to a specified weak map and branch
888958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // to a specified target if equal. Skip the smi check if not required
889958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // (object is known to be a heap object)
890958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void DispatchWeakMap(Register obj, Register scratch1, Register scratch2,
891958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       Handle<WeakCell> cell, Handle<Code> success,
892958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       SmiCheckType smi_check_type);
893958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
894958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Compare the given value and the value of weak cell.
895958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void CmpWeakValue(Register value, Handle<WeakCell> cell, Register scratch);
8967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void GetWeakValue(Register value, Handle<WeakCell> cell);
898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
899958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Load the value of the weak cell in the value register. Branch to the given
900958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // miss label if the weak cell was cleared.
901958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void LoadWeakValue(Register value, Handle<WeakCell> cell, Label* miss);
9027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
903e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Compare the object in a register to a value from the root list.
904e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Uses the ip register as scratch.
905e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void CompareRoot(Register obj, Heap::RootListIndex index);
906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void PushRoot(Heap::RootListIndex index) {
907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LoadRoot(ip, index);
908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Push(ip);
909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
910e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Compare the object in a register to a value and jump if they are equal.
912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void JumpIfRoot(Register with, Heap::RootListIndex index, Label* if_equal) {
913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CompareRoot(with, index);
914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    b(eq, if_equal);
915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Compare the object in a register to a value and jump if they are not equal.
918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void JumpIfNotRoot(Register with, Heap::RootListIndex index,
919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     Label* if_not_equal) {
920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CompareRoot(with, index);
921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    b(ne, if_not_equal);
922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
923e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
9243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Load and check the instance type of an object for being a string.
9253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Loads the type into the second argument register.
926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Returns a condition that will be enabled if the object was a string
927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // and the passed-in condition passed. If the passed-in condition failed
928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // then flags remain unchanged.
9293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Condition IsObjectStringType(Register obj,
930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register type,
931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Condition cond = al) {
932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset), cond);
933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset), cond);
934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    tst(type, Operand(kIsNotStringMask), cond);
935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_EQ(0u, kStringTag);
9363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    return eq;
9373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
9383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
9403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Get the number of least significant bits from a register
9413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits);
9421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits);
9433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the value of a smi object into a double register.
945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The register value must be between d0 and d15.
946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SmiToDouble(LowDwVfpRegister value, Register smi);
947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if a double can be exactly represented as a signed 32-bit integer.
949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Z flag set to one if true.
950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TestDoubleIsInt32(DwVfpRegister double_input,
951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         LowDwVfpRegister double_scratch);
952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Try to convert a double to a signed 32-bit integer.
954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Z flag set to one and result assigned if the conversion is exact.
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TryDoubleToInt32Exact(Register result,
956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             DwVfpRegister double_input,
957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             LowDwVfpRegister double_scratch);
958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Floor a double and writes the value to the result register.
960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Go to exact if the conversion is exact (to be able to test -0),
961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // fall through calling code if an overflow occurred, else go to done.
962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // In return, input_high is loaded with high bits of input.
963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TryInt32Floor(Register result,
964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     DwVfpRegister double_input,
965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     Register input_high,
966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     LowDwVfpRegister double_scratch,
967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     Label* done,
968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     Label* exact);
969d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Performs a truncating conversion of a floating point number as used by
971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it
972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // succeeds, otherwise falls through if result is saturated. On return
973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // 'result' either holds answer, or is clobbered on fall through.
974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Only public for the test code in test-code-stubs-arm.cc.
976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TryInlineTruncateDoubleToI(Register result,
977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  DwVfpRegister input,
978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  Label* done);
97944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
98044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Performs a truncating conversion of a floating point number as used by
98144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // the JS bitwise operations. See ECMA-262 9.5: ToInt32.
982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Exits with 'result' holding the answer.
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TruncateDoubleToI(Register result, DwVfpRegister double_input);
984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Performs a truncating conversion of a heap number as used by
986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 'result' and 'input'
987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // must be different registers.  Exits with 'result' holding the answer.
988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TruncateHeapNumberToI(Register result, Register object);
989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Converts the smi or heap number in object to an int32 using the rules
991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // for ToInt32 as described in ECMAScript 9.5.: the value is truncated
992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // and brought into the range -2^31 .. +2^31 - 1. 'result' and 'input' must be
993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // different registers.
994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TruncateNumberToI(Register object,
995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register result,
996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register heap_number_map,
997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Register scratch1,
998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Label* not_int32);
999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check whether d16-d31 are available on the CPU. The result is given by the
1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Z condition flag: Z==0 if d16-d31 available, Z==1 otherwise.
1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CheckFor32DRegs(Register scratch);
1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Does a runtime check for 16/32 FP registers. Either way, pushes 32 double
1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // values to location, saving [d0..(d15|d31)].
1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SaveFPRegs(Register location, Register scratch);
1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Does a runtime check for 16/32 FP registers. Either way, pops 32 double
1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // values to location, restoring [d0..(d15|d31)].
1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RestoreFPRegs(Register location, Register scratch);
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1012f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Perform a floating-point min or max operation with the
1013f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // (IEEE-754-compatible) semantics of ARM64's fmin/fmax. Some cases, typically
1014f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // NaNs or +/-0.0, are expected to be rare and are handled in out-of-line
1015f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // code. The specific behaviour depends on supported instructions.
1016f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  //
1017f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // These functions assume (and assert) that !left.is(right). It is permitted
1018f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // for the result to alias either input register.
1019f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMax(SwVfpRegister result, SwVfpRegister left, SwVfpRegister right,
1020f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                Label* out_of_line);
1021f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMin(SwVfpRegister result, SwVfpRegister left, SwVfpRegister right,
1022f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                Label* out_of_line);
1023f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMax(DwVfpRegister result, DwVfpRegister left, DwVfpRegister right,
1024f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                Label* out_of_line);
1025f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMin(DwVfpRegister result, DwVfpRegister left, DwVfpRegister right,
1026f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                Label* out_of_line);
1027f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1028f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Generate out-of-line cases for the macros above.
1029f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMaxOutOfLine(SwVfpRegister result, SwVfpRegister left,
1030f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                         SwVfpRegister right);
1031f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMinOutOfLine(SwVfpRegister result, SwVfpRegister left,
1032f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                         SwVfpRegister right);
1033f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMaxOutOfLine(DwVfpRegister result, DwVfpRegister left,
1034f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                         DwVfpRegister right);
1035f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMinOutOfLine(DwVfpRegister result, DwVfpRegister left,
1036f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                         DwVfpRegister right);
1037f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Runtime calls
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call a code stub.
1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CallStub(CodeStub* stub,
1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                TypeFeedbackId ast_id = TypeFeedbackId::None(),
1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Condition cond = al);
1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Call a code stub.
10473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void TailCallStub(CodeStub* stub, Condition cond = al);
10483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call a runtime routine.
1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CallRuntime(const Runtime::Function* f,
1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   int num_arguments,
1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   SaveFPRegsMode save_doubles = kDontSaveFPRegs);
1053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void CallRuntimeSaveDoubles(Runtime::FunctionId fid) {
1054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    const Runtime::Function* function = Runtime::FunctionForId(fid);
1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallRuntime(function, function->nargs, kSaveFPRegs);
1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Convenience function: Same as above, but takes the fid instead.
1059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void CallRuntime(Runtime::FunctionId fid,
1060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   SaveFPRegsMode save_doubles = kDontSaveFPRegs) {
1061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    const Runtime::Function* function = Runtime::FunctionForId(fid);
1062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallRuntime(function, function->nargs, save_doubles);
1063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Convenience function: Same as above, but takes the fid instead.
1066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void CallRuntime(Runtime::FunctionId fid, int num_arguments,
1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   SaveFPRegsMode save_doubles = kDontSaveFPRegs) {
1068014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallRuntime(Runtime::FunctionForId(fid), num_arguments, save_doubles);
1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1071402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Convenience function: call an external reference.
1072402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void CallExternalReference(const ExternalReference& ext,
1073402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                             int num_arguments);
1074402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
10756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Convenience function: tail call a runtime routine (jump).
1076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void TailCallRuntime(Runtime::FunctionId fid);
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int CalculateStackPassedWords(int num_reg_arguments,
1079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                int num_double_arguments);
1080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Before calling a C-function from generated code, align arguments on stack.
10826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // After aligning the frame, non-register arguments must be stored in
10836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments
1084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // are word sized. If double arguments are used, this function assumes that
1085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // all double arguments are stored before core registers; otherwise the
1086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // correct alignment of the double values is not guaranteed.
10876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Some compilers/platforms require the stack to be aligned when calling
10886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // C++ code.
10896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Needs a scratch register to do some arithmetic. This register will be
10906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // trashed.
1091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void PrepareCallCFunction(int num_reg_arguments,
1092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            int num_double_registers,
1093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register scratch);
1094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void PrepareCallCFunction(int num_reg_arguments,
1095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register scratch);
1096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // There are two ways of passing double arguments on ARM, depending on
1098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // whether soft or hard floating point ABI is used. These functions
1099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // abstract parameter passing for the three different ways we call
1100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // C functions from generated code.
1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MovToFloatParameter(DwVfpRegister src);
1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MovToFloatParameters(DwVfpRegister src1, DwVfpRegister src2);
1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MovToFloatResult(DwVfpRegister src);
11046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Calls a C function and cleans up the space for arguments allocated
11066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // by PrepareCallCFunction. The called function is not allowed to trigger a
11076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // garbage collection, since that might move the code and invalidate the
11086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // return address (unless this is somehow accounted for by the called
11096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // function).
11106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void CallCFunction(ExternalReference function, int num_arguments);
11113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CallCFunction(Register function, int num_arguments);
1112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void CallCFunction(ExternalReference function,
1113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     int num_reg_arguments,
1114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     int num_double_arguments);
11153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CallCFunction(Register function,
1116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     int num_reg_arguments,
1117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     int num_double_arguments);
11186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MovFromFloatParameter(DwVfpRegister dst);
1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MovFromFloatResult(DwVfpRegister dst);
1121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to a runtime routine.
1123f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void JumpToExternalReference(const ExternalReference& builtin,
1124f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                               bool builtin_exit_frame = false);
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<Object> CodeObject() {
1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!code_object_.is_null());
11288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return code_object_;
11298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Emit code for a truncating division by a constant. The dividend register is
1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // unchanged and ip gets clobbered. Dividend and result must be different.
1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TruncatingDiv(Register result, Register dividend, int32_t divisor);
1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // StatsCounter support
1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void SetCounter(StatsCounter* counter, int value,
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  Register scratch1, Register scratch2);
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void IncrementCounter(StatsCounter* counter, int value,
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        Register scratch1, Register scratch2);
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void DecrementCounter(StatsCounter* counter, int value,
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        Register scratch1, Register scratch2);
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Debugging
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Calls Abort(msg) if the condition cond is not satisfied.
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use --debug_code to enable.
1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Assert(Condition cond, BailoutReason reason);
1153756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void AssertFastElements(Register elements);
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Like Assert(), but always enabled.
1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Check(Condition cond, BailoutReason reason);
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print a message to stdout and abort execution.
1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Abort(BailoutReason msg);
1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Verify restrictions about code generated in stubs.
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void set_generating_stub(bool value) { generating_stub_ = value; }
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool generating_stub() { return generating_stub_; }
11643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void set_has_frame(bool value) { has_frame_ = value; }
11653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool has_frame() { return has_frame_; }
11663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline bool AllowThisStubCall(CodeStub* stub);
1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // EABI variant for double arguments in use.
1169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool use_eabi_hardfloat() {
1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef __arm__
1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return base::OS::ArmUsingHardFloat();
1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#elif USE_EABI_HARDFLOAT
1173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return true;
1174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#else
1175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return false;
1176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
1177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1179d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // ---------------------------------------------------------------------------
11801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Number utilities
11811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
11821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check whether the value of reg is a power of two and not zero. If not
11831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // control continues at the label not_power_of_two. If reg is a power of two
11841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // the register scratch contains the value of (reg - 1) when control falls
11851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // through.
11861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void JumpIfNotPowerOfTwoOrZero(Register reg,
11871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                 Register scratch,
11881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                 Label* not_power_of_two_or_zero);
118944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check whether the value of reg is a power of two and not zero.
119044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Control falls through if it is, with scratch containing the mask
119144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // value (reg - 1).
119244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Otherwise control jumps to the 'zero_and_neg' label if the value of reg is
119344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // zero or negative, or jumps to the 'not_power_of_two' label if the value is
119444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // strictly positive but not a power of two.
119544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg,
119644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       Register scratch,
119744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       Label* zero_and_neg,
119844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       Label* not_power_of_two);
11991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ---------------------------------------------------------------------------
12013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Smi utilities
12023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void SmiTag(Register reg, SBit s = LeaveCC) {
1204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    add(reg, reg, Operand(reg), s);
1205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
12061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void SmiTag(Register dst, Register src, SBit s = LeaveCC) {
12071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    add(dst, src, Operand(src), s);
12081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1210b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Try to convert int32 to smi. If the value is to large, preserve
1211b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // the original value and jump to not_a_smi. Destroys scratch and
1212b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // sets flags.
1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TrySmiTag(Register reg, Label* not_a_smi) {
1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TrySmiTag(reg, reg, not_a_smi);
1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TrySmiTag(Register reg, Register src, Label* not_a_smi) {
1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiTag(ip, src, SetCC);
1218b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    b(vs, not_a_smi);
1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(reg, ip);
1220b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1221b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void SmiUntag(Register reg, SBit s = LeaveCC) {
1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(reg, Operand::SmiUntag(reg), s);
1225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void SmiUntag(Register dst, Register src, SBit s = LeaveCC) {
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mov(dst, Operand::SmiUntag(src), s);
12281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
12303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Untag the source value into destination and jump if source is a smi.
12313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Souce and destination can be the same register.
12323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case);
12333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test if the register contains a smi (Z == 0 (eq) if true).
1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void SmiTst(Register value) {
1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    tst(value, Operand(kSmiTagMask));
1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void NonNegativeSmiTst(Register value) {
1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    tst(value, Operand(kSmiTagMask | kSmiSignMask));
1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Jump if the register contains a smi.
12421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  inline void JumpIfSmi(Register value, Label* smi_label) {
12431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    tst(value, Operand(kSmiTagMask));
12441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    b(eq, smi_label);
12451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
12461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Jump if either of the registers contain a non-smi.
12471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  inline void JumpIfNotSmi(Register value, Label* not_smi_label) {
12481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    tst(value, Operand(kSmiTagMask));
12491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    b(ne, not_smi_label);
12501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
12513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Jump if either of the registers contain a non-smi.
12523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi);
12533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Jump if either of the registers contain a smi.
12543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi);
12553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Abort execution if argument is a number, enabled via --debug-code.
12573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void AssertNotNumber(Register object);
12583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Abort execution if argument is a smi, enabled via --debug-code.
1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AssertNotSmi(Register object);
1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AssertSmi(Register object);
1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Abort execution if argument is not a string, enabled via --debug-code.
1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AssertString(Register object);
12651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Abort execution if argument is not a name, enabled via --debug-code.
1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AssertName(Register object);
1268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Abort execution if argument is not a JSFunction, enabled via --debug-code.
1270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void AssertFunction(Register object);
1271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Abort execution if argument is not a JSBoundFunction,
1273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // enabled via --debug-code.
1274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void AssertBoundFunction(Register object);
1275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1276bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Abort execution if argument is not a JSGeneratorObject,
1277bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // enabled via --debug-code.
1278bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void AssertGeneratorObject(Register object);
1279bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1280109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Abort execution if argument is not a JSReceiver, enabled via --debug-code.
1281109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void AssertReceiver(Register object);
1282109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Abort execution if argument is not undefined or an AllocationSite, enabled
1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // via --debug-code.
1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AssertUndefinedOrAllocationSite(Register object, Register scratch);
1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Abort execution if reg is not the root value with the given index,
1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // enabled via --debug-code.
1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AssertIsRoot(Register reg, Heap::RootListIndex index);
12901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ---------------------------------------------------------------------------
12921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // HeapNumber utilities
12931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void JumpIfNotHeapNumber(Register object,
12951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                           Register heap_number_map,
12961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                           Register scratch,
12971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                           Label* on_not_heap_number);
1298756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
12993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // ---------------------------------------------------------------------------
1300d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // String utilities
1301d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Checks if both objects are sequential one-byte strings and jumps to label
1303d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // if either is not. Assumes that neither object is a smi.
1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfNonSmisNotBothSequentialOneByteStrings(Register object1,
1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                    Register object2,
1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                    Register scratch1,
1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                    Register scratch2,
1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                    Label* failure);
1309d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Checks if both objects are sequential one-byte strings and jumps to label
1311d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // if either is not.
1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfNotBothSequentialOneByteStrings(Register first, Register second,
1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             Register scratch1,
1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             Register scratch2,
1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             Label* not_flat_one_byte_strings);
1316d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Checks if both instance types are sequential one-byte strings and jumps to
13186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // label if either is not.
1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfBothInstanceTypesAreNotSequentialOneByte(
1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register first_object_instance_type, Register second_object_instance_type,
1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register scratch1, Register scratch2, Label* failure);
1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void JumpIfNotUniqueNameInstanceType(Register reg, Label* not_unique_name);
13246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmitSeqStringSetCharCheck(Register string,
1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register index,
1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register value,
1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 uint32_t encoding_mask);
13296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void ClampUint8(Register output_reg, Register input_reg);
1332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void ClampDoubleToUint8(Register result_reg,
1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          DwVfpRegister input_reg,
1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          LowDwVfpRegister double_scratch);
1336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void LoadInstanceDescriptors(Register map, Register descriptors);
1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EnumLength(Register dst, Register map);
1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void NumberOfOwnDescriptors(Register dst, Register map);
1341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LoadAccessor(Register dst, Register holder, int accessor_index,
1342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    AccessorComponent accessor);
1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<typename Field>
1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DecodeField(Register dst, Register src) {
1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Ubfx(dst, src, Field::kShift, Field::kSize);
1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<typename Field>
1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DecodeField(Register reg) {
1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DecodeField<Field>(reg, reg);
1352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<typename Field>
1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DecodeFieldToSmi(Register dst, Register src) {
1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static const int shift = Field::kShift;
1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static const int mask = Field::kMask >> shift << kSmiTagSize;
1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT((mask & (0x80000000u >> (kSmiTagSize - 1))) == 0);
1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (shift < kSmiTagSize) {
1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mov(dst, Operand(src, LSL, kSmiTagSize - shift));
1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      and_(dst, dst, Operand(mask));
1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (shift > kSmiTagSize) {
1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mov(dst, Operand(src, LSR, shift - kSmiTagSize));
1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      and_(dst, dst, Operand(mask));
1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      and_(dst, src, Operand(mask));
1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template<typename Field>
1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DecodeFieldToSmi(Register reg) {
1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DecodeField<Field>(reg, reg);
1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load the type feedback vector from a JavaScript frame.
137762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void EmitLoadFeedbackVector(Register vector);
1378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Activation support.
1380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void EnterFrame(StackFrame::Type type,
1381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                  bool load_constant_pool_pointer_reg = false);
1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Returns the pc offset at which the frame ends.
1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int LeaveFrame(StackFrame::Type type);
13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1385f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void EnterBuiltinFrame(Register context, Register target, Register argc);
1386f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void LeaveBuiltinFrame(Register context, Register target, Register argc);
1387f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Expects object in r0 and returns map with validated enum cache
13893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // in r0.  Assumes that any other register can be used as a scratch.
1390109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void CheckEnumCache(Label* call_runtime);
13913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // AllocationMemento support. Arrays may have an associated
1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // AllocationMemento object that can be checked for in order to pretransition
1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to another type.
1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // On entry, receiver_reg should point to the array object.
1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // scratch_reg gets clobbered.
1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If allocation info is present, condition flags are set to eq.
1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TestJSArrayForAllocationMemento(Register receiver_reg,
1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Register scratch_reg,
1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Label* no_memento_found);
1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Loads the constant pool pointer (pp) register.
1403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LoadConstantPoolPointerRegisterFromCodeTargetAddress(
1404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Register code_target_address);
1405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LoadConstantPoolPointerRegister();
1406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
140844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void CallCFunctionHelper(Register function,
1409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           int num_reg_arguments,
1410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           int num_double_arguments);
141144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
14123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Helper functions for generating invokes.
1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void InvokePrologue(const ParameterCount& expected,
1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      const ParameterCount& actual,
1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Label* done,
14183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      bool* definitely_mismatches,
1419b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                      InvokeFlag flag,
1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const CallWrapper& call_wrapper);
1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
14233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void InNewSpace(Register object,
14243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Register scratch,
14253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Condition cond,  // eq for new space, ne otherwise.
14263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Label* branch);
14273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Helper for finding the mark bits for an address.  Afterwards, the
14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // bitmap register points at the word with the mark bits and the mask
14303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the position of the first bit.  Leaves addr_reg unchanged.
14313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline void GetMarkBits(Register addr_reg,
14323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          Register bitmap_reg,
14333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          Register mask_reg);
14343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1435e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Compute memory operands for safepoint stack slots.
1436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  static int SafepointRegisterStackIndex(int reg_code);
1437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  MemOperand SafepointRegisterSlot(Register reg);
1438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  MemOperand SafepointRegistersAndDoublesSlot(Register reg);
1439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1440f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Implementation helpers for FloatMin and FloatMax.
1441f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  template <typename T>
1442f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMaxHelper(T result, T left, T right, Label* out_of_line);
1443f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  template <typename T>
1444f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMinHelper(T result, T left, T right, Label* out_of_line);
1445f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  template <typename T>
1446f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMaxOutOfLineHelper(T result, T left, T right);
1447f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  template <typename T>
1448f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FloatMinOutOfLineHelper(T result, T left, T right);
1449f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
14503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  bool generating_stub_;
14513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool has_frame_;
14523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // This handle will be patched with the code object on installation.
14533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Handle<Object> code_object_;
1454e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Needs access to SafepointRegisterStackIndex for compiled frame
1456e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // traversal.
1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class StandardFrame;
1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The code patcher is used to patch (typically) small parts of code e.g. for
1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// debugging and other types of instrumentation. When using the code patcher
1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the exact number of bytes specified must be emitted. It is not legal to emit
1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// relocation information. If any of these constraints are violated it causes
1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// an assertion to fail.
1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CodePatcher {
1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum FlushICache {
1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FLUSH,
1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DONT_FLUSH
1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CodePatcher(Isolate* isolate, byte* address, int instructions,
1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              FlushICache flush_cache = FLUSH);
1475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ~CodePatcher();
1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Macro assembler to emit code.
1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MacroAssembler* masm() { return &masm_; }
1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit an instruction directly.
14811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void Emit(Instr instr);
1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit an address directly.
1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Emit(Address addr);
1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Emit the condition part of an instruction leaving the rest of the current
14871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // instruction unchanged.
14881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void EmitCondition(Condition cond);
14891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* address_;  // The address of the code being patched.
1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int size_;  // Number of bytes of the expected patch size.
1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MacroAssembler masm_;  // Macro assembler used to generate the code.
1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FlushICache flush_cache_;  // Whether to flush the I cache after patching.
1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Static helper functions.
1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochinline MemOperand ContextMemOperand(Register context, int index = 0) {
15028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return MemOperand(context, Context::SlotOffset(index));
15038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
15048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochinline MemOperand NativeContextMemOperand() {
1507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return ContextMemOperand(cp, Context::NATIVE_CONTEXT_INDEX);
15088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
15098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define ACCESS_MASM(masm) masm->
1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
1513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_ARM_MACRO_ASSEMBLER_ARM_H_
1516