macro-assembler-arm.cc revision 257744e915dfc84d6d07a6b2accf8402d9ffc708
11e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Copyright 2011 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
289ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick#include <limits.h>  // For LONG_MIN, LONG_MAX.
299ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
32f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_ARM)
33f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "bootstrapper.h"
358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "codegen.h"
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "debug.h"
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "runtime.h"
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
428b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochMacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size)
438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : Assembler(arg_isolate, buffer, size),
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      generating_stub_(false),
458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      allow_stub_calls_(true) {
468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (isolate() != NULL) {
478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    code_object_ = Handle<Object>(isolate()->heap()->undefined_value(),
488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                  isolate());
498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We always generate arm code, never thumb code, even if V8 is compiled to
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// thumb, so we require inter-working support
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if defined(__thumb__) && !defined(USE_THUMB_INTERWORK)
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#error "flag -mthumb-interwork missing"
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We do not support thumb inter-working with an arm architecture not supporting
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the blx instruction (below v5t).  If you know what CPU you are compiling for
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// you can use -march=armv7 or similar.
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if defined(USE_THUMB_INTERWORK) && !defined(CAN_USE_THUMB_INSTRUCTIONS)
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block# error "For thumb inter-working we require an architecture which supports blx"
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Using bx does not yield better code, so use it only when required
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if defined(USE_THUMB_INTERWORK)
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define USE_BX 1
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Register target, Condition cond) {
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if USE_BX
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bx(target, cond);
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(pc, Operand(target), LeaveCC, cond);
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(intptr_t target, RelocInfo::Mode rmode,
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Condition cond) {
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if USE_BX
86257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  mov(ip, Operand(target, rmode));
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bx(ip, cond);
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(pc, Operand(target, rmode), LeaveCC, cond);
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(byte* target, RelocInfo::Mode rmode,
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Condition cond) {
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!RelocInfo::IsCodeTarget(rmode));
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Jump(reinterpret_cast<intptr_t>(target), rmode, cond);
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode,
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Condition cond) {
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(RelocInfo::IsCodeTarget(rmode));
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 'code' is always generated ARM code, never THUMB code
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond);
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint MacroAssembler::CallSize(Register target, Condition cond) {
11044f0eee88ff00398ff7f715fab053374d808c90dSteve Block#if USE_BLX
11144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return kInstrSize;
11244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#else
11344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return 2 * kInstrSize;
11444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
11544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
11644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
11744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Call(Register target, Condition cond) {
11944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Block constant pool for the call instruction sequence.
12044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockConstPoolScope block_const_pool(this);
12144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int pre_position = pc_offset();
12344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
12444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if USE_BLX
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  blx(target, cond);
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // set lr for return at current pc + 8
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(lr, Operand(pc), LeaveCC, cond);
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(pc, Operand(target), LeaveCC, cond);
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
13244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
13344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
13444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int post_position = pc_offset();
13544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(pre_position + CallSize(target, cond), post_position);
13644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint MacroAssembler::CallSize(
14144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    intptr_t target, RelocInfo::Mode rmode, Condition cond) {
14244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int size = 2 * kInstrSize;
14344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Instr mov_instr = cond | MOV | LeaveCC;
14444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!Operand(target, rmode).is_single_instruction(mov_instr)) {
14544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    size += kInstrSize;
14644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
14744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return size;
14844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
14944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
15044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::Call(intptr_t target,
152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          RelocInfo::Mode rmode,
153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          Condition cond) {
15444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Block constant pool for the call instruction sequence.
15544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  BlockConstPoolScope block_const_pool(this);
15644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
15744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int pre_position = pc_offset();
15844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
15944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#if USE_BLX
1616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // On ARMv5 and after the recommended call sequence is:
1626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  ldr ip, [pc, #...]
1636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  blx ip
1646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Statement positions are expected to be recorded when the target
16644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // address is loaded. The mov method will automatically record
16744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // positions when pc is the target, since this is not the case here
16844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // we have to do it explicitly.
16944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  positions_recorder()->WriteRecordedPositions();
1706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  mov(ip, Operand(target, rmode));
17244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  blx(ip, cond);
1736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(kCallTargetAddressOffset == 2 * kInstrSize);
1756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#else
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set lr for return at current pc + 8.
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(lr, Operand(pc), LeaveCC, cond);
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit a ldr<cond> pc, [pc + offset of target in constant pool].
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(pc, Operand(target, rmode), LeaveCC, cond);
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kCallTargetAddressOffset == kInstrSize);
1816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
18244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
18344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
18444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int post_position = pc_offset();
18544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(pre_position + CallSize(target, rmode, cond), post_position);
18644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint MacroAssembler::CallSize(
19144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    byte* target, RelocInfo::Mode rmode, Condition cond) {
19244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return CallSize(reinterpret_cast<intptr_t>(target), rmode);
19344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
19444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::Call(
19744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    byte* target, RelocInfo::Mode rmode, Condition cond) {
19844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
19944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int pre_position = pc_offset();
20044f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
20144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!RelocInfo::IsCodeTarget(rmode));
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Call(reinterpret_cast<intptr_t>(target), rmode, cond);
20444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
20544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
20644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int post_position = pc_offset();
20744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(pre_position + CallSize(target, rmode, cond), post_position);
20844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint MacroAssembler::CallSize(
21344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<Code> code, RelocInfo::Mode rmode, Condition cond) {
21444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return CallSize(reinterpret_cast<intptr_t>(code.location()), rmode, cond);
21544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
21644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
21744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::CallWithAstId(Handle<Code> code,
219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   RelocInfo::Mode rmode,
220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   unsigned ast_id,
221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   Condition cond) {
222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef DEBUG
223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int pre_position = pc_offset();
224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(rmode == RelocInfo::CODE_TARGET_WITH_ID);
227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(ast_id != kNoASTId);
228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(ast_id_for_reloc_info_ == kNoASTId);
229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ast_id_for_reloc_info_ = ast_id;
230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // 'code' is always generated ARM code, never THUMB code
231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Call(reinterpret_cast<intptr_t>(code.location()), rmode, cond);
232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef DEBUG
234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int post_position = pc_offset();
235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_EQ(pre_position + CallSize(code, rmode, cond), post_position);
236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::Call(Handle<Code> code,
241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          RelocInfo::Mode rmode,
242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          Condition cond) {
24344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
24444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int pre_position = pc_offset();
24544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
24644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(RelocInfo::IsCodeTarget(rmode));
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 'code' is always generated ARM code, never THUMB code
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Call(reinterpret_cast<intptr_t>(code.location()), rmode, cond);
25044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
25144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
25244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int post_position = pc_offset();
25344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(pre_position + CallSize(code, rmode, cond), post_position);
25444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Ret(Condition cond) {
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if USE_BX
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bx(lr, cond);
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(pc, Operand(lr), LeaveCC, cond);
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::Drop(int count, Condition cond) {
268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (count > 0) {
269e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    add(sp, sp, Operand(count * kPointerSize), LeaveCC, cond);
270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::Ret(int drop, Condition cond) {
275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Drop(drop, cond);
276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Ret(cond);
277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::Swap(Register reg1,
2817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                          Register reg2,
2827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                          Register scratch,
2837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                          Condition cond) {
2846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (scratch.is(no_reg)) {
2857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    eor(reg1, reg1, Operand(reg2), LeaveCC, cond);
2867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    eor(reg2, reg2, Operand(reg1), LeaveCC, cond);
2877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    eor(reg1, reg1, Operand(reg2), LeaveCC, cond);
2886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
2897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    mov(scratch, reg1, LeaveCC, cond);
2907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    mov(reg1, reg2, LeaveCC, cond);
2917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    mov(reg2, scratch, LeaveCC, cond);
2926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
2946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
296e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::Call(Label* target) {
297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  bl(target);
298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::Move(Register dst, Handle<Object> value) {
302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  mov(dst, Operand(value));
303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
304d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
305d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3066ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::Move(Register dst, Register src) {
3076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!dst.is(src)) {
3086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    mov(dst, src);
3096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
3116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::Move(DoubleRegister dst, DoubleRegister src) {
314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(CpuFeatures::IsSupported(VFP3));
315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CpuFeatures::Scope scope(VFP3);
316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!dst.is(src)) {
317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    vmov(dst, src);
318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::And(Register dst, Register src1, const Operand& src2,
3239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                         Condition cond) {
3243e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  if (!src2.is_reg() &&
3253e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      !src2.must_use_constant_pool() &&
3263e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      src2.immediate() == 0) {
3279ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    mov(dst, Operand(0, RelocInfo::NONE), LeaveCC, cond);
3283e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
3293e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  } else if (!src2.is_single_instruction() &&
3303e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu             !src2.must_use_constant_pool() &&
3318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch             CpuFeatures::IsSupported(ARMv7) &&
3323e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu             IsPowerOf2(src2.immediate() + 1)) {
3333e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    ubfx(dst, src1, 0, WhichPowerOf2(src2.immediate() + 1), cond);
3343e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
3353e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  } else {
3363e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    and_(dst, src1, src2, LeaveCC, cond);
3379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
3389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
3399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::Ubfx(Register dst, Register src1, int lsb, int width,
3429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                          Condition cond) {
3439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ASSERT(lsb < 32);
3448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (!CpuFeatures::IsSupported(ARMv7)) {
3459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
3469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    and_(dst, src1, Operand(mask), LeaveCC, cond);
3479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    if (lsb != 0) {
3489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      mov(dst, Operand(dst, LSR, lsb), LeaveCC, cond);
3499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    }
3509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  } else {
3519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    ubfx(dst, src1, lsb, width, cond);
3529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
3539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
3549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::Sbfx(Register dst, Register src1, int lsb, int width,
3579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                          Condition cond) {
3589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ASSERT(lsb < 32);
3598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (!CpuFeatures::IsSupported(ARMv7)) {
3609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
3619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    and_(dst, src1, Operand(mask), LeaveCC, cond);
3629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    int shift_up = 32 - lsb - width;
3639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    int shift_down = lsb + shift_up;
3649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    if (shift_up != 0) {
3659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      mov(dst, Operand(dst, LSL, shift_up), LeaveCC, cond);
3669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    }
3679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    if (shift_down != 0) {
3689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      mov(dst, Operand(dst, ASR, shift_down), LeaveCC, cond);
3699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    }
3709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  } else {
3719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    sbfx(dst, src1, lsb, width, cond);
3729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
3739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
3749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
376e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::Bfi(Register dst,
377e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         Register src,
378e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         Register scratch,
379e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         int lsb,
380e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         int width,
381e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         Condition cond) {
382e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(0 <= lsb && lsb < 32);
383e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(0 <= width && width < 32);
384e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(lsb + width < 32);
385e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(!scratch.is(dst));
386e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (width == 0) return;
3878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (!CpuFeatures::IsSupported(ARMv7)) {
388e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
389e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    bic(dst, dst, Operand(mask));
390e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    and_(scratch, src, Operand((1 << width) - 1));
391e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    mov(scratch, Operand(scratch, LSL, lsb));
392e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    orr(dst, dst, scratch);
393e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
394e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    bfi(dst, src, lsb, width, cond);
395e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
396e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
397e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
398e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3999dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::Bfc(Register dst, int lsb, int width, Condition cond) {
4009dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ASSERT(lsb < 32);
4018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (!CpuFeatures::IsSupported(ARMv7)) {
4029dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
4039dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    bic(dst, dst, Operand(mask));
4049dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  } else {
4059dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    bfc(dst, lsb, width, cond);
4069dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
4079dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
4089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
4099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
41050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsenvoid MacroAssembler::Usat(Register dst, int satpos, const Operand& src,
41150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen                          Condition cond) {
4128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (!CpuFeatures::IsSupported(ARMv7)) {
41350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    ASSERT(!dst.is(pc) && !src.rm().is(pc));
41450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    ASSERT((satpos >= 0) && (satpos <= 31));
41550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
41650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    // These asserts are required to ensure compatibility with the ARMv7
41750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    // implementation.
41850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    ASSERT((src.shift_op() == ASR) || (src.shift_op() == LSL));
41950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    ASSERT(src.rs().is(no_reg));
42050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
42150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    Label done;
42250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    int satval = (1 << satpos) - 1;
42350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
42450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    if (cond != al) {
42550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen      b(NegateCondition(cond), &done);  // Skip saturate if !condition.
42650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    }
42750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    if (!(src.is_reg() && dst.is(src.rm()))) {
42850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen      mov(dst, src);
42950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    }
43050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    tst(dst, Operand(~satval));
43150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    b(eq, &done);
4329ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    mov(dst, Operand(0, RelocInfo::NONE), LeaveCC, mi);  // 0 if negative.
43350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    mov(dst, Operand(satval), LeaveCC, pl);  // satval if positive.
43450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    bind(&done);
43550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  } else {
43650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    usat(dst, satpos, src, cond);
43750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  }
43850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen}
43950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
44050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SmiJumpTable(Register index, Vector<Label*> targets) {
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Empty the const pool.
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckConstPool(true, true);
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  add(pc, pc, Operand(index,
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      LSL,
4461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      Instruction::kInstrSizeLog2 - kSmiTagSize));
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BlockConstPoolBefore(pc_offset() + (targets.length() + 1) * kInstrSize);
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  nop();  // Jump table alignment.
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < targets.length(); i++) {
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    b(targets[i]);
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LoadRoot(Register destination,
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Heap::RootListIndex index,
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Condition cond) {
4583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  ldr(destination, MemOperand(roots, index << kPointerSizeLog2), cond);
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsenvoid MacroAssembler::StoreRoot(Register source,
46325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                               Heap::RootListIndex index,
46425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                               Condition cond) {
46525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  str(source, MemOperand(roots, index << kPointerSizeLog2), cond);
46625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}
46725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
46825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
4696ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::RecordWriteHelper(Register object,
4708defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                       Register address,
4718defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                       Register scratch) {
47244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
4736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Check that the object is not in new space.
4746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label not_in_new_space;
4758defd9ff6930b4e24729971a61cf7469daf119beSteve Block    InNewSpace(object, scratch, ne, &not_in_new_space);
4766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Abort("new-space object passed to RecordWriteHelper");
4776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bind(&not_in_new_space);
4786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
4807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Calculate page address.
4819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  Bfc(object, 0, kPageSizeBits);
4829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
4839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Calculate region number.
4848defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Ubfx(address, address, Page::kRegionSizeLog2,
4859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen       kPageSizeBits - Page::kRegionSizeLog2);
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Mark region dirty.
4888defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ldr(scratch, MemOperand(object, Page::kDirtyFlagOffset));
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(ip, Operand(1));
4908defd9ff6930b4e24729971a61cf7469daf119beSteve Block  orr(scratch, scratch, Operand(ip, LSL, address));
4918defd9ff6930b4e24729971a61cf7469daf119beSteve Block  str(scratch, MemOperand(object, Page::kDirtyFlagOffset));
4926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4956ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::InNewSpace(Register object,
4966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                Register scratch,
4971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                Condition cond,
4986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                Label* branch) {
4991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(cond == eq || cond == ne);
50044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  and_(scratch, object, Operand(ExternalReference::new_space_mask(isolate())));
50144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  cmp(scratch, Operand(ExternalReference::new_space_start(isolate())));
5021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  b(cond, branch);
5036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
5046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Will clobber 4 registers: object, offset, scratch, ip.  The
5076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// register 'object' contains a heap object pointer.  The heap object
5086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// tag is shifted away.
5099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::RecordWrite(Register object,
5109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                 Operand offset,
5119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                 Register scratch0,
5129dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                 Register scratch1) {
5136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // The compiled code assumes that record write doesn't change the
5146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // context register, so we check that none of the clobbered
5156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // registers are cp.
5169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ASSERT(!object.is(cp) && !scratch0.is(cp) && !scratch1.is(cp));
5176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label done;
5196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // First, test that the object is not in the new space.  We cannot set
5217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // region marks for new space pages.
5229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  InNewSpace(object, scratch0, eq, &done);
5236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5248defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Add offset into the object.
5258defd9ff6930b4e24729971a61cf7469daf119beSteve Block  add(scratch0, object, offset);
5268defd9ff6930b4e24729971a61cf7469daf119beSteve Block
5276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Record the actual write.
5288defd9ff6930b4e24729971a61cf7469daf119beSteve Block  RecordWriteHelper(object, scratch0, scratch1);
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
5314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Clobber all input registers when running with the debug-code flag
5334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // turned on to provoke errors.
53444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
5356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    mov(object, Operand(BitCast<int32_t>(kZapValue)));
5369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    mov(scratch0, Operand(BitCast<int32_t>(kZapValue)));
5379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    mov(scratch1, Operand(BitCast<int32_t>(kZapValue)));
5384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5428defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Will clobber 4 registers: object, address, scratch, ip.  The
5438defd9ff6930b4e24729971a61cf7469daf119beSteve Block// register 'object' contains a heap object pointer.  The heap object
5448defd9ff6930b4e24729971a61cf7469daf119beSteve Block// tag is shifted away.
5458defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid MacroAssembler::RecordWrite(Register object,
5468defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                 Register address,
5478defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                 Register scratch) {
5488defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // The compiled code assumes that record write doesn't change the
5498defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // context register, so we check that none of the clobbered
5508defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // registers are cp.
5518defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(!object.is(cp) && !address.is(cp) && !scratch.is(cp));
5528defd9ff6930b4e24729971a61cf7469daf119beSteve Block
5538defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label done;
5548defd9ff6930b4e24729971a61cf7469daf119beSteve Block
5558defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // First, test that the object is not in the new space.  We cannot set
5568defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // region marks for new space pages.
5578defd9ff6930b4e24729971a61cf7469daf119beSteve Block  InNewSpace(object, scratch, eq, &done);
5588defd9ff6930b4e24729971a61cf7469daf119beSteve Block
5598defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Record the actual write.
5608defd9ff6930b4e24729971a61cf7469daf119beSteve Block  RecordWriteHelper(object, address, scratch);
5618defd9ff6930b4e24729971a61cf7469daf119beSteve Block
5628defd9ff6930b4e24729971a61cf7469daf119beSteve Block  bind(&done);
5638defd9ff6930b4e24729971a61cf7469daf119beSteve Block
5648defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Clobber all input registers when running with the debug-code flag
5658defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // turned on to provoke errors.
56644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
5678defd9ff6930b4e24729971a61cf7469daf119beSteve Block    mov(object, Operand(BitCast<int32_t>(kZapValue)));
5688defd9ff6930b4e24729971a61cf7469daf119beSteve Block    mov(address, Operand(BitCast<int32_t>(kZapValue)));
5698defd9ff6930b4e24729971a61cf7469daf119beSteve Block    mov(scratch, Operand(BitCast<int32_t>(kZapValue)));
5708defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
5718defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
5728defd9ff6930b4e24729971a61cf7469daf119beSteve Block
5738defd9ff6930b4e24729971a61cf7469daf119beSteve Block
574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Push and pop all registers that can hold pointers.
575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::PushSafepointRegisters() {
576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Safepoints expect a block of contiguous register values starting with r0:
577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(((1 << kNumSafepointSavedRegisters) - 1) == kSafepointSavedRegisters);
578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Safepoints expect a block of kNumSafepointRegisters values on the
579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // stack, so adjust the stack for unsaved registers.
580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(num_unsaved >= 0);
582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  sub(sp, sp, Operand(num_unsaved * kPointerSize));
583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  stm(db_w, sp, kSafepointSavedRegisters);
584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::PopSafepointRegisters() {
588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ldm(ia_w, sp, kSafepointSavedRegisters);
590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  add(sp, sp, Operand(num_unsaved * kPointerSize));
591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
594b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid MacroAssembler::PushSafepointRegistersAndDoubles() {
595b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  PushSafepointRegisters();
596b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  sub(sp, sp, Operand(DwVfpRegister::kNumAllocatableRegisters *
597b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                      kDoubleSize));
598b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  for (int i = 0; i < DwVfpRegister::kNumAllocatableRegisters; i++) {
599b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    vstr(DwVfpRegister::FromAllocationIndex(i), sp, i * kDoubleSize);
600b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
601b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
602b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
603b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
604b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid MacroAssembler::PopSafepointRegistersAndDoubles() {
605b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  for (int i = 0; i < DwVfpRegister::kNumAllocatableRegisters; i++) {
606b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    vldr(DwVfpRegister::FromAllocationIndex(i), sp, i * kDoubleSize);
607b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
608b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  add(sp, sp, Operand(DwVfpRegister::kNumAllocatableRegisters *
609b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                      kDoubleSize));
610b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  PopSafepointRegisters();
611b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
612b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
613e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register src,
614e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                                             Register dst) {
615e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  str(src, SafepointRegistersAndDoublesSlot(dst));
6161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
6171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
619e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) {
620e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  str(src, SafepointRegisterSlot(dst));
6211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
6221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
624e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
625e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ldr(dst, SafepointRegisterSlot(src));
6261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
6271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The registers are pushed starting with the highest encoding,
631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // which means that lowest encodings are closest to the stack pointer.
632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(reg_code >= 0 && reg_code < kNumSafepointRegisters);
633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return reg_code;
634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6371e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockMemOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
6381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return MemOperand(sp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
6391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
6401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6421e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockMemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
6431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // General purpose registers are pushed last on the stack.
6441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int doubles_size = DwVfpRegister::kNumAllocatableRegisters * kDoubleSize;
6451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
6461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return MemOperand(sp, doubles_size + register_offset);
6471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
6481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::Ldrd(Register dst1, Register dst2,
651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                          const MemOperand& src, Condition cond) {
652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(src.rm().is(no_reg));
653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(!dst1.is(lr));  // r14.
654f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(0, dst1.code() % 2);
655f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(dst1.code() + 1, dst2.code());
656f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
657f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate two ldr instructions if ldrd is not available.
6588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (CpuFeatures::IsSupported(ARMv7)) {
659f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CpuFeatures::Scope scope(ARMv7);
660f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    ldrd(dst1, dst2, src, cond);
661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    MemOperand src2(src);
663f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    src2.set_offset(src2.offset() + 4);
664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (dst1.is(src.rn())) {
665f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      ldr(dst2, src2, cond);
666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      ldr(dst1, src, cond);
667f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    } else {
668f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      ldr(dst1, src, cond);
669f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      ldr(dst2, src2, cond);
670f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
671f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
672f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
673f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
674f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid MacroAssembler::Strd(Register src1, Register src2,
676f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                          const MemOperand& dst, Condition cond) {
677f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(dst.rm().is(no_reg));
678f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(!src1.is(lr));  // r14.
679f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(0, src1.code() % 2);
680f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(src1.code() + 1, src2.code());
681f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
682f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Generate two str instructions if strd is not available.
6838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (CpuFeatures::IsSupported(ARMv7)) {
684f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    CpuFeatures::Scope scope(ARMv7);
685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    strd(src1, src2, dst, cond);
686f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
687f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    MemOperand dst2(dst);
688f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    dst2.set_offset(dst2.offset() + 4);
689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    str(src1, dst, cond);
690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    str(src2, dst2, cond);
691f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
694f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
695b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid MacroAssembler::ClearFPSCRBits(const uint32_t bits_to_clear,
696b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                    const Register scratch,
697b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                    const Condition cond) {
698b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  vmrs(scratch, cond);
699b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  bic(scratch, scratch, Operand(bits_to_clear), LeaveCC, cond);
700b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  vmsr(scratch, cond);
701b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
702b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
703b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
704b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid MacroAssembler::VFPCompareAndSetFlags(const DwVfpRegister src1,
705b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                           const DwVfpRegister src2,
706b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                           const Condition cond) {
707b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Compare and move FPSCR flags to the normal condition flags.
708b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  VFPCompareAndLoadFlags(src1, src2, pc, cond);
709b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
710b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
711b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid MacroAssembler::VFPCompareAndSetFlags(const DwVfpRegister src1,
712b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                           const double src2,
713b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                           const Condition cond) {
714b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Compare and move FPSCR flags to the normal condition flags.
715b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  VFPCompareAndLoadFlags(src1, src2, pc, cond);
716b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
717b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
718b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
719b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid MacroAssembler::VFPCompareAndLoadFlags(const DwVfpRegister src1,
720b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                            const DwVfpRegister src2,
721b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                            const Register fpscr_flags,
722b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                            const Condition cond) {
723b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Compare and load FPSCR.
724b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  vcmp(src1, src2, cond);
725b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  vmrs(fpscr_flags, cond);
726b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
727b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
728b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid MacroAssembler::VFPCompareAndLoadFlags(const DwVfpRegister src1,
729b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                            const double src2,
730b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                            const Register fpscr_flags,
731b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                            const Condition cond) {
732b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Compare and load FPSCR.
733b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  vcmp(src1, src2, cond);
734b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  vmrs(fpscr_flags, cond);
735086aeeaae12517475c22695a200be45495516549Ben Murdoch}
736086aeeaae12517475c22695a200be45495516549Ben Murdoch
737086aeeaae12517475c22695a200be45495516549Ben Murdoch
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::EnterFrame(StackFrame::Type type) {
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0-r3: preserved
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stm(db_w, sp, cp.bit() | fp.bit() | lr.bit());
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(ip, Operand(Smi::FromInt(type)));
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(ip);
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(ip, Operand(CodeObject()));
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(ip);
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  add(fp, sp, Operand(3 * kPointerSize));  // Adjust FP to point to saved FP.
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::LeaveFrame(StackFrame::Type type) {
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: preserved
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: preserved
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: preserved
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Drop the execution stack down to the frame pointer and restore
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the caller frame pointer and return address.
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(sp, fp);
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ldm(ia_w, sp, fp.bit() | lr.bit());
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) {
7621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Setup the frame structure on the stack.
7631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement);
7641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset);
7651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset);
7661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Push(lr, fp);
767402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  mov(fp, Operand(sp));  // Setup new frame pointer.
7681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Reserve room for saved entry sp and code object.
7691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  sub(sp, sp, Operand(2 * kPointerSize));
77044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
7711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    mov(ip, Operand(0));
7721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset));
7731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
774402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  mov(ip, Operand(CodeObject()));
7751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset));
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Save the frame pointer and the context in top.
77844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(ip, Operand(ExternalReference(Isolate::k_c_entry_fp_address, isolate())));
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  str(fp, MemOperand(ip));
78044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(ip, Operand(ExternalReference(Isolate::k_context_address, isolate())));
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  str(cp, MemOperand(ip));
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Optionally save all double registers.
784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (save_doubles) {
7858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    DwVfpRegister first = d0;
7868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    DwVfpRegister last =
7878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        DwVfpRegister::from_code(DwVfpRegister::kNumRegisters - 1);
7888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    vstm(db_w, sp, first, last);
7891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Note that d0 will be accessible at
7901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    //   fp - 2 * kPointerSize - DwVfpRegister::kNumRegisters * kDoubleSize,
7911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // since the sp slot and code slot were pushed after the fp.
792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
7931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
7941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Reserve place for the return address and stack space and align the frame
7951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // preparing for calling the runtime function.
7961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  const int frame_alignment = MacroAssembler::ActivationFrameAlignment();
7971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  sub(sp, sp, Operand((stack_space + 1) * kPointerSize));
7981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (frame_alignment > 0) {
7991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(IsPowerOf2(frame_alignment));
8001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    and_(sp, sp, Operand(-frame_alignment));
8011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
8021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Set the exit frame sp value to point just before the return address
8041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // location.
8051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  add(ip, sp, Operand(kPointerSize));
8061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset));
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8106ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::InitializeNewString(Register string,
8116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                         Register length,
8126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                         Heap::RootListIndex map_index,
8136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                         Register scratch1,
8146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                         Register scratch2) {
8156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(scratch1, Operand(length, LSL, kSmiTagSize));
8166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LoadRoot(scratch2, map_index);
8176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  str(scratch1, FieldMemOperand(string, String::kLengthOffset));
8186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(scratch1, Operand(String::kEmptyHashField));
8196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  str(scratch2, FieldMemOperand(string, HeapObject::kMapOffset));
8206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  str(scratch1, FieldMemOperand(string, String::kHashFieldOffset));
8216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
8226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8246ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockint MacroAssembler::ActivationFrameAlignment() {
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if defined(V8_HOST_ARCH_ARM)
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Running on the real platform. Use the alignment as mandated by the local
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // environment.
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Note: This will break if we ever start generating snapshots on one ARM
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // platform for another ARM platform with a different alignment.
8306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return OS::ActivationFrameAlignment();
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else  // defined(V8_HOST_ARCH_ARM)
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If we are using the simulator then we should always align to the expected
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // alignment. As the simulator is used to generate snapshots we do not know
8346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // if the target platform will need alignment, so this is controlled from a
8356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // flag.
8366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return FLAG_sim_stack_alignment;
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // defined(V8_HOST_ARCH_ARM)
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
841e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::LeaveExitFrame(bool save_doubles,
842e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                    Register argument_count) {
843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Optionally restore all double registers.
844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (save_doubles) {
8458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // Calculate the stack location of the saved doubles and restore them.
8468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    const int offset = 2 * kPointerSize;
8478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    sub(r3, fp, Operand(offset + DwVfpRegister::kNumRegisters * kDoubleSize));
8488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    DwVfpRegister first = d0;
8498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    DwVfpRegister last =
8508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        DwVfpRegister::from_code(DwVfpRegister::kNumRegisters - 1);
8518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    vldm(ia, r3, first, last);
852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear top frame.
8559ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  mov(r3, Operand(0, RelocInfo::NONE));
85644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(ip, Operand(ExternalReference(Isolate::k_c_entry_fp_address, isolate())));
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  str(r3, MemOperand(ip));
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore current context from top and clear it in debug mode.
86044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(ip, Operand(ExternalReference(Isolate::k_context_address, isolate())));
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ldr(cp, MemOperand(ip));
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  str(r3, MemOperand(ip));
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
866e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Tear down the exit frame, pop the arguments, and return.
8671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  mov(sp, Operand(fp));
8681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ldm(ia_w, sp, fp.bit() | lr.bit());
869e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (argument_count.is_valid()) {
870e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    add(sp, sp, Operand(argument_count, LSL, kPointerSizeLog2));
871e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
872e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
873e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
874e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::GetCFunctionDoubleResult(const DoubleRegister dst) {
875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (use_eabi_hardfloat()) {
876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Move(dst, d0);
877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    vmov(dst, r0, r1);
879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SetCallKind(Register dst, CallKind call_kind) {
884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This macro takes the dst register to make the code more readable
885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // at the call sites. However, the dst register has to be r5 to
886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // follow the calling convention which requires the call type to be
887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // in r5.
888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(dst.is(r5));
889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (call_kind == CALL_AS_FUNCTION) {
890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    mov(dst, Operand(Smi::FromInt(1)));
891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    mov(dst, Operand(Smi::FromInt(0)));
893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokePrologue(const ParameterCount& expected,
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const ParameterCount& actual,
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Handle<Code> code_constant,
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Register code_reg,
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    Label* done,
902b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                    InvokeFlag flag,
903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    const CallWrapper& call_wrapper,
904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    CallKind call_kind) {
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool definitely_matches = false;
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label regular_invoke;
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check whether the expected and actual arguments count match. If not,
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // setup registers according to contract with ArgumentsAdaptorTrampoline:
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  r0: actual arguments count
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  r1: function (passed through to callee)
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  r2: expected arguments count
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  r3: callee code entry
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The code below is made a lot easier because the calling code already sets
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // up actual and expected registers according to the contract if values are
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // passed in registers.
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(actual.is_immediate() || actual.reg().is(r0));
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(expected.is_immediate() || expected.reg().is(r2));
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((!code_constant.is_null() && code_reg.is(no_reg)) || code_reg.is(r3));
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (expected.is_immediate()) {
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(actual.is_immediate());
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (expected.immediate() == actual.immediate()) {
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      definitely_matches = true;
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mov(r0, Operand(actual.immediate()));
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (expected.immediate() == sentinel) {
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Don't worry about adapting arguments for builtins that
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // don't want that done. Skip adaption code by making it look
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // like we have a match between expected and actual number of
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // arguments.
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        definitely_matches = true;
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mov(r2, Operand(expected.immediate()));
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (actual.is_immediate()) {
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      cmp(expected.reg(), Operand(actual.immediate()));
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      b(eq, &regular_invoke);
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mov(r0, Operand(actual.immediate()));
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      cmp(expected.reg(), Operand(actual.reg()));
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      b(eq, &regular_invoke);
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!definitely_matches) {
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!code_constant.is_null()) {
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mov(r3, Operand(code_constant));
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<Code> adaptor =
95744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        isolate()->builtins()->ArgumentsAdaptorTrampoline();
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (flag == CALL_FUNCTION) {
959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET));
960257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      SetCallKind(r5, call_kind);
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Call(adaptor, RelocInfo::CODE_TARGET);
962257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      call_wrapper.AfterCall();
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      b(done);
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      SetCallKind(r5, call_kind);
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Jump(adaptor, RelocInfo::CODE_TARGET);
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bind(&regular_invoke);
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Register code,
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& expected,
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& actual,
976b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                InvokeFlag flag,
977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                const CallWrapper& call_wrapper,
978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                CallKind call_kind) {
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label done;
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
981b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag,
982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 call_wrapper, call_kind);
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (flag == CALL_FUNCTION) {
984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    call_wrapper.BeforeCall(CallSize(code));
985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SetCallKind(r5, call_kind);
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Call(code);
987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    call_wrapper.AfterCall();
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(flag == JUMP_FUNCTION);
990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SetCallKind(r5, call_kind);
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Jump(code);
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Continue here if InvokePrologue does handle the invocation due to
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // mismatched parameter counts.
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeCode(Handle<Code> code,
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& expected,
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                const ParameterCount& actual,
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                RelocInfo::Mode rmode,
1004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                InvokeFlag flag,
1005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                CallKind call_kind) {
1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label done;
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  InvokePrologue(expected, actual, code, no_reg, &done, flag,
1009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 NullCallWrapper(), call_kind);
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (flag == CALL_FUNCTION) {
1011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SetCallKind(r5, call_kind);
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Call(code, rmode);
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SetCallKind(r5, call_kind);
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Jump(code, rmode);
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Continue here if InvokePrologue does handle the invocation due to
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // mismatched parameter counts.
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeFunction(Register fun,
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const ParameterCount& actual,
1026b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                    InvokeFlag flag,
1027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    const CallWrapper& call_wrapper,
1028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    CallKind call_kind) {
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Contract with called JS functions requires that function is passed in r1.
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(fun.is(r1));
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Register expected_reg = r2;
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Register code_reg = r3;
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ldr(code_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ldr(expected_reg,
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      FieldMemOperand(code_reg,
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      SharedFunctionInfo::kFormalParameterCountOffset));
10407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  mov(expected_reg, Operand(expected_reg, ASR, kSmiTagSize));
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ldr(code_reg,
1042791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount expected(expected_reg);
1045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  InvokeCode(code_reg, expected, actual, flag, call_wrapper, call_kind);
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1049402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::InvokeFunction(JSFunction* function,
1050402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                    const ParameterCount& actual,
1051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    InvokeFlag flag,
1052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                    CallKind call_kind) {
1053402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ASSERT(function->is_compiled());
1054402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1055402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Get the function and setup the context.
1056402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  mov(r1, Operand(Handle<JSFunction>(function)));
1057402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1058402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1059402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Invoke the cached code.
1060402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Handle<Code> code(function->code());
1061402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ParameterCount expected(function->shared()->formal_parameter_count());
1062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (V8::UseCrankshaft()) {
1063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // TODO(kasperl): For now, we always call indirectly through the
1064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // code field in the function to allow recompilation to take effect
1065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // without changing any of the call sites.
1066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
1067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    InvokeCode(r3, expected, actual, flag, NullCallWrapper(), call_kind);
1068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
1069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag, call_kind);
1070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::IsObjectJSObjectType(Register heap_object,
1075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          Register map,
1076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          Register scratch,
1077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                          Label* fail) {
1078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ldr(map, FieldMemOperand(heap_object, HeapObject::kMapOffset));
1079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  IsInstanceJSObjectType(map, scratch, fail);
1080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::IsInstanceJSObjectType(Register map,
1084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            Register scratch,
1085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            Label* fail) {
1086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
1087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  cmp(scratch, Operand(FIRST_JS_OBJECT_TYPE));
1088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  b(lt, fail);
1089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  cmp(scratch, Operand(LAST_JS_OBJECT_TYPE));
1090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  b(gt, fail);
1091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::IsObjectJSStringType(Register object,
1095e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                          Register scratch,
1096e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                          Label* fail) {
1097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(kNotStringTag != 0);
1098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
1100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
1101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  tst(scratch, Operand(kIsNotStringMask));
11021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  b(ne, fail);
1103402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1104402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1105402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
110680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef ENABLE_DEBUGGER_SUPPORT
1107402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::DebugBreak() {
1108402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ASSERT(allow_stub_calls());
11099ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  mov(r0, Operand(0, RelocInfo::NONE));
111044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(r1, Operand(ExternalReference(Runtime::kDebugBreak, isolate())));
1111402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CEntryStub ces(1);
1112402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
1113402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::PushTryHandler(CodeLocation try_location,
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    HandlerType type) {
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust this code if not the case.
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The pc (return address) is passed in register lr.
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (try_location == IN_JAVASCRIPT) {
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (type == TRY_CATCH_HANDLER) {
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mov(r3, Operand(StackHandler::TRY_CATCH));
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mov(r3, Operand(StackHandler::TRY_FINALLY));
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           && StackHandlerConstants::kFPOffset == 2 * kPointerSize
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           && StackHandlerConstants::kPCOffset == 3 * kPointerSize);
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    stm(db_w, sp, r3.bit() | fp.bit() | lr.bit());
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Save the current handler as the next handler.
113344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mov(r3, Operand(ExternalReference(Isolate::k_handler_address, isolate())));
1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ldr(r1, MemOperand(r3));
1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(StackHandlerConstants::kNextOffset == 0);
1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(r1);
1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Link this handler as the new current one.
1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    str(sp, MemOperand(r3));
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Must preserve r0-r4, r5-r7 are available.
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(try_location == IN_JS_ENTRY);
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The frame pointer does not point to a JS frame so we save NULL
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // for fp. We expect the code throwing an exception to check fp
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // before dereferencing it to restore the context.
11459ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    mov(ip, Operand(0, RelocInfo::NONE));  // To save a NULL frame pointer.
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(r6, Operand(StackHandler::ENTRY));
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           && StackHandlerConstants::kFPOffset == 2 * kPointerSize
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           && StackHandlerConstants::kPCOffset == 3 * kPointerSize);
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    stm(db_w, sp, r6.bit() | ip.bit() | lr.bit());
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Save the current handler as the next handler.
115244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mov(r7, Operand(ExternalReference(Isolate::k_handler_address, isolate())));
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ldr(r6, MemOperand(r7));
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(StackHandlerConstants::kNextOffset == 0);
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(r6);
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Link this handler as the new current one.
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    str(sp, MemOperand(r7));
1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1162e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid MacroAssembler::PopTryHandler() {
1163e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(0, StackHandlerConstants::kNextOffset);
1164e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  pop(r1);
116544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(ip, Operand(ExternalReference(Isolate::k_handler_address, isolate())));
1166e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
1167e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  str(r1, MemOperand(ip));
1168e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1169e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1170e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::Throw(Register value) {
1172e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // r0 is expected to hold the exception.
1173e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!value.is(r0)) {
1174e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    mov(r0, value);
1175e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Adjust this code if not the case.
1178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
1179e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Drop the sp to the top of the handler.
118144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(r3, Operand(ExternalReference(Isolate::k_handler_address, isolate())));
1182e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ldr(sp, MemOperand(r3));
1183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Restore the next handler and frame pointer, discard handler state.
1185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
1186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  pop(r2);
1187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  str(r2, MemOperand(r3));
1188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize);
1189e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ldm(ia_w, sp, r3.bit() | fp.bit());  // r3: discarded state.
1190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Before returning we restore the context from the frame pointer if
1192e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // not NULL.  The frame pointer is NULL in the exception handler of a
1193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // JS entry frame.
1194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  cmp(fp, Operand(0, RelocInfo::NONE));
1195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Set cp to NULL if fp is NULL.
1196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq);
1197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Restore cp otherwise.
1198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
1199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#ifdef DEBUG
120044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
1201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    mov(lr, Operand(pc));
1202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#endif
1204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
1205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  pop(pc);
1206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
1210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                      Register value) {
1211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Adjust this code if not the case.
1212e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
1213e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1214e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // r0 is expected to hold the exception.
1215e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!value.is(r0)) {
1216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    mov(r0, value);
1217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1218e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Drop sp to the top stack handler.
122044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(r3, Operand(ExternalReference(Isolate::k_handler_address, isolate())));
1221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ldr(sp, MemOperand(r3));
1222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Unwind the handlers until the ENTRY handler is found.
1224e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Label loop, done;
1225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bind(&loop);
1226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Load the type of the current stack handler.
1227e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  const int kStateOffset = StackHandlerConstants::kStateOffset;
1228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ldr(r2, MemOperand(sp, kStateOffset));
1229e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  cmp(r2, Operand(StackHandler::ENTRY));
1230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  b(eq, &done);
1231e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Fetch the next handler in the list.
1232e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  const int kNextOffset = StackHandlerConstants::kNextOffset;
1233e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ldr(sp, MemOperand(sp, kNextOffset));
1234e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  jmp(&loop);
1235e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bind(&done);
1236e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1237e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Set the top handler address to next handler past the current ENTRY handler.
1238e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
1239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  pop(r2);
1240e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  str(r2, MemOperand(r3));
1241e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (type == OUT_OF_MEMORY) {
1243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Set external caught exception to false.
124444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ExternalReference external_caught(
124544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Isolate::k_external_caught_exception_address, isolate());
1246e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    mov(r0, Operand(false, RelocInfo::NONE));
1247e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    mov(r2, Operand(external_caught));
1248e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    str(r0, MemOperand(r2));
1249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1250e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Set pending exception and r0 to out of memory exception.
1251e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Failure* out_of_memory = Failure::OutOfMemoryException();
1252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory)));
125344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mov(r2, Operand(ExternalReference(Isolate::k_pending_exception_address,
125444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                      isolate())));
1255e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    str(r0, MemOperand(r2));
1256e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1258e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Stack layout at this point. See also StackHandlerConstants.
1259e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // sp ->   state (ENTRY)
1260e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //         fp
1261e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //         lr
1262e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Discard handler state (r2 is not used) and restore frame pointer.
1264e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize);
1265e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ldm(ia_w, sp, r2.bit() | fp.bit());  // r2: discarded state.
1266e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Before returning we restore the context from the frame pointer if
1267e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // not NULL.  The frame pointer is NULL in the exception handler of a
1268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // JS entry frame.
1269e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  cmp(fp, Operand(0, RelocInfo::NONE));
1270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Set cp to NULL if fp is NULL.
1271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq);
1272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Restore cp otherwise.
1273e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
1274e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#ifdef DEBUG
127544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
1276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    mov(lr, Operand(pc));
1277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#endif
1279e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
1280e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  pop(pc);
1281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1282e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1283e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register scratch,
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Label* miss) {
1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label same_contexts;
1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!holder_reg.is(scratch));
1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!holder_reg.is(ip));
1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch.is(ip));
1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load current lexical context from the stack frame.
1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ldr(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset));
1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // In debug mode, make sure the lexical context is set.
1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
12979ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  cmp(scratch, Operand(0, RelocInfo::NONE));
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Check(ne, "we should not have an empty lexical context");
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the global context of the current context.
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ldr(scratch, FieldMemOperand(scratch, offset));
1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ldr(scratch, FieldMemOperand(scratch, GlobalObject::kGlobalContextOffset));
1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the context is a global context.
130744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // TODO(119): avoid push(holder_reg)/pop(holder_reg)
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Cannot use ip as a temporary in this verification code. Due to the fact
1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // that ip is clobbered as part of cmp with an object Operand.
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(holder_reg);  // Temporarily save holder on the stack.
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Read the first word and compare to the global_context_map.
1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ldr(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset));
1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    LoadRoot(ip, Heap::kGlobalContextMapRootIndex);
1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmp(holder_reg, ip);
1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(eq, "JSGlobalObject::global_context should be a global context.");
1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pop(holder_reg);  // Restore holder.
1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if both contexts are the same.
1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ldr(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kContextOffset));
1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmp(scratch, Operand(ip));
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  b(eq, &same_contexts);
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the context is a global context.
132644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // TODO(119): avoid push(holder_reg)/pop(holder_reg)
1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Cannot use ip as a temporary in this verification code. Due to the fact
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // that ip is clobbered as part of cmp with an object Operand.
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    push(holder_reg);  // Temporarily save holder on the stack.
1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(holder_reg, ip);  // Move ip to its holding place.
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    LoadRoot(ip, Heap::kNullValueRootIndex);
1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmp(holder_reg, ip);
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(ne, "JSGlobalProxy::context() should not be null.");
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ldr(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset));
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    LoadRoot(ip, Heap::kGlobalContextMapRootIndex);
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cmp(holder_reg, ip);
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Check(eq, "JSGlobalObject::global_context should be a global context.");
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Restore ip is not needed. ip is reloaded below.
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pop(holder_reg);  // Restore holder.
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Restore ip to holder's context.
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ldr(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kContextOffset));
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the security token in the calling global object is
1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // compatible with the security token in the receiving global
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object.
1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int token_offset = Context::kHeaderSize +
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     Context::SECURITY_TOKEN_INDEX * kPointerSize;
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ldr(scratch, FieldMemOperand(scratch, token_offset));
1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ldr(ip, FieldMemOperand(ip, token_offset));
1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmp(scratch, Operand(ip));
1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  b(ne, miss);
1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&same_contexts);
1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(int object_size,
1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result,
1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch1,
1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch2,
1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* gc_required,
1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        AllocationFlags flags) {
13675913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
136844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
13695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
13705913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result, Operand(0x7091));
13715913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(scratch1, Operand(0x7191));
13725913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(scratch2, Operand(0x7291));
13735913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
13745913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
13755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
13765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
13775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!result.is(scratch1));
1379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!result.is(scratch2));
1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch1.is(scratch2));
1381e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(!scratch1.is(ip));
1382e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(!scratch2.is(ip));
1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
138425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // Make object size into bytes.
138525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  if ((flags & SIZE_IN_WORDS) != 0) {
138625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    object_size *= kPointerSize;
138725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  }
138825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  ASSERT_EQ(0, object_size & kObjectAlignmentMask);
138925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check relative positions of allocation top and limit addresses.
1391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The values must be adjacent in memory to allow the use of LDM.
1392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Also, assert that the registers are numbered such that the values
1393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // are loaded in the correct order.
1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_top =
139544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_top_address(isolate());
1396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ExternalReference new_space_allocation_limit =
139744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_limit_address(isolate());
1398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  intptr_t top   =
1399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      reinterpret_cast<intptr_t>(new_space_allocation_top.address());
1400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  intptr_t limit =
1401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      reinterpret_cast<intptr_t>(new_space_allocation_limit.address());
1402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT((limit - top) == kPointerSize);
1403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(result.code() < ip.code());
1404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Set up allocation top address and object size registers.
1406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Register topaddr = scratch1;
1407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Register obj_size_reg = scratch2;
1408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  mov(topaddr, Operand(new_space_allocation_top));
1409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  mov(obj_size_reg, Operand(object_size));
1410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // This code stores a temporary value in ip. This is OK, as the code below
1412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // does not need ip for implicit literal generation.
1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & RESULT_CONTAINS_TOP) == 0) {
1414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Load allocation top into result and allocation limit into ip.
1415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ldm(ia, topaddr, result.bit() | ip.bit());
1416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
141744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
1418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Assert that result actually contains top on entry. ip is used
1419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // immediately below so this use of ip does not cause difference with
1420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // respect to register content between debug and release mode.
1421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ldr(ip, MemOperand(topaddr));
1422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      cmp(result, ip);
1423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Check(eq, "Unexpected allocation top");
1424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Load allocation limit into ip. Result already contains allocation top.
1426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ldr(ip, MemOperand(topaddr, limit - top));
1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate new top and bail out if new space is exhausted. Use result
1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to calculate the new top.
14311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  add(scratch2, result, Operand(obj_size_reg), SetCC);
14321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  b(cs, gc_required);
1433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  cmp(scratch2, Operand(ip));
1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  b(hi, gc_required);
1435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  str(scratch2, MemOperand(topaddr));
1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Tag object if requested.
1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & TAG_OBJECT) != 0) {
1439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    add(result, result, Operand(kHeapObjectTag));
1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::AllocateInNewSpace(Register object_size,
1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register result,
1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch1,
1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch2,
1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* gc_required,
1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        AllocationFlags flags) {
14505913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  if (!FLAG_inline_new) {
145144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
14525913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      // Trash the registers to simulate an allocation failure.
14535913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(result, Operand(0x7091));
14545913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(scratch1, Operand(0x7191));
14555913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      mov(scratch2, Operand(0x7291));
14565913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    }
14575913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    jmp(gc_required);
14585913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return;
14595913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
14605913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
1461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Assert that the register arguments are different and that none of
1462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // them are ip. ip is used explicitly in the code generated below.
1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!result.is(scratch1));
1464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!result.is(scratch2));
1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch1.is(scratch2));
1466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!result.is(ip));
1467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!scratch1.is(ip));
1468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!scratch2.is(ip));
1469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check relative positions of allocation top and limit addresses.
1471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The values must be adjacent in memory to allow the use of LDM.
1472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Also, assert that the registers are numbered such that the values
1473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // are loaded in the correct order.
1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_top =
147544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_top_address(isolate());
1476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ExternalReference new_space_allocation_limit =
147744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_limit_address(isolate());
1478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  intptr_t top =
1479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      reinterpret_cast<intptr_t>(new_space_allocation_top.address());
1480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  intptr_t limit =
1481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      reinterpret_cast<intptr_t>(new_space_allocation_limit.address());
1482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT((limit - top) == kPointerSize);
1483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(result.code() < ip.code());
1484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Set up allocation top address.
1486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Register topaddr = scratch1;
1487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  mov(topaddr, Operand(new_space_allocation_top));
1488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // This code stores a temporary value in ip. This is OK, as the code below
1490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // does not need ip for implicit literal generation.
1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & RESULT_CONTAINS_TOP) == 0) {
1492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Load allocation top into result and allocation limit into ip.
1493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ldm(ia, topaddr, result.bit() | ip.bit());
1494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
149544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (emit_debug_code()) {
1496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Assert that result actually contains top on entry. ip is used
1497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // immediately below so this use of ip does not cause difference with
1498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // respect to register content between debug and release mode.
1499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ldr(ip, MemOperand(topaddr));
1500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      cmp(result, ip);
1501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Check(eq, "Unexpected allocation top");
1502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Load allocation limit into ip. Result already contains allocation top.
1504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ldr(ip, MemOperand(topaddr, limit - top));
1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate new top and bail out if new space is exhausted. Use result
1508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // to calculate the new top. Object size may be in words so a shift is
1509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // required to get the number of bytes.
151025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  if ((flags & SIZE_IN_WORDS) != 0) {
15111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    add(scratch2, result, Operand(object_size, LSL, kPointerSizeLog2), SetCC);
151225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  } else {
15131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    add(scratch2, result, Operand(object_size), SetCC);
151425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  }
15151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  b(cs, gc_required);
1516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  cmp(scratch2, Operand(ip));
1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  b(hi, gc_required);
1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1519d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Update allocation top. result temporarily holds the new top.
152044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
1521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    tst(scratch2, Operand(kObjectAlignmentMask));
1522d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Check(eq, "Unaligned allocation in new space");
1523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  str(scratch2, MemOperand(topaddr));
1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tag object if requested.
1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((flags & TAG_OBJECT) != 0) {
1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    add(result, result, Operand(kHeapObjectTag));
1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::UndoAllocationInNewSpace(Register object,
1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              Register scratch) {
1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference new_space_allocation_top =
153644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::new_space_allocation_top_address(isolate());
1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure the object has no tag before resetting top.
1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  and_(object, object, Operand(~kHeapObjectTagMask));
1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object un-allocated is below the current top.
1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(scratch, Operand(new_space_allocation_top));
1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ldr(scratch, MemOperand(scratch));
1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmp(object, scratch);
1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Check(lt, "Undo allocation of non allocated memory");
1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Write the address of the object to un-allocate as the current top.
1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(scratch, Operand(new_space_allocation_top));
1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  str(object, MemOperand(scratch));
1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::AllocateTwoByteString(Register result,
15543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                           Register length,
15553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                           Register scratch1,
15563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                           Register scratch2,
15573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                           Register scratch3,
15583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                           Label* gc_required) {
15593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Calculate the number of bytes needed for the characters in the string while
15603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // observing object alignment.
15613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
15623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  mov(scratch1, Operand(length, LSL, 1));  // Length in bytes, not chars.
15633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  add(scratch1, scratch1,
15643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      Operand(kObjectAlignmentMask + SeqTwoByteString::kHeaderSize));
156525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  and_(scratch1, scratch1, Operand(~kObjectAlignmentMask));
15663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Allocate two-byte string in new space.
15683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  AllocateInNewSpace(scratch1,
15693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                     result,
15703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                     scratch2,
15713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                     scratch3,
15723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                     gc_required,
15733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                     TAG_OBJECT);
15743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Set the map, length and hash field.
15766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  InitializeNewString(result,
15776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      length,
15786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      Heap::kStringMapRootIndex,
15796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      scratch1,
15806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      scratch2);
15813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
15823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::AllocateAsciiString(Register result,
15853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                         Register length,
15863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                         Register scratch1,
15873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                         Register scratch2,
15883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                         Register scratch3,
15893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                         Label* gc_required) {
15903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Calculate the number of bytes needed for the characters in the string while
15913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // observing object alignment.
15923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0);
15933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  ASSERT(kCharSize == 1);
15943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  add(scratch1, length,
15953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      Operand(kObjectAlignmentMask + SeqAsciiString::kHeaderSize));
159625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  and_(scratch1, scratch1, Operand(~kObjectAlignmentMask));
15973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
15983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Allocate ASCII string in new space.
15993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  AllocateInNewSpace(scratch1,
16003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                     result,
16013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                     scratch2,
16023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                     scratch3,
16033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                     gc_required,
16043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                     TAG_OBJECT);
16053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Set the map, length and hash field.
16076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  InitializeNewString(result,
16086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      length,
16096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      Heap::kAsciiStringMapRootIndex,
16106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      scratch1,
16116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      scratch2);
16123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
16133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::AllocateTwoByteConsString(Register result,
16163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                               Register length,
16173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                               Register scratch1,
16183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                               Register scratch2,
16193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                               Label* gc_required) {
162025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  AllocateInNewSpace(ConsString::kSize,
16213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                     result,
16223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                     scratch1,
16233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                     scratch2,
16243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                     gc_required,
16253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                     TAG_OBJECT);
16266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  InitializeNewString(result,
16286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      length,
16296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      Heap::kConsStringMapRootIndex,
16306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      scratch1,
16316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      scratch2);
16323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
16333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::AllocateAsciiConsString(Register result,
16363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                             Register length,
16373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                             Register scratch1,
16383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                             Register scratch2,
16393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                             Label* gc_required) {
164025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  AllocateInNewSpace(ConsString::kSize,
16413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                     result,
16423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                     scratch1,
16433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                     scratch2,
16443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                     gc_required,
16453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                     TAG_OBJECT);
16466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  InitializeNewString(result,
16486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      length,
16496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      Heap::kConsAsciiStringMapRootIndex,
16506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      scratch1,
16516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      scratch2);
16523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
16533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16556ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CompareObjectType(Register object,
1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Register map,
1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Register type_reg,
1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       InstanceType type) {
16596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ldr(map, FieldMemOperand(object, HeapObject::kMapOffset));
1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompareInstanceType(map, type_reg, type);
1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CompareInstanceType(Register map,
1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                         Register type_reg,
1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                         InstanceType type) {
1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ldrb(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmp(type_reg, Operand(type));
1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1672e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::CompareRoot(Register obj,
1673e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 Heap::RootListIndex index) {
1674e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(!obj.is(ip));
1675e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LoadRoot(ip, index);
1676e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  cmp(obj, ip);
1677e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1678e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1679e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
16803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::CheckMap(Register obj,
16813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Register scratch,
16823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Handle<Map> map,
16833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Label* fail,
1684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                              SmiCheckType smi_check_type) {
1685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
16861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    JumpIfSmi(obj, fail);
16873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
16883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
16893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  mov(ip, Operand(map));
16903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  cmp(scratch, ip);
16913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  b(ne, fail);
16923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
16933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid MacroAssembler::CheckMap(Register obj,
16967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                              Register scratch,
16977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                              Heap::RootListIndex index,
16987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                              Label* fail,
1699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                              SmiCheckType smi_check_type) {
1700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
17011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    JumpIfSmi(obj, fail);
17027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
17037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
17047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  LoadRoot(ip, index);
17057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  cmp(scratch, ip);
17067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  b(ne, fail);
17077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
17087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::DispatchMap(Register obj,
1711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Register scratch,
1712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Handle<Map> map,
1713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Handle<Code> success,
1714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 SmiCheckType smi_check_type) {
1715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label fail;
1716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (smi_check_type == DO_SMI_CHECK) {
1717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    JumpIfSmi(obj, &fail);
1718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
1720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  mov(ip, Operand(map));
1721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  cmp(scratch, ip);
1722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Jump(success, RelocInfo::CODE_TARGET, eq);
1723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&fail);
1724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::TryGetFunctionPrototype(Register function,
1728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register result,
1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register scratch,
1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Label* miss) {
1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
17321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  JumpIfSmi(function, miss);
1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function really is a function.  Load map into result reg.
1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompareObjectType(function, result, scratch, JS_FUNCTION_TYPE);
1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  b(ne, miss);
1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that the function has an instance prototype.
1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label non_instance;
1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ldrb(scratch, FieldMemOperand(result, Map::kBitFieldOffset));
1741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  tst(scratch, Operand(1 << Map::kHasNonInstancePrototype));
1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  b(ne, &non_instance);
1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype or initial map from the function.
1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ldr(result,
1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the prototype or initial map is the hole, don't return it and
1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // simply miss the cache instead. This will allow us to allocate a
1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // prototype object on-demand in the runtime system.
1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LoadRoot(ip, Heap::kTheHoleValueRootIndex);
1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cmp(result, ip);
1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  b(eq, miss);
1754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the function does not have an initial map, we're done.
1756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label done;
1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompareObjectType(result, scratch, scratch, MAP_TYPE);
1758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  b(ne, &done);
1759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the prototype from the initial map.
1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ldr(result, FieldMemOperand(result, Map::kPrototypeOffset));
1762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jmp(&done);
1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Non-instance prototype: Fetch prototype from constructor field
1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in initial map.
1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&non_instance);
1767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ldr(result, FieldMemOperand(result, Map::kConstructorOffset));
1768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All done.
1770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&done);
1771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallStub(CodeStub* stub, Condition cond) {
17751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(allow_stub_calls());  // Stub calls are not allowed in some stubs.
1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Call(stub->GetCode(), RelocInfo::CODE_TARGET, cond);
1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochMaybeObject* MacroAssembler::TryCallStub(CodeStub* stub, Condition cond) {
1781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(allow_stub_calls());  // Stub calls are not allowed in some stubs.
1782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Object* result;
1783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  { MaybeObject* maybe_result = stub->TryGetCode();
1784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!maybe_result->ToObject(&result)) return maybe_result;
1785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET, cond);
1787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return result;
1788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
17913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::TailCallStub(CodeStub* stub, Condition cond) {
17921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(allow_stub_calls());  // Stub calls are not allowed in some stubs.
17931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond);
17941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
17951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17971e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockMaybeObject* MacroAssembler::TryTailCallStub(CodeStub* stub, Condition cond) {
17981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(allow_stub_calls());  // Stub calls are not allowed in some stubs.
17991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Object* result;
18001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  { MaybeObject* maybe_result = stub->TryGetCode();
18011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (!maybe_result->ToObject(&result)) return maybe_result;
18021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Jump(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET, cond);
18041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return result;
18051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
18061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
18091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return ref0.address() - ref1.address();
18101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
18111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18131e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockMaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(
1814e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ExternalReference function, int stack_space) {
18151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ExternalReference next_address =
18161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ExternalReference::handle_scope_next_address();
18171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  const int kNextOffset = 0;
18181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  const int kLimitOffset = AddressOffset(
18191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ExternalReference::handle_scope_limit_address(),
18201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      next_address);
18211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  const int kLevelOffset = AddressOffset(
18221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ExternalReference::handle_scope_level_address(),
18231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      next_address);
18241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Allocate HandleScope in callee-save registers.
18261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  mov(r7, Operand(next_address));
18271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ldr(r4, MemOperand(r7, kNextOffset));
18281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ldr(r5, MemOperand(r7, kLimitOffset));
18291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ldr(r6, MemOperand(r7, kLevelOffset));
18301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  add(r6, r6, Operand(1));
18311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  str(r6, MemOperand(r7, kLevelOffset));
18321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Native call returns to the DirectCEntry stub which redirects to the
18341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // return address pushed on stack (could have moved after GC).
18351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // DirectCEntry stub itself is generated early and never moves.
18361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  DirectCEntryStub stub;
18371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  stub.GenerateCall(this, function);
18381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Label promote_scheduled_exception;
18401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Label delete_allocated_handles;
18411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Label leave_exit_frame;
18421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // If result is non-zero, dereference to get the result value
18441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // otherwise set it to undefined.
18451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  cmp(r0, Operand(0));
18461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
18471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ldr(r0, MemOperand(r0), ne);
18481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // No more valid handles (the result handle was the last one). Restore
18501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // previous handle scope.
18511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  str(r4, MemOperand(r7, kNextOffset));
185244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
18531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ldr(r1, MemOperand(r7, kLevelOffset));
18541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    cmp(r1, r6);
18551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Check(eq, "Unexpected level after return from api call");
18561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
18571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  sub(r6, r6, Operand(1));
18581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  str(r6, MemOperand(r7, kLevelOffset));
18591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ldr(ip, MemOperand(r7, kLimitOffset));
18601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  cmp(r5, ip);
18611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  b(ne, &delete_allocated_handles);
18621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check if the function scheduled an exception.
18641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bind(&leave_exit_frame);
18651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LoadRoot(r4, Heap::kTheHoleValueRootIndex);
186644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(ip, Operand(ExternalReference::scheduled_exception_address(isolate())));
18671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ldr(r5, MemOperand(ip));
18681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  cmp(r4, r5);
18691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  b(ne, &promote_scheduled_exception);
18701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1871e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // LeaveExitFrame expects unwind space to be in a register.
18721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  mov(r4, Operand(stack_space));
1873e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LeaveExitFrame(false, r4);
1874e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(pc, lr);
18751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bind(&promote_scheduled_exception);
187744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  MaybeObject* result
187844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      = TryTailCallExternalReference(
187944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference(Runtime::kPromoteScheduledException, isolate()),
188044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          0,
188144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          1);
18821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (result->IsFailure()) {
18831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return result;
18841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
18851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // HandleScope limit has changed. Delete allocated extensions.
18871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bind(&delete_allocated_handles);
18881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  str(r5, MemOperand(r7, kLimitOffset));
18891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  mov(r4, r0);
18908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  PrepareCallCFunction(1, r5);
18918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  mov(r0, Operand(ExternalReference::isolate_address()));
189244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CallCFunction(
18938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      ExternalReference::delete_handle_scope_extensions(isolate()), 1);
18941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  mov(r0, r4);
18951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  jmp(&leave_exit_frame);
18961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return result;
18983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
18993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
19003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IllegalOperation(int num_arguments) {
1902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (num_arguments > 0) {
1903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    add(sp, sp, Operand(num_arguments * kPointerSize));
1904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LoadRoot(r0, Heap::kUndefinedValueRootIndex);
1906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
190980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid MacroAssembler::IndexFromHash(Register hash, Register index) {
191080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // If the hash field contains an array index pick it out. The assert checks
191180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // that the constants for the maximum number of digits for an array index
191280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // cached in the hash field and the number of bits reserved for it does not
191380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // conflict.
191480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
191580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen         (1 << String::kArrayIndexValueBits));
191680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // We want the smi-tagged index in key.  kArrayIndexValueMask has zeros in
191780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // the low kHashShift bits.
191880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  STATIC_ASSERT(kSmiTag == 0);
191980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Ubfx(hash, hash, String::kHashShift, String::kArrayIndexValueBits);
192080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  mov(index, Operand(hash, LSL, kSmiTagSize));
192180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
192280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
192380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1924d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::IntegerToDoubleConversionWithVFP3(Register inReg,
1925d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                                       Register outHighReg,
1926d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                                       Register outLowReg) {
1927d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // ARMv7 VFP3 instructions to implement integer to double conversion.
1928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  mov(r7, Operand(inReg, ASR, kSmiTagSize));
1929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  vmov(s15, r7);
19306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  vcvt_f64_s32(d7, s15);
1931e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  vmov(outLowReg, outHighReg, d7);
1932d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1933d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
19358defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid MacroAssembler::ObjectToDoubleVFPRegister(Register object,
19368defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                               DwVfpRegister result,
19378defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                               Register scratch1,
19388defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                               Register scratch2,
19398defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                               Register heap_number_map,
19408defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                               SwVfpRegister scratch3,
19418defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                               Label* not_number,
19428defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                               ObjectToDoubleFlags flags) {
19438defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label done;
19448defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if ((flags & OBJECT_NOT_SMI) == 0) {
19458defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Label not_smi;
19461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    JumpIfNotSmi(object, &not_smi);
19478defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // Remove smi tag and convert to double.
19488defd9ff6930b4e24729971a61cf7469daf119beSteve Block    mov(scratch1, Operand(object, ASR, kSmiTagSize));
19498defd9ff6930b4e24729971a61cf7469daf119beSteve Block    vmov(scratch3, scratch1);
19508defd9ff6930b4e24729971a61cf7469daf119beSteve Block    vcvt_f64_s32(result, scratch3);
19518defd9ff6930b4e24729971a61cf7469daf119beSteve Block    b(&done);
19528defd9ff6930b4e24729971a61cf7469daf119beSteve Block    bind(&not_smi);
19538defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
19548defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Check for heap number and load double value from it.
19558defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ldr(scratch1, FieldMemOperand(object, HeapObject::kMapOffset));
19568defd9ff6930b4e24729971a61cf7469daf119beSteve Block  sub(scratch2, object, Operand(kHeapObjectTag));
19578defd9ff6930b4e24729971a61cf7469daf119beSteve Block  cmp(scratch1, heap_number_map);
19588defd9ff6930b4e24729971a61cf7469daf119beSteve Block  b(ne, not_number);
19598defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if ((flags & AVOID_NANS_AND_INFINITIES) != 0) {
19608defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // If exponent is all ones the number is either a NaN or +/-Infinity.
19618defd9ff6930b4e24729971a61cf7469daf119beSteve Block    ldr(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
19628defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Sbfx(scratch1,
19638defd9ff6930b4e24729971a61cf7469daf119beSteve Block         scratch1,
19648defd9ff6930b4e24729971a61cf7469daf119beSteve Block         HeapNumber::kExponentShift,
19658defd9ff6930b4e24729971a61cf7469daf119beSteve Block         HeapNumber::kExponentBits);
19668defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // All-one value sign extend to -1.
19678defd9ff6930b4e24729971a61cf7469daf119beSteve Block    cmp(scratch1, Operand(-1));
19688defd9ff6930b4e24729971a61cf7469daf119beSteve Block    b(eq, not_number);
19698defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
19708defd9ff6930b4e24729971a61cf7469daf119beSteve Block  vldr(result, scratch2, HeapNumber::kValueOffset);
19718defd9ff6930b4e24729971a61cf7469daf119beSteve Block  bind(&done);
19728defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
19738defd9ff6930b4e24729971a61cf7469daf119beSteve Block
19748defd9ff6930b4e24729971a61cf7469daf119beSteve Block
19758defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid MacroAssembler::SmiToDoubleVFPRegister(Register smi,
19768defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                            DwVfpRegister value,
19778defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                            Register scratch1,
19788defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                            SwVfpRegister scratch2) {
19798defd9ff6930b4e24729971a61cf7469daf119beSteve Block  mov(scratch1, Operand(smi, ASR, kSmiTagSize));
19808defd9ff6930b4e24729971a61cf7469daf119beSteve Block  vmov(scratch2, scratch1);
19818defd9ff6930b4e24729971a61cf7469daf119beSteve Block  vcvt_f64_s32(value, scratch2);
19828defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
19838defd9ff6930b4e24729971a61cf7469daf119beSteve Block
19848defd9ff6930b4e24729971a61cf7469daf119beSteve Block
19859ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick// Tries to get a signed int32 out of a double precision floating point heap
19869ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick// number. Rounds towards 0. Branch to 'not_int32' if the double is out of the
19879ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick// 32bits signed integer range.
19889ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrickvoid MacroAssembler::ConvertToInt32(Register source,
19899ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                                    Register dest,
19909ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                                    Register scratch,
19919ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                                    Register scratch2,
19921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    DwVfpRegister double_scratch,
19939ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                                    Label *not_int32) {
19948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (CpuFeatures::IsSupported(VFP3)) {
19959ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    CpuFeatures::Scope scope(VFP3);
19969ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    sub(scratch, source, Operand(kHeapObjectTag));
19971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    vldr(double_scratch, scratch, HeapNumber::kValueOffset);
19981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    vcvt_s32_f64(double_scratch.low(), double_scratch);
19991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    vmov(dest, double_scratch.low());
20009ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // Signed vcvt instruction will saturate to the minimum (0x80000000) or
20019ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // maximun (0x7fffffff) signed 32bits integer when the double is out of
20029ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // range. When substracting one, the minimum signed integer becomes the
20039ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // maximun signed integer.
20049ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    sub(scratch, dest, Operand(1));
20059ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    cmp(scratch, Operand(LONG_MAX - 1));
20069ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // If equal then dest was LONG_MAX, if greater dest was LONG_MIN.
20079ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    b(ge, not_int32);
20089ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  } else {
20099ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // This code is faster for doubles that are in the ranges -0x7fffffff to
20109ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // -0x40000000 or 0x40000000 to 0x7fffffff. This corresponds almost to
20119ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // the range of signed int32 values that are not Smis.  Jumps to the label
20129ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // 'not_int32' if the double isn't in the range -0x80000000.0 to
20139ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // 0x80000000.0 (excluding the endpoints).
20149ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    Label right_exponent, done;
20159ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // Get exponent word.
20169ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    ldr(scratch, FieldMemOperand(source, HeapNumber::kExponentOffset));
20179ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // Get exponent alone in scratch2.
20189ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    Ubfx(scratch2,
2019e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         scratch,
2020e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         HeapNumber::kExponentShift,
2021e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         HeapNumber::kExponentBits);
20229ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // Load dest with zero.  We use this either for the final shift or
20239ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // for the answer.
20249ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    mov(dest, Operand(0, RelocInfo::NONE));
20259ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // Check whether the exponent matches a 32 bit signed int that is not a Smi.
20269ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). This is
20279ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // the exponent that we are fastest at and also the highest exponent we can
20289ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // handle here.
20299ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    const uint32_t non_smi_exponent = HeapNumber::kExponentBias + 30;
20309ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // The non_smi_exponent, 0x41d, is too big for ARM's immediate field so we
20319ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // split it up to avoid a constant pool entry.  You can't do that in general
20329ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // for cmp because of the overflow flag, but we know the exponent is in the
20339ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // range 0-2047 so there is no overflow.
20349ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    int fudge_factor = 0x400;
20359ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    sub(scratch2, scratch2, Operand(fudge_factor));
20369ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    cmp(scratch2, Operand(non_smi_exponent - fudge_factor));
20379ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // If we have a match of the int32-but-not-Smi exponent then skip some
20389ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // logic.
20399ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    b(eq, &right_exponent);
20409ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // If the exponent is higher than that then go to slow case.  This catches
20419ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // numbers that don't fit in a signed int32, infinities and NaNs.
20429ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    b(gt, not_int32);
20439ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
20449ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // We know the exponent is smaller than 30 (biased).  If it is less than
20459ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, ie
20469ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // it rounds to zero.
20479ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    const uint32_t zero_exponent = HeapNumber::kExponentBias + 0;
20489ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    sub(scratch2, scratch2, Operand(zero_exponent - fudge_factor), SetCC);
20499ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // Dest already has a Smi zero.
20509ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    b(lt, &done);
20519ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
20529ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // We have an exponent between 0 and 30 in scratch2.  Subtract from 30 to
20539ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // get how much to shift down.
20549ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    rsb(dest, scratch2, Operand(30));
20559ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
20569ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    bind(&right_exponent);
20579ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // Get the top bits of the mantissa.
20589ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    and_(scratch2, scratch, Operand(HeapNumber::kMantissaMask));
20599ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // Put back the implicit 1.
20609ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    orr(scratch2, scratch2, Operand(1 << HeapNumber::kExponentShift));
20619ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // Shift up the mantissa bits to take up the space the exponent used to
20629ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // take. We just orred in the implicit bit so that took care of one and
20639ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // we want to leave the sign bit 0 so we subtract 2 bits from the shift
20649ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // distance.
20659ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2;
20669ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    mov(scratch2, Operand(scratch2, LSL, shift_distance));
20679ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // Put sign in zero flag.
20689ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    tst(scratch, Operand(HeapNumber::kSignMask));
20699ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // Get the second half of the double. For some exponents we don't
20709ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // actually need this because the bits get shifted out again, but
20719ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // it's probably slower to test than just to do it.
20729ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    ldr(scratch, FieldMemOperand(source, HeapNumber::kMantissaOffset));
20739ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // Shift down 22 bits to get the last 10 bits.
20749ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    orr(scratch, scratch2, Operand(scratch, LSR, 32 - shift_distance));
20759ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // Move down according to the exponent.
20769ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    mov(dest, Operand(scratch, LSR, dest));
20779ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // Fix sign if sign bit was set.
20789ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    rsb(dest, dest, Operand(0, RelocInfo::NONE), LeaveCC, ne);
20799ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    bind(&done);
20809ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  }
20819ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick}
20829ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
20839ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
2084e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::EmitVFPTruncate(VFPRoundingMode rounding_mode,
2085e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     SwVfpRegister result,
2086e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     DwVfpRegister double_input,
2087e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     Register scratch1,
2088e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     Register scratch2,
2089e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     CheckForInexactConversion check_inexact) {
20908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsSupported(VFP3));
2091e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CpuFeatures::Scope scope(VFP3);
2092e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register prev_fpscr = scratch1;
2093e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Register scratch = scratch2;
2094e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2095e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int32_t check_inexact_conversion =
2096e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    (check_inexact == kCheckForInexactConversion) ? kVFPInexactExceptionBit : 0;
2097e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2098e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Set custom FPCSR:
2099e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //  - Set rounding mode.
2100e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //  - Clear vfp cumulative exception flags.
2101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //  - Make sure Flush-to-zero mode control bit is unset.
2102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  vmrs(prev_fpscr);
2103e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bic(scratch,
2104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      prev_fpscr,
2105e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Operand(kVFPExceptionMask |
2106e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              check_inexact_conversion |
2107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              kVFPRoundingModeMask |
2108e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              kVFPFlushToZeroMask));
2109e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // 'Round To Nearest' is encoded by 0b00 so no bits need to be set.
2110e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (rounding_mode != kRoundToNearest) {
2111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    orr(scratch, scratch, Operand(rounding_mode));
2112e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2113e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  vmsr(scratch);
2114e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2115e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Convert the argument to an integer.
2116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  vcvt_s32_f64(result,
2117e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch               double_input,
2118e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch               (rounding_mode == kRoundToZero) ? kDefaultRoundToZero
2119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                               : kFPSCRRounding);
2120e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Retrieve FPSCR.
2122e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  vmrs(scratch);
2123e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Restore FPSCR.
2124e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  vmsr(prev_fpscr);
2125e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Check for vfp exceptions.
2126e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  tst(scratch, Operand(kVFPExceptionMask | check_inexact_conversion));
2127e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2128e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2129e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
213044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::EmitOutOfInt32RangeTruncate(Register result,
213144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 Register input_high,
213244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 Register input_low,
213344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 Register scratch) {
213444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label done, normal_exponent, restore_sign;
213544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
213644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Extract the biased exponent in result.
213744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Ubfx(result,
213844f0eee88ff00398ff7f715fab053374d808c90dSteve Block       input_high,
213944f0eee88ff00398ff7f715fab053374d808c90dSteve Block       HeapNumber::kExponentShift,
214044f0eee88ff00398ff7f715fab053374d808c90dSteve Block       HeapNumber::kExponentBits);
214144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
214244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check for Infinity and NaNs, which should return 0.
214344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  cmp(result, Operand(HeapNumber::kExponentMask));
214444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(result, Operand(0), LeaveCC, eq);
214544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  b(eq, &done);
214644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
214744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Express exponent as delta to (number of mantissa bits + 31).
214844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sub(result,
214944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      result,
215044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits + 31),
215144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      SetCC);
215244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
215344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If the delta is strictly positive, all bits would be shifted away,
215444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // which means that we can return 0.
215544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  b(le, &normal_exponent);
215644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(result, Operand(0));
215744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  b(&done);
215844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
215944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&normal_exponent);
216044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int kShiftBase = HeapNumber::kNonMantissaBitsInTopWord - 1;
216144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Calculate shift.
216244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  add(scratch, result, Operand(kShiftBase + HeapNumber::kMantissaBits), SetCC);
216344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
216444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Save the sign.
216544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register sign = result;
216644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  result = no_reg;
216744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  and_(sign, input_high, Operand(HeapNumber::kSignMask));
216844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
216944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Set the implicit 1 before the mantissa part in input_high.
217044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  orr(input_high,
217144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      input_high,
217244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Operand(1 << HeapNumber::kMantissaBitsInTopWord));
217344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Shift the mantissa bits to the correct position.
217444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // We don't need to clear non-mantissa bits as they will be shifted away.
217544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If they weren't, it would mean that the answer is in the 32bit range.
217644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(input_high, Operand(input_high, LSL, scratch));
217744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
217844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Replace the shifted bits with bits from the lower mantissa word.
217944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label pos_shift, shift_done;
218044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  rsb(scratch, scratch, Operand(32), SetCC);
218144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  b(&pos_shift, ge);
218244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
218344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Negate scratch.
218444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  rsb(scratch, scratch, Operand(0));
218544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(input_low, Operand(input_low, LSL, scratch));
218644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  b(&shift_done);
218744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
218844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&pos_shift);
218944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(input_low, Operand(input_low, LSR, scratch));
219044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
219144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&shift_done);
219244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  orr(input_high, input_high, Operand(input_low));
219344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Restore sign if necessary.
219444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  cmp(sign, Operand(0));
219544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  result = sign;
219644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sign = no_reg;
219744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  rsb(result, input_high, Operand(0), LeaveCC, ne);
219844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(result, input_high, LeaveCC, eq);
219944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&done);
220044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
220144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
220244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
220344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::EmitECMATruncate(Register result,
220444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                      DwVfpRegister double_input,
220544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                      SwVfpRegister single_scratch,
220644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                      Register scratch,
220744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                      Register input_high,
220844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                      Register input_low) {
220944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CpuFeatures::Scope scope(VFP3);
221044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!input_high.is(result));
221144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!input_low.is(result));
221244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!input_low.is(input_high));
221344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!scratch.is(result) &&
221444f0eee88ff00398ff7f715fab053374d808c90dSteve Block         !scratch.is(input_high) &&
221544f0eee88ff00398ff7f715fab053374d808c90dSteve Block         !scratch.is(input_low));
221644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!single_scratch.is(double_input.low()) &&
221744f0eee88ff00398ff7f715fab053374d808c90dSteve Block         !single_scratch.is(double_input.high()));
221844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
221944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label done;
222044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
222144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Clear cumulative exception flags.
222244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ClearFPSCRBits(kVFPExceptionMask, scratch);
222344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Try a conversion to a signed integer.
222444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  vcvt_s32_f64(single_scratch, double_input);
222544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  vmov(result, single_scratch);
222644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Retrieve he FPSCR.
222744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  vmrs(scratch);
222844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check for overflow and NaNs.
222944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  tst(scratch, Operand(kVFPOverflowExceptionBit |
223044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                       kVFPUnderflowExceptionBit |
223144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                       kVFPInvalidOpExceptionBit));
223244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If we had no exceptions we are done.
223344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  b(eq, &done);
223444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
223544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Load the double value and perform a manual truncation.
223644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  vmov(input_low, input_high, double_input);
223744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  EmitOutOfInt32RangeTruncate(result,
223844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              input_high,
223944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              input_low,
224044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              scratch);
224144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bind(&done);
224244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
224344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
224444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
22453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::GetLeastBitsFromSmi(Register dst,
22463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                         Register src,
22473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                         int num_least_bits) {
22488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (CpuFeatures::IsSupported(ARMv7)) {
22497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ubfx(dst, src, kSmiTagSize, num_least_bits);
22503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  } else {
22513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    mov(dst, Operand(src, ASR, kSmiTagSize));
22523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    and_(dst, dst, Operand((1 << num_least_bits) - 1));
22533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
22543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
22553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
22563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
22571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::GetLeastBitsFromInt32(Register dst,
22581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                           Register src,
22591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                           int num_least_bits) {
22601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  and_(dst, src, Operand((1 << num_least_bits) - 1));
22611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
22621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
22631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
226444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallRuntime(const Runtime::Function* f,
226544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 int num_arguments) {
2266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All parameters are on the stack.  r0 has the return value after call.
2267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the expected number of arguments of the runtime function is
2269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // constant, we check that the actual number of arguments match the
2270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // expectation.
2271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (f->nargs >= 0 && f->nargs != num_arguments) {
2272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    IllegalOperation(num_arguments);
2273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // TODO(1236192): Most runtime routines don't need the number of
22774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // arguments passed in because it is constant. At some point we
22784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // should remove this need and make the runtime routine entry code
22794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // smarter.
22804515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  mov(r0, Operand(num_arguments));
228144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(r1, Operand(ExternalReference(f, isolate())));
22824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CEntryStub stub(1);
2283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CallStub(&stub);
2284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::CallRuntime(Runtime::FunctionId fid, int num_arguments) {
2288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CallRuntime(Runtime::FunctionForId(fid), num_arguments);
2289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) {
229344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const Runtime::Function* function = Runtime::FunctionForId(id);
2294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  mov(r0, Operand(function->nargs));
229544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  mov(r1, Operand(ExternalReference(function, isolate())));
2296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CEntryStub stub(1);
2297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  stub.SaveDoubles();
2298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CallStub(&stub);
2299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2302402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid MacroAssembler::CallExternalReference(const ExternalReference& ext,
2303402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                           int num_arguments) {
2304402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  mov(r0, Operand(num_arguments));
2305402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  mov(r1, Operand(ext));
2306402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2307402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CEntryStub stub(1);
2308402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CallStub(&stub);
2309402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
2310402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2311402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
23126ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
23136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               int num_arguments,
23146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               int result_size) {
2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // TODO(1236192): Most runtime routines don't need the number of
2316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // arguments passed in because it is constant. At some point we
2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // should remove this need and make the runtime routine entry code
2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // smarter.
2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(r0, Operand(num_arguments));
23206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  JumpToExternalReference(ext);
2321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23241e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockMaybeObject* MacroAssembler::TryTailCallExternalReference(
23251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    const ExternalReference& ext, int num_arguments, int result_size) {
23261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // TODO(1236192): Most runtime routines don't need the number of
23271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // arguments passed in because it is constant. At some point we
23281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // should remove this need and make the runtime routine entry code
23291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // smarter.
23301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  mov(r0, Operand(num_arguments));
23311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return TryJumpToExternalReference(ext);
23321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
23331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
23341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
23356ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
23366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     int num_arguments,
23376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     int result_size) {
233844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  TailCallExternalReference(ExternalReference(fid, isolate()),
233944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            num_arguments,
234044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            result_size);
23416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
23426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
23436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
23446ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpToExternalReference(const ExternalReference& builtin) {
2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if defined(__thumb__)
2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Thumb mode builtin.
2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1);
2348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(r1, Operand(builtin));
2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CEntryStub stub(1);
2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
2352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23551e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockMaybeObject* MacroAssembler::TryJumpToExternalReference(
23561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    const ExternalReference& builtin) {
23571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#if defined(__thumb__)
23581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Thumb mode builtin.
23591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1);
23601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
23611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  mov(r1, Operand(builtin));
23621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  CEntryStub stub(1);
23631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return TryTailCallStub(&stub);
23641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
23651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
23661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
2368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   InvokeFlag flag,
2369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   const CallWrapper& call_wrapper) {
2370402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GetBuiltinEntry(r2, id);
2371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (flag == CALL_FUNCTION) {
2372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    call_wrapper.BeforeCall(CallSize(r2));
2373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SetCallKind(r5, CALL_AS_METHOD);
2374402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Call(r2);
2375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    call_wrapper.AfterCall();
2376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(flag == JUMP_FUNCTION);
2378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SetCallKind(r5, CALL_AS_METHOD);
2379402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Jump(r2);
2380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2384791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid MacroAssembler::GetBuiltinFunction(Register target,
2385791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                        Builtins::JavaScript id) {
23866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Load the builtins object into target register.
23876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ldr(target, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
23886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ldr(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset));
2389402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Load the JavaScript builtin function from the builtins object.
2390791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  ldr(target, FieldMemOperand(target,
23916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                          JSBuiltinsObject::OffsetOfFunctionWithId(id)));
2392791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
2393791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
23946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2395791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
2396791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  ASSERT(!target.is(r1));
2397791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  GetBuiltinFunction(r1, id);
23986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Load the code entry point from the builtins object.
2399791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  ldr(target, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
2400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::SetCounter(StatsCounter* counter, int value,
2404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Register scratch1, Register scratch2) {
2405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(scratch1, Operand(value));
2407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(scratch2, Operand(ExternalReference(counter)));
2408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    str(scratch1, MemOperand(scratch2));
2409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::IncrementCounter(StatsCounter* counter, int value,
2414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register scratch1, Register scratch2) {
2415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(value > 0);
2416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(scratch2, Operand(ExternalReference(counter)));
2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ldr(scratch1, MemOperand(scratch2));
2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    add(scratch1, scratch1, Operand(value));
2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    str(scratch1, MemOperand(scratch2));
2421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::DecrementCounter(StatsCounter* counter, int value,
2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register scratch1, Register scratch2) {
2427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(value > 0);
2428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_native_code_counters && counter->Enabled()) {
2429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(scratch2, Operand(ExternalReference(counter)));
2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ldr(scratch1, MemOperand(scratch2));
2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    sub(scratch1, scratch1, Operand(value));
2432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    str(scratch1, MemOperand(scratch2));
2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Assert(Condition cond, const char* msg) {
243844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code())
24391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Check(cond, msg);
2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid MacroAssembler::AssertRegisterIsRoot(Register reg,
24449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                          Heap::RootListIndex index) {
244544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
24469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    LoadRoot(ip, index);
24479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    cmp(reg, ip);
24489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    Check(eq, "Register did not match expected root");
24499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
24509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
24519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
24529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2453756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AssertFastElements(Register elements) {
245444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
2455756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    ASSERT(!elements.is(ip));
2456756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Label ok;
2457756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    push(elements);
2458756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    ldr(elements, FieldMemOperand(elements, HeapObject::kMapOffset));
2459756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
2460756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    cmp(elements, ip);
2461756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    b(eq, &ok);
2462756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
2463756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    cmp(elements, ip);
2464756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    b(eq, &ok);
2465756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Abort("JSObject with fast elements map has slow elements");
2466756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    bind(&ok);
2467756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    pop(elements);
2468756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
2469756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2470756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2471756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
24721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::Check(Condition cond, const char* msg) {
2473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label L;
24741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  b(cond, &L);
2475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Abort(msg);
2476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // will not return here
2477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind(&L);
2478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MacroAssembler::Abort(const char* msg) {
24828defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label abort_start;
24838defd9ff6930b4e24729971a61cf7469daf119beSteve Block  bind(&abort_start);
2484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We want to pass the msg string like a smi to avoid GC
2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // problems, however msg is not guaranteed to be aligned
2486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // properly. Instead, we pass an aligned pointer that is
2487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // a proper v8 smi, but also pass the alignment difference
2488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // from the real pointer as a smi.
2489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  intptr_t p1 = reinterpret_cast<intptr_t>(msg);
2490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag;
2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(reinterpret_cast<Object*>(p0)->IsSmi());
2492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (msg != NULL) {
2494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment("Abort message: ");
2495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordComment(msg);
2496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Disable stub call restrictions to always allow calls to abort.
2499086aeeaae12517475c22695a200be45495516549Ben Murdoch  AllowStubCallsScope allow_scope(this, true);
2500d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(r0, Operand(p0));
2502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(r0);
2503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mov(r0, Operand(Smi::FromInt(p1 - p0)));
2504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  push(r0);
2505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CallRuntime(Runtime::kAbort, 2);
2506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // will not return here
25078defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (is_const_pool_blocked()) {
25088defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // If the calling code cares about the exact number of
25098defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // instructions generated, we insert padding here to keep the size
25108defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // of the Abort macro constant.
25118defd9ff6930b4e24729971a61cf7469daf119beSteve Block    static const int kExpectedAbortInstructions = 10;
25128defd9ff6930b4e24729971a61cf7469daf119beSteve Block    int abort_instructions = InstructionsGeneratedSince(&abort_start);
25138defd9ff6930b4e24729971a61cf7469daf119beSteve Block    ASSERT(abort_instructions <= kExpectedAbortInstructions);
25148defd9ff6930b4e24729971a61cf7469daf119beSteve Block    while (abort_instructions++ < kExpectedAbortInstructions) {
25158defd9ff6930b4e24729971a61cf7469daf119beSteve Block      nop();
25168defd9ff6930b4e24729971a61cf7469daf119beSteve Block    }
25178defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
2518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2521d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid MacroAssembler::LoadContext(Register dst, int context_chain_length) {
2522d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (context_chain_length > 0) {
2523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Move up the chain of contexts to the context containing the slot.
2524d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ldr(dst, MemOperand(cp, Context::SlotOffset(Context::CLOSURE_INDEX)));
2525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Load the function context (which is the incoming, outer context).
2526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ldr(dst, FieldMemOperand(dst, JSFunction::kContextOffset));
2527d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    for (int i = 1; i < context_chain_length; i++) {
2528d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      ldr(dst, MemOperand(dst, Context::SlotOffset(Context::CLOSURE_INDEX)));
2529d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      ldr(dst, FieldMemOperand(dst, JSFunction::kContextOffset));
2530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
2531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
2532e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Slot is in the current function context.  Move it into the
2533e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // destination register in case we store into it (the write barrier
2534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // cannot be allowed to destroy the context in esi).
2535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    mov(dst, cp);
2536e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2537e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2538e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // We should not have found a 'with' context by walking the context chain
2539e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // (i.e., the static scope chain and runtime context chain do not agree).
2540e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // A variable occurring in such a scope should have slot type LOOKUP and
2541e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // not CONTEXT.
254244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
2543e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ldr(ip, MemOperand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX)));
2544e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    cmp(dst, ip);
2545e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Check(eq, "Yo dawg, I heard you liked function contexts "
2546e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              "so I put function contexts in all your contexts");
2547d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2548d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2549d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
25518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::LoadGlobalFunction(int index, Register function) {
25528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the global or builtins object from the current context.
25538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ldr(function, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
25548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the global context from the global or builtins object.
25558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ldr(function, FieldMemOperand(function,
25568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                GlobalObject::kGlobalContextOffset));
25578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the function from the global context.
25588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ldr(function, MemOperand(function, Context::SlotOffset(index)));
25598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
25608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
25618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
25628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
25638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                                  Register map,
25648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                                  Register scratch) {
25658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the initial map. The global functions all have initial maps.
25668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ldr(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
256744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
25688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    Label ok, fail;
2569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK);
25708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    b(&ok);
25718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    bind(&fail);
25728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    Abort("Global functions must have initial map");
25738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    bind(&ok);
25748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
25758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
25768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
25778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
25781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::JumpIfNotPowerOfTwoOrZero(
25791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Register reg,
25801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Register scratch,
25811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Label* not_power_of_two_or_zero) {
25821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  sub(scratch, reg, Operand(1), SetCC);
25831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  b(mi, not_power_of_two_or_zero);
25841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  tst(scratch, reg);
25851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  b(ne, not_power_of_two_or_zero);
25861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
25871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
25881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
258944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::JumpIfNotPowerOfTwoOrZeroAndNeg(
259044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register reg,
259144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Register scratch,
259244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Label* zero_and_neg,
259344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Label* not_power_of_two) {
259444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sub(scratch, reg, Operand(1), SetCC);
259544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  b(mi, zero_and_neg);
259644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  tst(scratch, reg);
259744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  b(ne, not_power_of_two);
259844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
259944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
260044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
26013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::JumpIfNotBothSmi(Register reg1,
26023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                      Register reg2,
26033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                      Label* on_not_both_smi) {
26041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  STATIC_ASSERT(kSmiTag == 0);
26053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  tst(reg1, Operand(kSmiTagMask));
26063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  tst(reg2, Operand(kSmiTagMask), eq);
26073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  b(ne, on_not_both_smi);
26083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
26093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
26103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
26113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid MacroAssembler::JumpIfEitherSmi(Register reg1,
26123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                     Register reg2,
26133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                     Label* on_either_smi) {
26141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  STATIC_ASSERT(kSmiTag == 0);
26153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  tst(reg1, Operand(kSmiTagMask));
26163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  tst(reg2, Operand(kSmiTagMask), ne);
26173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  b(eq, on_either_smi);
26183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
26193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
26203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2621756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid MacroAssembler::AbortIfSmi(Register object) {
26221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  STATIC_ASSERT(kSmiTag == 0);
2623756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  tst(object, Operand(kSmiTagMask));
2624756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Assert(ne, "Operand is a smi");
2625756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2626756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2627756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
26281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::AbortIfNotSmi(Register object) {
26291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  STATIC_ASSERT(kSmiTag == 0);
26301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  tst(object, Operand(kSmiTagMask));
26311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Assert(eq, "Operand is not smi");
26321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
26331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
26341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2635e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::AbortIfNotString(Register object) {
2636e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
2637e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  tst(object, Operand(kSmiTagMask));
2638e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Assert(ne, "Operand is not a string");
2639e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  push(object);
2640e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ldr(object, FieldMemOperand(object, HeapObject::kMapOffset));
2641e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompareInstanceType(object, object, FIRST_NONSTRING_TYPE);
2642e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  pop(object);
2643e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Assert(lo, "Operand is not a string");
2644e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2645e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2646e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2647e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
26481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::AbortIfNotRootValue(Register src,
26491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                         Heap::RootListIndex root_value_index,
26501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                         const char* message) {
2651e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CompareRoot(src, root_value_index);
26521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Assert(eq, message);
26531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
26541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
26551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
26561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::JumpIfNotHeapNumber(Register object,
26571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                         Register heap_number_map,
26581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                         Register scratch,
26591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                         Label* on_not_heap_number) {
26601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
26611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
26621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  cmp(scratch, heap_number_map);
26631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  b(ne, on_not_heap_number);
26641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
26651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
26661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2667d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::JumpIfNonSmisNotBothSequentialAsciiStrings(
2668d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Register first,
2669d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Register second,
2670d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Register scratch1,
2671d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Register scratch2,
2672d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Label* failure) {
2673d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Test that both first and second are sequential ASCII strings.
2674d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Assume that they are non-smis.
2675d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ldr(scratch1, FieldMemOperand(first, HeapObject::kMapOffset));
2676d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ldr(scratch2, FieldMemOperand(second, HeapObject::kMapOffset));
2677d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
2678d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ldrb(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset));
26796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  JumpIfBothInstanceTypesAreNotSequentialAscii(scratch1,
26816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               scratch2,
26826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               scratch1,
26836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               scratch2,
26846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               failure);
2685d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2686d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2687d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first,
2688d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                                         Register second,
2689d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                                         Register scratch1,
2690d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                                         Register scratch2,
2691d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                                         Label* failure) {
2692d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Check that neither is a smi.
26931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  STATIC_ASSERT(kSmiTag == 0);
2694d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  and_(scratch1, first, Operand(second));
2695d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  tst(scratch1, Operand(kSmiTagMask));
2696d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  b(eq, failure);
2697d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  JumpIfNonSmisNotBothSequentialAsciiStrings(first,
2698d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                             second,
2699d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                             scratch1,
2700d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                             scratch2,
2701d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                             failure);
2702d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
2703d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
27056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Allocates a heap number or jumps to the need_gc label if the young space
27066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// is full and a scavenge is needed.
27076ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::AllocateHeapNumber(Register result,
27086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                        Register scratch1,
27096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                        Register scratch2,
27109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                        Register heap_number_map,
27116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                        Label* gc_required) {
27126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Allocate an object in the heap for the heap number and tag it as a heap
27136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // object.
271425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  AllocateInNewSpace(HeapNumber::kSize,
27156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     result,
27166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     scratch1,
27176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     scratch2,
27186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     gc_required,
27196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     TAG_OBJECT);
27206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Store heap number map in the allocated object.
27229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
27239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  str(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
27246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
27256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27278defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid MacroAssembler::AllocateHeapNumberWithValue(Register result,
27288defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                                 DwVfpRegister value,
27298defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                                 Register scratch1,
27308defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                                 Register scratch2,
27318defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                                 Register heap_number_map,
27328defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                                 Label* gc_required) {
27338defd9ff6930b4e24729971a61cf7469daf119beSteve Block  AllocateHeapNumber(result, scratch1, scratch2, heap_number_map, gc_required);
27348defd9ff6930b4e24729971a61cf7469daf119beSteve Block  sub(scratch1, result, Operand(kHeapObjectTag));
27358defd9ff6930b4e24729971a61cf7469daf119beSteve Block  vstr(value, scratch1, HeapNumber::kValueOffset);
27368defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
27378defd9ff6930b4e24729971a61cf7469daf119beSteve Block
27388defd9ff6930b4e24729971a61cf7469daf119beSteve Block
2739bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch// Copies a fixed number of fields of heap objects from src to dst.
2740bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid MacroAssembler::CopyFields(Register dst,
2741bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                Register src,
2742bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                RegList temps,
2743bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                int field_count) {
2744bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // At least one bit set in the first 15 registers.
2745bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT((temps & ((1 << 15) - 1)) != 0);
2746bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT((temps & dst.bit()) == 0);
2747bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT((temps & src.bit()) == 0);
2748bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Primitive implementation using only one temporary register.
2749bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2750bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register tmp = no_reg;
2751bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Find a temp register in temps list.
2752bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  for (int i = 0; i < 15; i++) {
2753bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    if ((temps & (1 << i)) != 0) {
2754bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      tmp.set_code(i);
2755bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      break;
2756bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    }
2757bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
2758bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT(!tmp.is(no_reg));
2759bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2760bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  for (int i = 0; i < field_count; i++) {
2761bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    ldr(tmp, FieldMemOperand(src, i * kPointerSize));
2762bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    str(tmp, FieldMemOperand(dst, i * kPointerSize));
2763bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
2764bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
2765bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2766bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2767e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MacroAssembler::CopyBytes(Register src,
2768e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               Register dst,
2769e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               Register length,
2770e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               Register scratch) {
2771e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Label align_loop, align_loop_1, word_loop, byte_loop, byte_loop_1, done;
2772e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2773e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Align src before copying in word size chunks.
2774e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bind(&align_loop);
2775e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  cmp(length, Operand(0));
2776e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  b(eq, &done);
2777e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bind(&align_loop_1);
2778e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  tst(src, Operand(kPointerSize - 1));
2779e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  b(eq, &word_loop);
2780e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ldrb(scratch, MemOperand(src, 1, PostIndex));
2781e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  strb(scratch, MemOperand(dst, 1, PostIndex));
2782e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  sub(length, length, Operand(1), SetCC);
2783e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  b(ne, &byte_loop_1);
2784e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2785e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Copy bytes in word size chunks.
2786e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bind(&word_loop);
278744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
2788e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    tst(src, Operand(kPointerSize - 1));
2789e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Assert(eq, "Expecting alignment for CopyBytes");
2790e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2791e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  cmp(length, Operand(kPointerSize));
2792e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  b(lt, &byte_loop);
2793e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ldr(scratch, MemOperand(src, kPointerSize, PostIndex));
2794e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#if CAN_USE_UNALIGNED_ACCESSES
2795e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  str(scratch, MemOperand(dst, kPointerSize, PostIndex));
2796e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#else
2797e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  strb(scratch, MemOperand(dst, 1, PostIndex));
2798e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(scratch, Operand(scratch, LSR, 8));
2799e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  strb(scratch, MemOperand(dst, 1, PostIndex));
2800e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(scratch, Operand(scratch, LSR, 8));
2801e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  strb(scratch, MemOperand(dst, 1, PostIndex));
2802e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  mov(scratch, Operand(scratch, LSR, 8));
2803e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  strb(scratch, MemOperand(dst, 1, PostIndex));
2804e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#endif
2805e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  sub(length, length, Operand(kPointerSize));
2806e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  b(&word_loop);
2807e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2808e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Copy the last bytes if any left.
2809e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bind(&byte_loop);
2810e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  cmp(length, Operand(0));
2811e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  b(eq, &done);
2812e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bind(&byte_loop_1);
2813e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ldrb(scratch, MemOperand(src, 1, PostIndex));
2814e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  strb(scratch, MemOperand(dst, 1, PostIndex));
2815e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  sub(length, length, Operand(1), SetCC);
2816e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  b(ne, &byte_loop_1);
2817e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bind(&done);
2818e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2819e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2820e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
28218defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid MacroAssembler::CountLeadingZeros(Register zeros,   // Answer.
28228defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                       Register source,  // Input.
28238defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                       Register scratch) {
28241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(!zeros.is(source) || !source.is(scratch));
28258defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(!zeros.is(scratch));
28268defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(!scratch.is(ip));
28278defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(!source.is(ip));
28288defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(!zeros.is(ip));
28296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef CAN_USE_ARMV5_INSTRUCTIONS
28306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  clz(zeros, source);  // This instruction is only supported after ARM5.
28316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#else
28329ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  mov(zeros, Operand(0, RelocInfo::NONE));
28338defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Move(scratch, source);
28346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Top 16.
28356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  tst(scratch, Operand(0xffff0000));
28366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  add(zeros, zeros, Operand(16), LeaveCC, eq);
28376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(scratch, Operand(scratch, LSL, 16), LeaveCC, eq);
28386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Top 8.
28396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  tst(scratch, Operand(0xff000000));
28406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  add(zeros, zeros, Operand(8), LeaveCC, eq);
28416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(scratch, Operand(scratch, LSL, 8), LeaveCC, eq);
28426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Top 4.
28436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  tst(scratch, Operand(0xf0000000));
28446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  add(zeros, zeros, Operand(4), LeaveCC, eq);
28456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(scratch, Operand(scratch, LSL, 4), LeaveCC, eq);
28466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Top 2.
28476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  tst(scratch, Operand(0xc0000000));
28486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  add(zeros, zeros, Operand(2), LeaveCC, eq);
28496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  mov(scratch, Operand(scratch, LSL, 2), LeaveCC, eq);
28506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Top bit.
28516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  tst(scratch, Operand(0x80000000u));
28526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  add(zeros, zeros, Operand(1), LeaveCC, eq);
28536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
28546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
28556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
28566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
28576ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii(
28586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register first,
28596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register second,
28606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register scratch1,
28616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register scratch2,
28626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label* failure) {
28636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int kFlatAsciiStringMask =
28646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
28656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int kFlatAsciiStringTag = ASCII_STRING_TYPE;
28666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  and_(scratch1, first, Operand(kFlatAsciiStringMask));
28676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  and_(scratch2, second, Operand(kFlatAsciiStringMask));
28686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  cmp(scratch1, Operand(kFlatAsciiStringTag));
28696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Ignore second test if first test failed.
28706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  cmp(scratch2, Operand(kFlatAsciiStringTag), eq);
28716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  b(ne, failure);
28726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
28736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
28746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
28756ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(Register type,
28766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                                            Register scratch,
28776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                                            Label* failure) {
28786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int kFlatAsciiStringMask =
28796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
28806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int kFlatAsciiStringTag = ASCII_STRING_TYPE;
28816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  and_(scratch, type, Operand(kFlatAsciiStringMask));
28826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  cmp(scratch, Operand(kFlatAsciiStringTag));
28836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  b(ne, failure);
28846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
28856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
288644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const int kRegisterPassedArguments = 4;
28876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
288844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochint MacroAssembler::CalculateStackPassedWords(int num_reg_arguments,
2890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              int num_double_arguments) {
2891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int stack_passed_words = 0;
2892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (use_eabi_hardfloat()) {
2893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // In the hard floating point calling convention, we can use
2894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // all double registers to pass doubles.
2895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (num_double_arguments > DoubleRegister::kNumRegisters) {
2896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      stack_passed_words +=
2897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          2 * (num_double_arguments - DoubleRegister::kNumRegisters);
2898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
2899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
2900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // In the soft floating point calling convention, every double
2901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // argument is passed using two registers.
2902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    num_reg_arguments += 2 * num_double_arguments;
2903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
29046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Up to four simple arguments are passed in registers r0..r3.
2905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (num_reg_arguments > kRegisterPassedArguments) {
2906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    stack_passed_words += num_reg_arguments - kRegisterPassedArguments;
2907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return stack_passed_words;
2909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
2913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          int num_double_arguments,
2914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Register scratch) {
2915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int frame_alignment = ActivationFrameAlignment();
2916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int stack_passed_arguments = CalculateStackPassedWords(
2917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      num_reg_arguments, num_double_arguments);
29186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (frame_alignment > kPointerSize) {
29196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Make stack end at alignment and make room for num_arguments - 4 words
29206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // and the original value of sp.
29216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    mov(scratch, sp);
29226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    sub(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize));
29236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(IsPowerOf2(frame_alignment));
29246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    and_(sp, sp, Operand(-frame_alignment));
29256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    str(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize));
29266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
29276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    sub(sp, sp, Operand(stack_passed_arguments * kPointerSize));
29286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
29296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
29306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
29316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
2933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          Register scratch) {
2934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  PrepareCallCFunction(num_reg_arguments, 0, scratch);
2935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg) {
2939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (use_eabi_hardfloat()) {
2940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Move(d0, dreg);
2941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
2942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    vmov(r0, r1, dreg);
2943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg1,
2948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             DoubleRegister dreg2) {
2949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (use_eabi_hardfloat()) {
2950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (dreg2.is(d0)) {
2951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ASSERT(!dreg1.is(d1));
2952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Move(d1, dreg2);
2953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Move(d0, dreg1);
2954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
2955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Move(d0, dreg1);
2956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Move(d1, dreg2);
2957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
2958257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
2959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    vmov(r0, r1, dreg1);
2960257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    vmov(r2, r3, dreg2);
2961257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2962257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg,
2966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register reg) {
2967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (use_eabi_hardfloat()) {
2968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Move(d0, dreg);
2969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Move(r0, reg);
2970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
2971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Move(r2, reg);
2972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    vmov(r0, r1, dreg);
2973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
29776ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid MacroAssembler::CallCFunction(ExternalReference function,
2978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   int num_reg_arguments,
2979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   int num_double_arguments) {
2980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CallCFunctionHelper(no_reg,
2981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      function,
2982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      ip,
2983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      num_reg_arguments,
2984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      num_double_arguments);
29856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
29866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
298844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallCFunction(Register function,
2989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Register scratch,
2990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     int num_reg_arguments,
2991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     int num_double_arguments) {
299244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CallCFunctionHelper(function,
299344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      ExternalReference::the_hole_value_location(isolate()),
299444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      scratch,
2995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      num_reg_arguments,
2996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      num_double_arguments);
2997257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::CallCFunction(ExternalReference function,
3001257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   int num_arguments) {
3002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CallCFunction(function, num_arguments, 0);
3003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3006257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::CallCFunction(Register function,
3007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   Register scratch,
3008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   int num_arguments) {
3009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CallCFunction(function, scratch, num_arguments, 0);
301044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
301144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
301244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
301344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MacroAssembler::CallCFunctionHelper(Register function,
301444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         ExternalReference function_reference,
301544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                         Register scratch,
3016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                         int num_reg_arguments,
3017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                         int num_double_arguments) {
30186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Make sure that the stack is aligned before calling a C function unless
30196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // running in the simulator. The simulator has its own alignment check which
30206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // provides more information.
30216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#if defined(V8_HOST_ARCH_ARM)
302244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
30236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int frame_alignment = OS::ActivationFrameAlignment();
30246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int frame_alignment_mask = frame_alignment - 1;
30256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (frame_alignment > kPointerSize) {
30266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ASSERT(IsPowerOf2(frame_alignment));
30276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Label alignment_as_expected;
30286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      tst(sp, Operand(frame_alignment_mask));
30296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      b(eq, &alignment_as_expected);
30306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Don't use Check here, as it will call Runtime_Abort possibly
30316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // re-entering here.
30326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      stop("Unexpected alignment");
30336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      bind(&alignment_as_expected);
30346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
30356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
30366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
30376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
30386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Just call directly. The function called cannot cause a GC, or
30396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // allow preemption, so the return address in the link register
30406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // stays correct.
304144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (function.is(no_reg)) {
304244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mov(scratch, Operand(function_reference));
304344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    function = scratch;
304444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
30456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Call(function);
3046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int stack_passed_arguments = CalculateStackPassedWords(
3047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      num_reg_arguments, num_double_arguments);
3048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (ActivationFrameAlignment() > kPointerSize) {
30496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ldr(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
30506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
30516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    add(sp, sp, Operand(stack_passed_arguments * sizeof(kPointerSize)));
30526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
30536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
30546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
30556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
30561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid MacroAssembler::GetRelocatedValueLocation(Register ldr_location,
30571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                               Register result) {
30581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  const uint32_t kLdrOffsetMask = (1 << 12) - 1;
30591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  const int32_t kPCRegOffset = 2 * kPointerSize;
30601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ldr(result, MemOperand(ldr_location));
306144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (emit_debug_code()) {
30621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Check that the instruction is a ldr reg, [pc + offset] .
30631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    and_(result, result, Operand(kLdrPCPattern));
30641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    cmp(result, Operand(kLdrPCPattern));
30651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Check(eq, "The instruction to patch should be a load from pc.");
30661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Result was clobbered. Restore it.
30671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ldr(result, MemOperand(ldr_location));
30681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
30691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Get the address of the constant.
30701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  and_(result, result, Operand(kLdrOffsetMask));
30711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  add(result, ldr_location, Operand(result));
30721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  add(result, result, Operand(kPCRegOffset));
30731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
30741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
30751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampUint8(Register output_reg, Register input_reg) {
3077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Usat(output_reg, 8, Operand(input_reg));
3078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::ClampDoubleToUint8(Register result_reg,
3082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        DoubleRegister input_reg,
3083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                        DoubleRegister temp_double_reg) {
3084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label above_zero;
3085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
3086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label in_bounds;
3087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  vmov(temp_double_reg, 0.0);
3089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  VFPCompareAndSetFlags(input_reg, temp_double_reg);
3090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  b(gt, &above_zero);
3091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Double value is less than zero, NaN or Inf, return 0.
3093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  mov(result_reg, Operand(0));
3094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  b(al, &done);
3095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Double value is >= 255, return 255.
3097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&above_zero);
3098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  vmov(temp_double_reg, 255.0);
3099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  VFPCompareAndSetFlags(input_reg, temp_double_reg);
3100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  b(le, &in_bounds);
3101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  mov(result_reg, Operand(255));
3102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  b(al, &done);
3103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // In 0-255 range, round and truncate.
3105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&in_bounds);
3106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  vmov(temp_double_reg, 0.5);
3107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  vadd(temp_double_reg, input_reg, temp_double_reg);
3108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  vcvt_u32_f64(s0, temp_double_reg);
3109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  vmov(result_reg, s0);
3110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&done);
3111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid MacroAssembler::LoadInstanceDescriptors(Register map,
3115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             Register descriptors) {
3116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ldr(descriptors,
3117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      FieldMemOperand(map, Map::kInstanceDescriptorsOrBitField3Offset));
3118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label not_smi;
3119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  JumpIfNotSmi(descriptors, &not_smi);
3120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  mov(descriptors, Operand(FACTORY->empty_descriptor_array()));
3121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bind(&not_smi);
3122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::CodePatcher(byte* address, int instructions)
3126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : address_(address),
3127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      instructions_(instructions),
3128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      size_(instructions * Assembler::kInstrSize),
31298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      masm_(Isolate::Current(), address, size_ + Assembler::kGap) {
3130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a new macro assembler pointing to the address of the code to patch.
3131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The size is adjusted with kGap on order for the assembler to generate size
3132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bytes of instructions without failing with buffer size constraints.
3133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
3134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCodePatcher::~CodePatcher() {
3138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indicate that code has changed.
3139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CPU::FlushICache(address_, size_);
3140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the code was patched as expected.
3142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(masm_.pc_ == address_ + size_);
3143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
3144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid CodePatcher::Emit(Instr instr) {
31481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  masm()->emit(instr);
3149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CodePatcher::Emit(Address addr) {
3153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  masm()->emit(reinterpret_cast<Instr>(addr));
3154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
31551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
31561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
31571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid CodePatcher::EmitCondition(Condition cond) {
31581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Instr instr = Assembler::instr_at(masm_.pc_);
31591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  instr = (instr & ~kCondMask) | cond;
31601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  masm_.emit(instr);
31611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
3162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
3165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_ARM
3167