1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright (c) 1994-2006 Sun Microsystems Inc.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// All Rights Reserved.
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// are met:
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// - Redistributions of source code must retain the above copyright notice,
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// this list of conditions and the following disclaimer.
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// - Redistribution in binary form must reproduce the above copyright
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer in the
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// documentation and/or other materials provided with the
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// distribution.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// - Neither the name of Sun Microsystems or the names of contributors may
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// be used to endorse or promote products derived from this software without
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// specific prior written permission.
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THE POSSIBILITY OF SUCH DAMAGE.
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The original source code covered by the above license above has been modified
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// significantly by Google Inc.
35692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_ARM_ASSEMBLER_ARM_INL_H_
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_ARM_ASSEMBLER_ARM_INL_H_
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "arm/assembler-arm.h"
413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "cpu.h"
43f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#include "debug.h"
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
50692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdochint DwVfpRegister::ToAllocationIndex(DwVfpRegister reg) {
51692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  ASSERT(!reg.is(kDoubleRegZero));
52692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  ASSERT(!reg.is(kScratchDoubleReg));
53692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  return reg.code();
54692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch}
55692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch
56692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RelocInfo::apply(intptr_t delta) {
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (RelocInfo::IsInternalReference(rmode_)) {
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // absolute code pointer inside code object moves with the code object.
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int32_t* p = reinterpret_cast<int32_t*>(pc_);
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *p += delta;  // relocate entry
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We do not use pc relative addressing on ARM, so there is
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // nothing else to do.
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAddress RelocInfo::target_address() {
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Assembler::target_address_at(pc_);
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAddress RelocInfo::target_address_address() {
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              || rmode_ == EMBEDDED_OBJECT
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              || rmode_ == EXTERNAL_REFERENCE);
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return reinterpret_cast<Address>(Assembler::target_address_address_at(pc_));
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
82f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkeint RelocInfo::target_address_size() {
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return kPointerSize;
84f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
85f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
86f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid RelocInfo::set_target_address(Address target, WriteBarrierMode mode) {
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Assembler::set_target_address_at(pc_, target);
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (mode == UPDATE_WRITE_BARRIER && host() != NULL && IsCodeTarget(rmode_)) {
913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Object* target_code = Code::GetCodeFromTargetAddress(target);
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        host(), this, HeapObject::cast(target_code));
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* RelocInfo::target_object() {
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
1003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return Memory::Object_at(Assembler::target_address_address_at(pc_));
1013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
1023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
104d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockHandle<Object> RelocInfo::target_object_handle(Assembler* origin) {
1053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
1063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return Memory::Object_Handle_at(Assembler::target_address_address_at(pc_));
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject** RelocInfo::target_object_address() {
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return reinterpret_cast<Object**>(Assembler::target_address_address_at(pc_));
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) {
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Assembler::set_target_address_at(pc_, reinterpret_cast<Address>(target));
1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (mode == UPDATE_WRITE_BARRIER &&
1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      host() != NULL &&
1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      target->IsHeapObject()) {
1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    host()->GetHeap()->incremental_marking()->RecordWrite(
1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        host(), &Memory::Object_at(pc_), HeapObject::cast(target));
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAddress* RelocInfo::target_reference_address() {
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(rmode_ == EXTERNAL_REFERENCE);
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return reinterpret_cast<Address*>(Assembler::target_address_address_at(pc_));
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHandle<JSGlobalPropertyCell> RelocInfo::target_cell_handle() {
135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Address address = Memory::Address_at(pc_);
137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return Handle<JSGlobalPropertyCell>(
138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      reinterpret_cast<JSGlobalPropertyCell**>(address));
139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochJSGlobalPropertyCell* RelocInfo::target_cell() {
143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Address address = Memory::Address_at(pc_);
145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Object* object = HeapObject::FromAddress(
146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      address - JSGlobalPropertyCell::kValueOffset);
147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return reinterpret_cast<JSGlobalPropertyCell*>(object);
148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid RelocInfo::set_target_cell(JSGlobalPropertyCell* cell,
1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                WriteBarrierMode mode) {
153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Address address = cell->address() + JSGlobalPropertyCell::kValueOffset;
155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Memory::Address_at(pc_) = address;
1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (mode == UPDATE_WRITE_BARRIER && host() != NULL) {
1573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // TODO(1550) We are passing NULL as a slot because cell can never be on
1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // evacuation candidate.
1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    host()->GetHeap()->incremental_marking()->RecordWrite(
1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        host(), NULL, cell);
1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAddress RelocInfo::call_address() {
1667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // The 2 instructions offset assumes patched debug break slot or return
1677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // sequence.
1687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
1697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch         (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Memory::Address_at(pc_ + 2 * Assembler::kInstrSize);
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RelocInfo::set_call_address(Address target) {
175bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
176bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch         (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Memory::Address_at(pc_ + 2 * Assembler::kInstrSize) = target;
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (host() != NULL) {
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Object* target_code = Code::GetCodeFromTargetAddress(target);
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        host(), this, HeapObject::cast(target_code));
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* RelocInfo::call_object() {
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return *call_object_address();
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
191bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochvoid RelocInfo::set_call_object(Object* target) {
192bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  *call_object_address() = target;
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
196bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject** RelocInfo::call_object_address() {
197bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
198bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch         (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
199bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize);
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockbool RelocInfo::IsPatchedReturnSequence() {
2046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Instr current_instr = Assembler::instr_at(pc_);
2056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Instr next_instr = Assembler::instr_at(pc_ + Assembler::kInstrSize);
2066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef USE_BLX
2076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // A patched return sequence is:
2086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  ldr ip, [pc, #0]
2096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  blx ip
2106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return ((current_instr & kLdrPCMask) == kLdrPCPattern)
2116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          && ((next_instr & kBlxRegMask) == kBlxRegPattern);
2126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#else
2136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // A patched return sequence is:
2146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  mov lr, pc
2156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  ldr pc, [pc, #-4]
2166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return (current_instr == kMovLrPc)
2176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          && ((next_instr & kLdrPCMask) == kLdrPCPattern);
2186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochbool RelocInfo::IsPatchedDebugBreakSlotSequence() {
2237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Instr current_instr = Assembler::instr_at(pc_);
2248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP);
2257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
228f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid RelocInfo::Visit(ObjectVisitor* visitor) {
229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  RelocInfo::Mode mode = rmode();
230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (mode == RelocInfo::EMBEDDED_OBJECT) {
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    visitor->VisitEmbeddedPointer(this);
232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else if (RelocInfo::IsCodeTarget(mode)) {
233f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    visitor->VisitCodeTarget(this);
2341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
2351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    visitor->VisitGlobalPropertyCell(this);
236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    visitor->VisitExternalReference(this);
238f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#ifdef ENABLE_DEBUGGER_SUPPORT
23944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // TODO(isolates): Get a cached isolate below.
24044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (((RelocInfo::IsJSReturn(mode) &&
2417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch              IsPatchedReturnSequence()) ||
2427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch             (RelocInfo::IsDebugBreakSlot(mode) &&
24344f0eee88ff00398ff7f715fab053374d808c90dSteve Block              IsPatchedDebugBreakSlotSequence())) &&
24444f0eee88ff00398ff7f715fab053374d808c90dSteve Block             Isolate::Current()->debug()->has_break_points()) {
245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    visitor->VisitDebugTarget(this);
246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif
247f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else if (mode == RelocInfo::RUNTIME_ENTRY) {
248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    visitor->VisitRuntimeEntry(this);
249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
253756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merricktemplate<typename StaticVisitor>
25444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid RelocInfo::Visit(Heap* heap) {
255756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  RelocInfo::Mode mode = rmode();
256756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (mode == RelocInfo::EMBEDDED_OBJECT) {
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    StaticVisitor::VisitEmbeddedPointer(heap, this);
258756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (RelocInfo::IsCodeTarget(mode)) {
2598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    StaticVisitor::VisitCodeTarget(heap, this);
2601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
2618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    StaticVisitor::VisitGlobalPropertyCell(heap, this);
262756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    StaticVisitor::VisitExternalReference(this);
264756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#ifdef ENABLE_DEBUGGER_SUPPORT
26544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (heap->isolate()->debug()->has_break_points() &&
266756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick             ((RelocInfo::IsJSReturn(mode) &&
267756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick              IsPatchedReturnSequence()) ||
268756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick             (RelocInfo::IsDebugBreakSlot(mode) &&
269756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick              IsPatchedDebugBreakSlotSequence()))) {
2708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    StaticVisitor::VisitDebugTarget(heap, this);
271756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#endif
272756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (mode == RelocInfo::RUNTIME_ENTRY) {
273756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    StaticVisitor::VisitRuntimeEntry(this);
274756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
275756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
276756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
277756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
278f7060e27768c550ace7ec48ad8c093466db52dfaLeon ClarkeOperand::Operand(int32_t immediate, RelocInfo::Mode rmode)  {
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = no_reg;
280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  imm32_ = immediate;
281f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  rmode_ = rmode;
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand::Operand(const ExternalReference& f)  {
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = no_reg;
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  imm32_ = reinterpret_cast<int32_t>(f.address());
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rmode_ = RelocInfo::EXTERNAL_REFERENCE;
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand::Operand(Smi* value) {
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = no_reg;
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  imm32_ =  reinterpret_cast<intptr_t>(value);
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rmode_ = RelocInfo::NONE;
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand::Operand(Register rm) {
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = rm;
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rs_ = no_reg;
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_op_ = LSL;
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_imm_ = 0;
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Operand::is_reg() const {
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return rm_.is_valid() &&
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         rs_.is(no_reg) &&
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         shift_op_ == LSL &&
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         shift_imm_ == 0;
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::CheckBuffer() {
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (buffer_space() <= kGap) {
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    GrowBuffer();
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (pc_offset() >= next_buffer_check_) {
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CheckConstPool(false, true);
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::emit(Instr x) {
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckBuffer();
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  *reinterpret_cast<Instr*>(pc_) = x;
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pc_ += kInstrSize;
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAddress Assembler::target_address_address_at(Address pc) {
333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Address target_pc = pc;
334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Instr instr = Memory::int32_at(target_pc);
335e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If we have a bx instruction, the instruction before the bx is
336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // what we need to patch.
337e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  static const int32_t kBxInstMask = 0x0ffffff0;
338e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  static const int32_t kBxInstPattern = 0x012fff10;
339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if ((instr & kBxInstMask) == kBxInstPattern) {
340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    target_pc -= kInstrSize;
341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    instr = Memory::int32_at(target_pc);
342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
3436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef USE_BLX
3456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If we have a blx instruction, the instruction before it is
3466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // what needs to be patched.
3476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if ((instr & kBlxRegMask) == kBlxRegPattern) {
3486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    target_pc -= kInstrSize;
3496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    instr = Memory::int32_at(target_pc);
3506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
3526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(IsLdrPcImmediateOffset(instr));
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int offset = instr & 0xfff;  // offset_12 is unsigned
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((instr & (1 << 23)) == 0) offset = -offset;  // U bit defines offset sign
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Verify that the constant pool comes after the instruction referencing it.
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(offset >= -4);
358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return target_pc + offset + 8;
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAddress Assembler::target_address_at(Address pc) {
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Memory::Address_at(target_address_address_at(pc));
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Assembler::deserialization_set_special_target_at(
3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Address constant_pool_entry, Address target) {
3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Memory::Address_at(constant_pool_entry) = target;
3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Assembler::set_external_target_at(Address constant_pool_entry,
3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Address target) {
375d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Memory::Address_at(constant_pool_entry) = target;
376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
378d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::set_target_address_at(Address pc, Address target) {
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Memory::Address_at(target_address_address_at(pc)) = target;
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Intuitively, we would think it is necessary to flush the instruction cache
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // after patching a target address in the code as follows:
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   CPU::FlushICache(pc, sizeof(target));
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // However, on ARM, no instruction was actually patched by the assignment
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // above; the target address is not part of an instruction, it is patched in
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the constant pool and is read via a data access; the instruction accessing
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // this address in the constant pool remains unchanged.
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_ARM_ASSEMBLER_ARM_INL_H_
393