assembler-arm.cc revision d0582a6c46733687d045e4188a1bcd0123c758a1
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.
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2008 the V8 project authors. All rights reserved.
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "arm/assembler-arm-inl.h"
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "serialize.h"
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
45d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Safe default is no features.
46d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockunsigned CpuFeatures::supported_ = 0;
47d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockunsigned CpuFeatures::enabled_ = 0;
48d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockunsigned CpuFeatures::found_by_runtime_probing_ = 0;
49d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
50d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid CpuFeatures::Probe() {
51d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the compiler is allowed to use vfp then we can use vfp too in our
52d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // code generation.
53d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#if !defined(__arm__)
54d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // For the simulator=arm build, always use VFP since the arm simulator has
55d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // VFP support.
56d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  supported_ |= 1u << VFP3;
57d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#else
58d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (Serializer::enabled()) {
59d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    supported_ |= OS::CpuFeaturesImpliedByPlatform();
60d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return;  // No features if we might serialize.
61d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
62d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
63d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (OS::ArmCpuHasFeature(VFP3)) {
64d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // This implementation also sets the VFP flags if
65d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // runtime detection of VFP returns true.
66d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    supported_ |= 1u << VFP3;
67d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    found_by_runtime_probing_ |= 1u << VFP3;
68d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
69d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif
70d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
71d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
72d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of Register and CRegister
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister no_reg = { -1 };
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r0  = {  0 };
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r1  = {  1 };
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r2  = {  2 };
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r3  = {  3 };
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r4  = {  4 };
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r5  = {  5 };
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r6  = {  6 };
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r7  = {  7 };
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r8  = {  8 };
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r9  = {  9 };
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r10 = { 10 };
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister fp  = { 11 };
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister ip  = { 12 };
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister sp  = { 13 };
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister lr  = { 14 };
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister pc  = { 15 };
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister no_creg = { -1 };
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr0  = {  0 };
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr1  = {  1 };
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr2  = {  2 };
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr3  = {  3 };
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr4  = {  4 };
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr5  = {  5 };
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr6  = {  6 };
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr7  = {  7 };
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr8  = {  8 };
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr9  = {  9 };
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr10 = { 10 };
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr11 = { 11 };
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr12 = { 12 };
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr13 = { 13 };
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr14 = { 14 };
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr15 = { 15 };
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
115d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Support for the VFP registers s0 to s31 (d0 to d15).
116d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Note that "sN:sM" is the same as "dN/2".
117d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s0  = {  0 };
118d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s1  = {  1 };
119d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s2  = {  2 };
120d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s3  = {  3 };
121d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s4  = {  4 };
122d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s5  = {  5 };
123d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s6  = {  6 };
124d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s7  = {  7 };
125d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s8  = {  8 };
126d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s9  = {  9 };
127d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s10 = { 10 };
128d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s11 = { 11 };
129d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s12 = { 12 };
130d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s13 = { 13 };
131d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s14 = { 14 };
132d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s15 = { 15 };
133d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s16 = { 16 };
134d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s17 = { 17 };
135d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s18 = { 18 };
136d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s19 = { 19 };
137d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s20 = { 20 };
138d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s21 = { 21 };
139d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s22 = { 22 };
140d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s23 = { 23 };
141d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s24 = { 24 };
142d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s25 = { 25 };
143d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s26 = { 26 };
144d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s27 = { 27 };
145d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s28 = { 28 };
146d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s29 = { 29 };
147d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s30 = { 30 };
148d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s31 = { 31 };
149d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
150d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d0  = {  0 };
151d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d1  = {  1 };
152d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d2  = {  2 };
153d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d3  = {  3 };
154d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d4  = {  4 };
155d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d5  = {  5 };
156d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d6  = {  6 };
157d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d7  = {  7 };
158d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d8  = {  8 };
159d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d9  = {  9 };
160d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d10 = { 10 };
161d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d11 = { 11 };
162d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d12 = { 12 };
163d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d13 = { 13 };
164d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d14 = { 14 };
165d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d15 = { 15 };
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of RelocInfo
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int RelocInfo::kApplyMask = 0;
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RelocInfo::PatchCode(byte* instructions, int instruction_count) {
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the code at the current address with the supplied instructions.
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Instr* pc = reinterpret_cast<Instr*>(pc_);
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Instr* instr = reinterpret_cast<Instr*>(instructions);
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < instruction_count; i++) {
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *(pc + i) = *(instr + i);
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indicate that code has changed.
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CPU::FlushICache(pc_, instruction_count * Assembler::kInstrSize);
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Patch the code at the current PC with a call to the target address.
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Additional guard instructions can be added if required.
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the code at the current address with a call to the target.
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNIMPLEMENTED();
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of Operand and MemOperand
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// See assembler-arm-inl.h for inlined constructors
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand::Operand(Handle<Object> handle) {
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = no_reg;
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Verify all Objects referred by code are NOT in new space.
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object* obj = *handle;
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!Heap::InNewSpace(obj));
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (obj->IsHeapObject()) {
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    imm32_ = reinterpret_cast<intptr_t>(handle.location());
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    rmode_ = RelocInfo::EMBEDDED_OBJECT;
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // no relocation needed
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    imm32_ =  reinterpret_cast<intptr_t>(obj);
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    rmode_ = RelocInfo::NONE;
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand::Operand(Register rm, ShiftOp shift_op, int shift_imm) {
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint5(shift_imm));
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(shift_op != ROR || shift_imm != 0);  // use RRX if you mean it
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = rm;
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rs_ = no_reg;
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_op_ = shift_op;
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_imm_ = shift_imm & 31;
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (shift_op == RRX) {
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // encoded as ROR with shift_imm == 0
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(shift_imm == 0);
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift_op_ = ROR;
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift_imm_ = 0;
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand::Operand(Register rm, ShiftOp shift_op, Register rs) {
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(shift_op != RRX);
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = rm;
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rs_ = no_reg;
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_op_ = shift_op;
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rs_ = rs;
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMemOperand::MemOperand(Register rn, int32_t offset, AddrMode am) {
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rn_ = rn;
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = no_reg;
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  offset_ = offset;
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  am_ = am;
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMemOperand::MemOperand(Register rn, Register rm, AddrMode am) {
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rn_ = rn;
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = rm;
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_op_ = LSL;
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_imm_ = 0;
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  am_ = am;
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMemOperand::MemOperand(Register rn, Register rm,
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       ShiftOp shift_op, int shift_imm, AddrMode am) {
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint5(shift_imm));
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rn_ = rn;
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = rm;
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_op_ = shift_op;
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_imm_ = shift_imm & 31;
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  am_ = am;
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of Assembler
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Instruction encoding bits
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum {
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  H   = 1 << 5,   // halfword (or byte)
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  S6  = 1 << 6,   // signed (or unsigned)
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  L   = 1 << 20,  // load (or store)
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  S   = 1 << 20,  // set condition code (or leave unchanged)
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  W   = 1 << 21,  // writeback base register (or leave unchanged)
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  A   = 1 << 21,  // accumulate in multiply instruction (or not)
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  B   = 1 << 22,  // unsigned byte (or word)
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  N   = 1 << 22,  // long (or short)
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  U   = 1 << 23,  // positive (or negative) offset/index
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  P   = 1 << 24,  // offset/pre-indexed addressing (or post-indexed addressing)
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  I   = 1 << 25,  // immediate shifter operand (or not)
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  B4  = 1 << 4,
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  B5  = 1 << 5,
285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  B6  = 1 << 6,
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  B7  = 1 << 7,
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  B8  = 1 << 8,
288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  B9  = 1 << 9,
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  B12 = 1 << 12,
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  B16 = 1 << 16,
291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  B18 = 1 << 18,
292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  B19 = 1 << 19,
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  B20 = 1 << 20,
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  B21 = 1 << 21,
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  B22 = 1 << 22,
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  B23 = 1 << 23,
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  B24 = 1 << 24,
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  B25 = 1 << 25,
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  B26 = 1 << 26,
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  B27 = 1 << 27,
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Instruction bit masks
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RdMask     = 15 << 12,  // in str instruction
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CondMask   = 15 << 28,
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CoprocessorMask = 15 << 8,
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OpCodeMask = 15 << 21,  // in data-processing instructions
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Imm24Mask  = (1 << 24) - 1,
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Off12Mask  = (1 << 12) - 1,
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reserved condition
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  nv = 15 << 28
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// add(sp, sp, 4) instruction (aka Pop())
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const Instr kPopInstruction =
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    al | 4 * B21 | 4 | LeaveCC | I | sp.code() * B16 | sp.code() * B12;
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r))
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register r is not encoded.
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const Instr kPushRegPattern =
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    al | B26 | 4 | NegPreIndex | sp.code() * B16;
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r))
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register r is not encoded.
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const Instr kPopRegPattern =
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    al | B26 | L | 4 | PostIndex | sp.code() * B16;
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// mov lr, pc
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst Instr kMovLrPc = al | 13*B21 | pc.code() | lr.code() * B12;
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ldr pc, [pc, #XXX]
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst Instr kLdrPCPattern = al | B26 | L | pc.code() * B16;
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// spare_buffer_
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kMinimalBufferSize = 4*KB;
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic byte* spare_buffer_ = NULL;
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAssembler::Assembler(void* buffer, int buffer_size) {
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (buffer == NULL) {
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // do our own buffer management
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (buffer_size <= kMinimalBufferSize) {
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      buffer_size = kMinimalBufferSize;
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (spare_buffer_ != NULL) {
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        buffer = spare_buffer_;
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        spare_buffer_ = NULL;
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (buffer == NULL) {
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      buffer_ = NewArray<byte>(buffer_size);
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      buffer_ = static_cast<byte*>(buffer);
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buffer_size_ = buffer_size;
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    own_buffer_ = true;
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // use externally provided buffer instead
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(buffer_size > 0);
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buffer_ = static_cast<byte*>(buffer);
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buffer_size_ = buffer_size;
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    own_buffer_ = false;
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // setup buffer pointers
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(buffer_ != NULL);
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pc_ = buffer_;
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  num_prinfo_ = 0;
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_buffer_check_ = 0;
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  no_const_pool_before_ = 0;
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  last_const_pool_end_ = 0;
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  last_bound_pos_ = 0;
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current_statement_position_ = RelocInfo::kNoPosition;
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current_position_ = RelocInfo::kNoPosition;
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  written_statement_position_ = current_statement_position_;
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  written_position_ = current_position_;
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAssembler::~Assembler() {
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (own_buffer_) {
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      spare_buffer_ = buffer_;
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      DeleteArray(buffer_);
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::GetCode(CodeDesc* desc) {
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // emit constant pool if necessary
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckConstPool(true, false);
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(num_prinfo_ == 0);
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // setup desc
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc->buffer = buffer_;
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc->buffer_size = buffer_size_;
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc->instr_size = pc_offset();
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::Align(int m) {
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(m >= 4 && IsPowerOf2(m));
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while ((pc_offset() & (m - 1)) != 0) {
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    nop();
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Labels refer to positions in the (to be) generated code.
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// There are bound, linked, and unused labels.
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Bound labels refer to known positions in the already
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// generated code. pos() is the position the label refers to.
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Linked labels refer to unknown positions in the code
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to be generated; pos() is the position of the last
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// instruction using the label.
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The link chain is terminated by a negative code position (must be aligned)
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int kEndOfChain = -4;
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Assembler::target_at(int pos)  {
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Instr instr = instr_at(pos);
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((instr & ~Imm24Mask) == 0) {
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Emitted label constant, not part of a branch.
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return instr - (Code::kHeaderSize - kHeapObjectTag);
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((instr & 7*B25) == 5*B25);  // b, bl, or blx imm24
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm26 = ((instr & Imm24Mask) << 8) >> 6;
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((instr & CondMask) == nv && (instr & B24) != 0)
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // blx uses bit 24 to encode bit 2 of imm26
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    imm26 += 2;
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return pos + kPcLoadDelta + imm26;
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::target_at_put(int pos, int target_pos) {
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Instr instr = instr_at(pos);
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((instr & ~Imm24Mask) == 0) {
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(target_pos == kEndOfChain || target_pos >= 0);
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Emitted label constant, not part of a branch.
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Make label relative to Code* of generated Code object.
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm26 = target_pos - (pos + kPcLoadDelta);
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((instr & 7*B25) == 5*B25);  // b, bl, or blx imm24
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((instr & CondMask) == nv) {
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // blx uses bit 24 to encode bit 2 of imm26
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT((imm26 & 1) == 0);
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr = (instr & ~(B24 | Imm24Mask)) | ((imm26 & 2) >> 1)*B24;
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT((imm26 & 3) == 0);
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr &= ~Imm24Mask;
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm24 = imm26 >> 2;
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_int24(imm24));
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  instr_at_put(pos, instr | (imm24 & Imm24Mask));
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::print(Label* L) {
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (L->is_unused()) {
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("unused label\n");
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (L->is_bound()) {
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("bound label to %d\n", L->pos());
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (L->is_linked()) {
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label l = *L;
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("unbound label");
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while (l.is_linked()) {
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PrintF("@ %d ", l.pos());
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Instr instr = instr_at(l.pos());
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if ((instr & ~Imm24Mask) == 0) {
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        PrintF("value\n");
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ASSERT((instr & 7*B25) == 5*B25);  // b, bl, or blx
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int cond = instr & CondMask;
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        const char* b;
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        const char* c;
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (cond == nv) {
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          b = "blx";
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          c = "";
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if ((instr & B24) != 0)
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            b = "bl";
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          else
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            b = "b";
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          switch (cond) {
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case eq: c = "eq"; break;
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case ne: c = "ne"; break;
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case hs: c = "hs"; break;
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case lo: c = "lo"; break;
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case mi: c = "mi"; break;
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case pl: c = "pl"; break;
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case vs: c = "vs"; break;
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case vc: c = "vc"; break;
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case hi: c = "hi"; break;
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case ls: c = "ls"; break;
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case ge: c = "ge"; break;
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case lt: c = "lt"; break;
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case gt: c = "gt"; break;
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case le: c = "le"; break;
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case al: c = ""; break;
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            default:
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              c = "";
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              UNREACHABLE();
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        PrintF("%s%s\n", b, c);
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      next(&l);
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bind_to(Label* L, int pos) {
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(0 <= pos && pos <= pc_offset());  // must have a valid binding position
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (L->is_linked()) {
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int fixup_pos = L->pos();
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    next(L);  // call next before overwriting link with target at fixup_pos
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    target_at_put(fixup_pos, pos);
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  L->bind_to(pos);
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Keep track of the last bound label so we don't eliminate any instructions
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // before a bound label.
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (pos > last_bound_pos_)
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    last_bound_pos_ = pos;
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::link_to(Label* L, Label* appendix) {
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (appendix->is_linked()) {
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (L->is_linked()) {
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // append appendix to L's list
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int fixup_pos;
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int link = L->pos();
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      do {
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        fixup_pos = link;
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        link = target_at(fixup_pos);
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } while (link > 0);
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(link == kEndOfChain);
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      target_at_put(fixup_pos, appendix->pos());
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // L is empty, simply use appendix
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *L = *appendix;
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  appendix->Unuse();  // appendix should not be used anymore
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bind(Label* L) {
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!L->is_bound());  // label can only be bound once
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind_to(L, pc_offset());
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::next(Label* L) {
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(L->is_linked());
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int link = target_at(L->pos());
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (link > 0) {
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    L->link_to(link);
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(link == kEndOfChain);
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    L->Unuse();
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Low-level code emission routines depending on the addressing mode
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool fits_shifter(uint32_t imm32,
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         uint32_t* rotate_imm,
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         uint32_t* immed_8,
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         Instr* instr) {
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // imm32 must be unsigned
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int rot = 0; rot < 16; rot++) {
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t imm8 = (imm32 << 2*rot) | (imm32 >> (32 - 2*rot));
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if ((imm8 <= 0xff)) {
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *rotate_imm = rot;
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *immed_8 = imm8;
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return true;
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // if the opcode is mov or mvn and if ~imm32 fits, change the opcode
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (instr != NULL && (*instr & 0xd*B21) == 0xd*B21) {
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) {
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *instr ^= 0x2*B21;
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return true;
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return false;
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We have to use the temporary register for things that can be relocated even
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// if they can be encoded in the ARM's 12 bits of immediate-offset instruction
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// space.  There is no guarantee that the relocated location can be similarly
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// encoded.
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool MustUseIp(RelocInfo::Mode rmode) {
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG
610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!Serializer::enabled()) {
611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Serializer::TooLateToEnableNow();
612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return Serializer::enabled();
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (rmode == RelocInfo::NONE) {
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return false;
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod1(Instr instr,
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         Register rn,
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         Register rd,
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         const Operand& x) {
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckBuffer();
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((instr & ~(CondMask | OpCodeMask | S)) == 0);
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!x.rm_.is_valid()) {
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // immediate
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t rotate_imm;
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t immed_8;
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (MustUseIp(x.rmode_) ||
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) {
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // The immediate operand cannot be encoded as a shifter operand, so load
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // it first to register ip and change the original instruction to use ip.
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // However, if the original instruction is a 'mov rd, x' (not setting the
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // condition code), then replace it with a 'ldr rd, [pc]'
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      RecordRelocInfo(x.rmode_, x.imm32_);
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CHECK(!rn.is(ip));  // rn should never be ip, or will be trashed
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Condition cond = static_cast<Condition>(instr & CondMask);
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if ((instr & ~CondMask) == 13*B21) {  // mov, S not set
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ldr(rd, MemOperand(pc, 0), cond);
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ldr(ip, MemOperand(pc, 0), cond);
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        addrmod1(instr, rn, rd, Operand(ip));
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= I | rotate_imm*B8 | immed_8;
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (!x.rs_.is_valid()) {
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // immediate shift
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // register shift
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc));
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= x.rs_.code()*B8 | x.shift_op_ | B4 | x.rm_.code();
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(instr | rn.code()*B16 | rd.code()*B12);
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (rn.is(pc) || x.rm_.is(pc))
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // block constant pool emission for one instruction after reading pc
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    BlockConstPoolBefore(pc_offset() + kInstrSize);
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod2(Instr instr, Register rd, const MemOperand& x) {
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((instr & ~(CondMask | B | L)) == B26);
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int am = x.am_;
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!x.rm_.is_valid()) {
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // immediate offset
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset_12 = x.offset_;
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (offset_12 < 0) {
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      offset_12 = -offset_12;
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      am ^= U;
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!is_uint12(offset_12)) {
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // immediate offset cannot be encoded, load it first to register ip
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // rn (and rd in a load) should never be ip, or will be trashed
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mov(ip, Operand(x.offset_), LeaveCC,
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          static_cast<Condition>(instr & CondMask));
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      addrmod2(instr, rd, MemOperand(x.rn_, ip, x.am_));
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(offset_12 >= 0);  // no masking needed
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= offset_12;
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // register offset (shift_imm_ and shift_op_ are 0) or scaled
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // register offset the constructors make sure than both shift_imm_
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // and shift_op_ are initialized
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!x.rm_.is(pc));
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= B25 | x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod3(Instr instr, Register rd, const MemOperand& x) {
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((instr & ~(CondMask | L | S6 | H)) == (B4 | B7));
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(x.rn_.is_valid());
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int am = x.am_;
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!x.rm_.is_valid()) {
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // immediate offset
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset_8 = x.offset_;
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (offset_8 < 0) {
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      offset_8 = -offset_8;
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      am ^= U;
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!is_uint8(offset_8)) {
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // immediate offset cannot be encoded, load it first to register ip
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // rn (and rd in a load) should never be ip, or will be trashed
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mov(ip, Operand(x.offset_), LeaveCC,
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          static_cast<Condition>(instr & CondMask));
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(offset_8 >= 0);  // no masking needed
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= B | (offset_8 >> 4)*B8 | (offset_8 & 0xf);
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (x.shift_imm_ != 0) {
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // scaled register offset not supported, load index first
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // rn (and rd in a load) should never be ip, or will be trashed
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(ip, Operand(x.rm_, x.shift_op_, x.shift_imm_), LeaveCC,
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        static_cast<Condition>(instr & CondMask));
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // register offset
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT((am & (P|W)) == P || !x.rm_.is(pc));  // no pc index with writeback
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= x.rm_.code();
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod4(Instr instr, Register rn, RegList rl) {
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((instr & ~(CondMask | P | U | W | L)) == B27);
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(rl != 0);
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!rn.is(pc));
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(instr | rn.code()*B16 | rl);
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod5(Instr instr, CRegister crd, const MemOperand& x) {
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // unindexed addressing is not encoded by this function
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ((B27 | B26),
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            (instr & ~(CondMask | CoprocessorMask | P | U | N | W | L)));
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(x.rn_.is_valid() && !x.rm_.is_valid());
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int am = x.am_;
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int offset_8 = x.offset_;
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((offset_8 & 3) == 0);  // offset must be an aligned word offset
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  offset_8 >>= 2;
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (offset_8 < 0) {
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    offset_8 = -offset_8;
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    am ^= U;
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint8(offset_8));  // unsigned word offset must fit in a byte
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // post-indexed addressing requires W == 1; different than in addrmod2/3
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((am & P) == 0)
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    am |= W;
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(offset_8 >= 0);  // no masking needed
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8);
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int target_pos;
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (L->is_bound()) {
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    target_pos = L->pos();
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (L->is_linked()) {
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      target_pos = L->pos();  // L's link
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      target_pos = kEndOfChain;
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    L->link_to(pc_offset());
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Block the emission of the constant pool, since the branch instruction must
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // be emitted at the pc offset recorded by the label
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BlockConstPoolBefore(pc_offset() + kInstrSize);
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return target_pos - (pc_offset() + kPcLoadDelta);
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::label_at_put(Label* L, int at_offset) {
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int target_pos;
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (L->is_bound()) {
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    target_pos = L->pos();
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (L->is_linked()) {
797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      target_pos = L->pos();  // L's link
798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      target_pos = kEndOfChain;
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    L->link_to(at_offset);
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Branch instructions
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::b(int branch_offset, Condition cond) {
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((branch_offset & 3) == 0);
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm24 = branch_offset >> 2;
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_int24(imm24));
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B27 | B25 | (imm24 & Imm24Mask));
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (cond == al)
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // dead code is a good location to emit the constant pool
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CheckConstPool(false, false);
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bl(int branch_offset, Condition cond) {
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((branch_offset & 3) == 0);
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm24 = branch_offset >> 2;
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_int24(imm24));
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B27 | B25 | B24 | (imm24 & Imm24Mask));
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::blx(int branch_offset) {  // v5 and above
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  WriteRecordedPositions();
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((branch_offset & 1) == 0);
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int h = ((branch_offset & 2) >> 1)*B24;
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm24 = branch_offset >> 2;
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_int24(imm24));
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(15 << 28 | B27 | B25 | h | (imm24 & Imm24Mask));
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::blx(Register target, Condition cond) {  // v5 and above
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  WriteRecordedPositions();
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!target.is(pc));
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | 3*B4 | target.code());
842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bx(Register target, Condition cond) {  // v5 and above, plus v4t
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  WriteRecordedPositions();
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!target.is(pc));  // use of pc is actually allowed, but discouraged
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | B4 | target.code());
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Data-processing instructions
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::and_(Register dst, Register src1, const Operand& src2,
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     SBit s, Condition cond) {
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod1(cond | 0*B21 | s, src1, dst, src2);
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::eor(Register dst, Register src1, const Operand& src2,
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod1(cond | 1*B21 | s, src1, dst, src2);
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::sub(Register dst, Register src1, const Operand& src2,
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod1(cond | 2*B21 | s, src1, dst, src2);
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::rsb(Register dst, Register src1, const Operand& src2,
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod1(cond | 3*B21 | s, src1, dst, src2);
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::add(Register dst, Register src1, const Operand& src2,
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod1(cond | 4*B21 | s, src1, dst, src2);
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Eliminate pattern: push(r), pop()
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   str(src, MemOperand(sp, 4, NegPreIndex), al);
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   add(sp, sp, Operand(kPointerSize));
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Both instructions can be eliminated.
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int pattern_size = 2 * kInstrSize;
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_push_pop_elimination &&
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      last_bound_pos_ <= (pc_offset() - pattern_size) &&
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      reloc_info_writer.last_pc() <= (pc_ - pattern_size) &&
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // pattern
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      instr_at(pc_ - 1 * kInstrSize) == kPopInstruction &&
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      (instr_at(pc_ - 2 * kInstrSize) & ~RdMask) == kPushRegPattern) {
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pc_ -= 2 * kInstrSize;
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (FLAG_print_push_pop_elimination) {
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PrintF("%x push(reg)/pop() eliminated\n", pc_offset());
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::adc(Register dst, Register src1, const Operand& src2,
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod1(cond | 5*B21 | s, src1, dst, src2);
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::sbc(Register dst, Register src1, const Operand& src2,
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod1(cond | 6*B21 | s, src1, dst, src2);
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::rsc(Register dst, Register src1, const Operand& src2,
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod1(cond | 7*B21 | s, src1, dst, src2);
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::tst(Register src1, const Operand& src2, Condition cond) {
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod1(cond | 8*B21 | S, src1, r0, src2);
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::teq(Register src1, const Operand& src2, Condition cond) {
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod1(cond | 9*B21 | S, src1, r0, src2);
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::cmp(Register src1, const Operand& src2, Condition cond) {
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod1(cond | 10*B21 | S, src1, r0, src2);
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::cmn(Register src1, const Operand& src2, Condition cond) {
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod1(cond | 11*B21 | S, src1, r0, src2);
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::orr(Register dst, Register src1, const Operand& src2,
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod1(cond | 12*B21 | s, src1, dst, src2);
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) {
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (dst.is(pc)) {
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    WriteRecordedPositions();
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod1(cond | 13*B21 | s, r0, dst, src);
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bic(Register dst, Register src1, const Operand& src2,
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod1(cond | 14*B21 | s, src1, dst, src2);
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) {
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod1(cond | 15*B21 | s, r0, dst, src);
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Multiply instructions
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mla(Register dst, Register src1, Register src2, Register srcA,
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | A | s | dst.code()*B16 | srcA.code()*B12 |
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       src2.code()*B8 | B7 | B4 | src1.code());
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mul(Register dst, Register src1, Register src2,
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // dst goes in bits 16-19 for this instruction!
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | s | dst.code()*B16 | src2.code()*B8 | B7 | B4 | src1.code());
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::smlal(Register dstL,
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register dstH,
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src1,
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src2,
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      SBit s,
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Condition cond) {
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(dstH));
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B23 | B22 | A | s | dstH.code()*B16 | dstL.code()*B12 |
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       src2.code()*B8 | B7 | B4 | src1.code());
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::smull(Register dstL,
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register dstH,
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src1,
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src2,
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      SBit s,
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Condition cond) {
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(dstH));
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 |
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       src2.code()*B8 | B7 | B4 | src1.code());
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::umlal(Register dstL,
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register dstH,
1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src1,
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src2,
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      SBit s,
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Condition cond) {
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(dstH));
1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B23 | A | s | dstH.code()*B16 | dstL.code()*B12 |
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       src2.code()*B8 | B7 | B4 | src1.code());
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::umull(Register dstL,
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register dstH,
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src1,
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src2,
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      SBit s,
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Condition cond) {
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(dstH));
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B23 | s | dstH.code()*B16 | dstL.code()*B12 |
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       src2.code()*B8 | B7 | B4 | src1.code());
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Miscellaneous arithmetic instructions
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::clz(Register dst, Register src, Condition cond) {
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // v5 and above.
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(pc) && !src.is(pc));
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B24 | B22 | B21 | 15*B16 | dst.code()*B12 |
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       15*B8 | B4 | src.code());
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Status register access instructions
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mrs(Register dst, SRegister s, Condition cond) {
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(pc));
1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B24 | s | 15*B16 | dst.code()*B12);
1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::msr(SRegisterFieldMask fields, const Operand& src,
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(fields >= B16 && fields < B20);  // at least one field set
1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Instr instr;
1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!src.rm_.is_valid()) {
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // immediate
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t rotate_imm;
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t immed_8;
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (MustUseIp(src.rmode_) ||
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) {
1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // immediate operand cannot be encoded, load it first to register ip
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      RecordRelocInfo(src.rmode_, src.imm32_);
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ldr(ip, MemOperand(pc, 0), cond);
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      msr(fields, Operand(ip), cond);
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr = I | rotate_imm*B8 | immed_8;
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!src.rs_.is_valid() && src.shift_imm_ == 0);  // only rm allowed
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr = src.rm_.code();
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | instr | B24 | B21 | fields | 15*B12);
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load/Store instructions
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (dst.is(pc)) {
1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    WriteRecordedPositions();
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod2(cond | B26 | L, dst, src);
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Eliminate pattern: push(r), pop(r)
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   str(r, MemOperand(sp, 4, NegPreIndex), al)
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   ldr(r, MemOperand(sp, 4, PostIndex), al)
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Both instructions can be eliminated.
1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int pattern_size = 2 * kInstrSize;
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_push_pop_elimination &&
1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      last_bound_pos_ <= (pc_offset() - pattern_size) &&
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      reloc_info_writer.last_pc() <= (pc_ - pattern_size) &&
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // pattern
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      instr_at(pc_ - 1 * kInstrSize) == (kPopRegPattern | dst.code() * B12) &&
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      instr_at(pc_ - 2 * kInstrSize) == (kPushRegPattern | dst.code() * B12)) {
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pc_ -= 2 * kInstrSize;
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (FLAG_print_push_pop_elimination) {
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PrintF("%x push/pop (same reg) eliminated\n", pc_offset());
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::str(Register src, const MemOperand& dst, Condition cond) {
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod2(cond | B26, src, dst);
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Eliminate pattern: pop(), push(r)
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //     add sp, sp, #4 LeaveCC, al; str r, [sp, #-4], al
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ->  str r, [sp, 0], al
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int pattern_size = 2 * kInstrSize;
1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_push_pop_elimination &&
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     last_bound_pos_ <= (pc_offset() - pattern_size) &&
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     reloc_info_writer.last_pc() <= (pc_ - pattern_size) &&
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     instr_at(pc_ - 1 * kInstrSize) == (kPushRegPattern | src.code() * B12) &&
1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     instr_at(pc_ - 2 * kInstrSize) == kPopInstruction) {
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pc_ -= 2 * kInstrSize;
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    emit(al | B26 | 0 | Offset | sp.code() * B16 | src.code() * B12);
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (FLAG_print_push_pop_elimination) {
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PrintF("%x pop()/push(reg) eliminated\n", pc_offset());
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) {
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod2(cond | B26 | B | L, dst, src);
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::strb(Register src, const MemOperand& dst, Condition cond) {
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod2(cond | B26 | B, src, dst);
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) {
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod3(cond | L | B7 | H | B4, dst, src);
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::strh(Register src, const MemOperand& dst, Condition cond) {
1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod3(cond | B7 | H | B4, src, dst);
1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) {
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod3(cond | L | B7 | S6 | B4, dst, src);
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) {
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod3(cond | L | B7 | S6 | H | B4, dst, src);
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load/Store multiple instructions
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldm(BlockAddrMode am,
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register base,
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    RegList dst,
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ABI stack constraint: ldmxx base, {..sp..}  base != sp  is not restartable
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(base.is(sp) || (dst & sp.bit()) == 0);
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod4(cond | B27 | am | L, base, dst);
1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // emit the constant pool after a function return implemented by ldm ..{..pc}
1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (cond == al && (dst & pc.bit()) != 0) {
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // There is a slight chance that the ldm instruction was actually a call,
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // in which case it would be wrong to return into the constant pool; we
1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // recognize this case by checking if the emission of the pool was blocked
1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // at the pc of the ldm instruction by a mov lr, pc instruction; if this is
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // the case, we emit a jump over the pool.
1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CheckConstPool(true, no_const_pool_before_ == pc_offset() - kInstrSize);
1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::stm(BlockAddrMode am,
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register base,
1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    RegList src,
1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod4(cond | B27 | am, base, src);
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Semaphore instructions
1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::swp(Register dst, Register src, Register base, Condition cond) {
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(pc) && !src.is(pc) && !base.is(pc));
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(base) && !src.is(base));
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | P | base.code()*B16 | dst.code()*B12 |
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       B7 | B4 | src.code());
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::swpb(Register dst,
1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     Register src,
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     Register base,
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     Condition cond) {
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(pc) && !src.is(pc) && !base.is(pc));
1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(base) && !src.is(base));
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | P | B | base.code()*B16 | dst.code()*B12 |
1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       B7 | B4 | src.code());
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Exception-generating instructions and debugging support
1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::stop(const char* msg) {
1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if !defined(__arm__)
1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The simulator handles these special instructions and stops execution.
1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(15 << 28 | ((intptr_t) msg));
1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else
1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Just issue a simple break instruction for now. Alternatively we could use
1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the swi(0x9f0001) instruction on Linux.
1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bkpt(0);
1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bkpt(uint32_t imm16) {  // v5 and above
1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint16(imm16));
1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(al | B24 | B21 | (imm16 >> 4)*B8 | 7*B4 | (imm16 & 0xf));
1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::swi(uint32_t imm24, Condition cond) {
1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint24(imm24));
1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | 15*B24 | imm24);
1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Coprocessor instructions
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::cdp(Coprocessor coproc,
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_1,
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crd,
1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crn,
1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crm,
1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_2,
1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint4(opcode_1) && is_uint3(opcode_2));
1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B27 | B26 | B25 | (opcode_1 & 15)*B20 | crn.code()*B16 |
1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       crd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | crm.code());
1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::cdp2(Coprocessor coproc,
1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int opcode_1,
1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crd,
1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crn,
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crm,
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int opcode_2) {  // v5 and above
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cdp(coproc, opcode_1, crd, crn, crm, opcode_2, static_cast<Condition>(nv));
1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mcr(Coprocessor coproc,
1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_1,
1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register rd,
1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crn,
1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crm,
1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_2,
1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2));
1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | crn.code()*B16 |
1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mcr2(Coprocessor coproc,
1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int opcode_1,
1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     Register rd,
1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crn,
1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crm,
1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int opcode_2) {  // v5 and above
1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mcr(coproc, opcode_1, rd, crn, crm, opcode_2, static_cast<Condition>(nv));
1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mrc(Coprocessor coproc,
1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_1,
1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register rd,
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crn,
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crm,
1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_2,
1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2));
1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | L | crn.code()*B16 |
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mrc2(Coprocessor coproc,
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int opcode_1,
1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     Register rd,
1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crn,
1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crm,
1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int opcode_2) {  // v5 and above
1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mrc(coproc, opcode_1, rd, crn, crm, opcode_2, static_cast<Condition>(nv));
1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldc(Coprocessor coproc,
1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crd,
1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    const MemOperand& src,
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    LFlag l,
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod5(cond | B27 | B26 | l | L | coproc*B8, crd, src);
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldc(Coprocessor coproc,
1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crd,
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register rn,
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int option,
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    LFlag l,
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // unindexed addressing
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint8(option));
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B27 | B26 | U | l | L | rn.code()*B16 | crd.code()*B12 |
1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       coproc*B8 | (option & 255));
1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldc2(Coprocessor coproc,
1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crd,
1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     const MemOperand& src,
1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     LFlag l) {  // v5 and above
1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ldc(coproc, crd, src, l, static_cast<Condition>(nv));
1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldc2(Coprocessor coproc,
1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crd,
1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     Register rn,
1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int option,
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     LFlag l) {  // v5 and above
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ldc(coproc, crd, rn, option, l, static_cast<Condition>(nv));
1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::stc(Coprocessor coproc,
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crd,
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    const MemOperand& dst,
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    LFlag l,
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod5(cond | B27 | B26 | l | coproc*B8, crd, dst);
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::stc(Coprocessor coproc,
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crd,
1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register rn,
1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int option,
1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    LFlag l,
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // unindexed addressing
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint8(option));
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B27 | B26 | U | l | rn.code()*B16 | crd.code()*B12 |
1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       coproc*B8 | (option & 255));
1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::stc2(Coprocessor
1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     coproc, CRegister crd,
1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     const MemOperand& dst,
1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     LFlag l) {  // v5 and above
1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stc(coproc, crd, dst, l, static_cast<Condition>(nv));
1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::stc2(Coprocessor coproc,
1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crd,
1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     Register rn,
1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int option,
1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     LFlag l) {  // v5 and above
1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stc(coproc, crd, rn, option, l, static_cast<Condition>(nv));
1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Support for VFP.
1374d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::fmdrr(const Register dst,
1375d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const Register src1,
1376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const Register src2,
1377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const SBit s,
1378d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const Condition cond) {
1379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dm = <Rt,Rt2>.
1380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-646.
1381d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) |
1382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
1383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(CpuFeatures::IsEnabled(VFP3));
1384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(!src1.is(pc) && !src2.is(pc));
1385d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xC*B24 | B22 | src2.code()*B16 |
1386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       src1.code()*B12 | 0xB*B8 | B4 | dst.code());
1387d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1389d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::fmrrd(const Register dst1,
1391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const Register dst2,
1392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const Register src,
1393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const SBit s,
1394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const Condition cond) {
1395d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // <Rt,Rt2> = Dm.
1396d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-646.
1397d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) |
1398d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
1399d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(CpuFeatures::IsEnabled(VFP3));
1400d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(!dst1.is(pc) && !dst2.is(pc));
1401d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 |
1402d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       dst1.code()*B12 | 0xB*B8 | B4 | src.code());
1403d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1404d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1405d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1406d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::fmsr(const Register dst,
1407d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const Register src,
1408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const SBit s,
1409d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const Condition cond) {
1410d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Sn = Rt.
1411d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-642.
1412d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) |
1413d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
1414d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(CpuFeatures::IsEnabled(VFP3));
1415d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(!src.is(pc));
1416d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 | (dst.code() >> 1)*B16 |
1417d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       src.code()*B12 | 0xA*B8 | (0x1 & dst.code())*B7 | B4);
1418d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1420d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::fmrs(const Register dst,
1422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const Register src,
1423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const SBit s,
1424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const Condition cond) {
1425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt = Sn.
1426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-642.
1427d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) |
1428d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
1429d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(CpuFeatures::IsEnabled(VFP3));
1430d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(!dst.is(pc));
1431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 | B20 | (src.code() >> 1)*B16 |
1432d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       dst.code()*B12 | 0xA*B8 | (0x1 & src.code())*B7 | B4);
1433d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1434d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1435d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1436d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::fsitod(const Register dst,
1437d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                       const Register src,
1438d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                       const SBit s,
1439d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                       const Condition cond) {
1440d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = Sm (integer in Sm converted to IEEE 64-bit doubles in Dd).
1441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-576.
1442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 11101(27-23)| D=?(22) | 11(21-20) | 1(19) |opc2=000(18-16) |
1443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Vd(15-12) | 101(11-9) | sz(8)=1 | op(7)=1 | 1(6) | M=?(5) | 0(4) | Vm(3-0)
1444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(CpuFeatures::IsEnabled(VFP3));
1445d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 | B23 | 0x3*B20 | B19 |
1446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       dst.code()*B12 | 0x5*B9 | B8 | B7 | B6 |
1447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       (0x1 & src.code())*B5 | (src.code() >> 1));
1448d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1449d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1450d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::ftosid(const Register dst,
1452d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                       const Register src,
1453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                       const SBit s,
1454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                       const Condition cond) {
1455d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Sd = Dm (IEEE 64-bit doubles in Dm converted to 32 bit integer in Sd).
1456d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-576.
1457d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 11101(27-23)| D=?(22) | 11(21-20) | 1(19) | opc2=101(18-16)|
1458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Vd(15-12) | 101(11-9) | sz(8)=1 | op(7)=? | 1(6) | M=?(5) | 0(4) | Vm(3-0)
1459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(CpuFeatures::IsEnabled(VFP3));
1460d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 | B23 |(0x1 & dst.code())*B22 |
1461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       0x3*B20 | B19 | 0x5*B16 | (dst.code() >> 1)*B12 |
1462d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       0x5*B9 | B8 | B7 | B6 | src.code());
1463d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1464d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1465d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1466d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::faddd(const Register dst,
1467d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const  Register src1,
1468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const  Register src2,
1469d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const  SBit s,
1470d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const  Condition cond) {
1471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = faddd(Dn, Dm) double precision floating point addition.
1472d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
1473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-536.
1474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) |
1475d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0)
1476d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(CpuFeatures::IsEnabled(VFP3));
1477d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 |
1478d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       dst.code()*B12 | 0x5*B9 | B8 | src2.code());
1479d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1480d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1481d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1482d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::fsubd(const Register dst,
1483d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const  Register src1,
1484d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const  Register src2,
1485d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const  SBit s,
1486d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const  Condition cond) {
1487d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = fsubd(Dn, Dm) double precision floating point subtraction.
1488d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
1489d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-784.
1490d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) |
1491d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 1(6) | M=?(5) | 0(4) | Vm(3-0)
1492d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(CpuFeatures::IsEnabled(VFP3));
1493d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 |
1494d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       dst.code()*B12 | 0x5*B9 | B8 | B6 | src2.code());
1495d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1496d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1497d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::fmuld(const Register dst,
1499d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const  Register src1,
1500d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const  Register src2,
1501d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const  SBit s,
1502d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const  Condition cond) {
1503d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = fmuld(Dn, Dm) double precision floating point multiplication.
1504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
1505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-784.
1506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 11100(27-23)| D=?(22) | 10(21-20) | Vn(19-16) |
1507d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0)
1508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(CpuFeatures::IsEnabled(VFP3));
1509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 | 0x2*B20 | src1.code()*B16 |
1510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       dst.code()*B12 | 0x5*B9 | B8 | src2.code());
1511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1512d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1514d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::fdivd(const Register dst,
1515d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const  Register src1,
1516d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const  Register src2,
1517d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const  SBit s,
1518d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                      const  Condition cond) {
1519d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = fdivd(Dn, Dm) double precision floating point division.
1520d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
1521d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-584.
1522d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 11101(27-23)| D=?(22) | 00(21-20) | Vn(19-16) |
1523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=? | 0(6) | M=?(5) | 0(4) | Vm(3-0)
1524d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(CpuFeatures::IsEnabled(VFP3));
1525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 | B23 | src1.code()*B16 |
1526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       dst.code()*B12 | 0x5*B9 | B8 | src2.code());
1527d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1528d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1529d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::fcmp(const Register src1,
1531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const Register src2,
1532d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const SBit s,
1533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const Condition cond) {
1534d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // vcmp(Dd, Dm) double precision floating point comparison.
1535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-570.
1536d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0100 (19-16) |
1537d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=? | 1(6) | M(5)=? | 0(4) | Vm(3-0)
1538d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(CpuFeatures::IsEnabled(VFP3));
1539d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 |
1540d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       src1.code()*B12 | 0x5*B9 | B8 | B6 | src2.code());
1541d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1542d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::vmrs(Register dst, Condition cond) {
1545d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-652.
1546d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) |
1547d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
1548d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(CpuFeatures::IsEnabled(VFP3));
1549d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 | 0xF*B20 |  B16 |
1550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       dst.code()*B12 | 0xA*B8 | B4);
1551d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Pseudo instructions
1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::lea(Register dst,
1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    const MemOperand& x,
1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s,
1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int am = x.am_;
1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!x.rm_.is_valid()) {
1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // immediate offset
1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if ((am & P) == 0)  // post indexing
1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mov(dst, Operand(x.rn_), s, cond);
1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    else if ((am & U) == 0)  // negative indexing
1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      sub(dst, x.rn_, Operand(x.offset_), s, cond);
1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    else
1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      add(dst, x.rn_, Operand(x.offset_), s, cond);
1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Register offset (shift_imm_ and shift_op_ are 0) or scaled
1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // register offset the constructors make sure than both shift_imm_
1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // and shift_op_ are initialized.
1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!x.rm_.is(pc));
1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if ((am & P) == 0)  // post indexing
1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mov(dst, Operand(x.rn_), s, cond);
1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    else if ((am & U) == 0)  // negative indexing
1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      sub(dst, x.rn_, Operand(x.rm_, x.shift_op_, x.shift_imm_), s, cond);
1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    else
1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      add(dst, x.rn_, Operand(x.rm_, x.shift_op_, x.shift_imm_), s, cond);
1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockbool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) {
1584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  uint32_t dummy1;
1585d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  uint32_t dummy2;
1586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return fits_shifter(imm32, &dummy1, &dummy2, NULL);
1587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1589d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::BlockConstPoolFor(int instructions) {
1591d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  BlockConstPoolBefore(pc_offset() + instructions * kInstrSize);
1592d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1593d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1594d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Debugging
1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::RecordJSReturn() {
1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  WriteRecordedPositions();
1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckBuffer();
1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RecordRelocInfo(RelocInfo::JS_RETURN);
1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::RecordComment(const char* msg) {
1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_debug_code) {
1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CheckBuffer();
1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::RecordPosition(int pos) {
1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (pos == RelocInfo::kNoPosition) return;
1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(pos >= 0);
1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current_position_ = pos;
1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::RecordStatementPosition(int pos) {
1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (pos == RelocInfo::kNoPosition) return;
1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(pos >= 0);
1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current_statement_position_ = pos;
1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::WriteRecordedPositions() {
1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Write the statement position if it is different from what was written last
1627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // time.
1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (current_statement_position_ != written_statement_position_) {
1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CheckBuffer();
1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_);
1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    written_statement_position_ = current_statement_position_;
1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Write the position if it is different from what was written last time and
1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // also different from the written statement position.
1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (current_position_ != written_position_ &&
1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      current_position_ != written_statement_position_) {
1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CheckBuffer();
1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordRelocInfo(RelocInfo::POSITION, current_position_);
1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    written_position_ = current_position_;
1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::GrowBuffer() {
1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!own_buffer_) FATAL("external code buffer is too small");
1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // compute new buffer size
1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CodeDesc desc;  // the new buffer
1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (buffer_size_ < 4*KB) {
1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    desc.buffer_size = 4*KB;
1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (buffer_size_ < 1*MB) {
1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    desc.buffer_size = 2*buffer_size_;
1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    desc.buffer_size = buffer_size_ + 1*MB;
1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_GT(desc.buffer_size, 0);  // no overflow
1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // setup new buffer
1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc.buffer = NewArray<byte>(desc.buffer_size);
1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc.instr_size = pc_offset();
1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // copy the data
1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int pc_delta = desc.buffer - buffer_;
1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  memmove(desc.buffer, buffer_, desc.instr_size);
1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  memmove(reloc_info_writer.pos() + rc_delta,
1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          reloc_info_writer.pos(), desc.reloc_size);
1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // switch buffers
1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DeleteArray(buffer_);
1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  buffer_ = desc.buffer;
1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  buffer_size_ = desc.buffer_size;
1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pc_ += pc_delta;
1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               reloc_info_writer.last_pc() + pc_delta);
1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // none of our relocation types are pc relative pointing outside the code
1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // buffer nor pc absolute pointing inside the code buffer, so there is no need
1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to relocate any emitted relocation entries
1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // relocate pending relocation entries
1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < num_prinfo_; i++) {
1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RelocInfo& rinfo = prinfo_[i];
1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           rinfo.rmode() != RelocInfo::POSITION);
1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (rinfo.rmode() != RelocInfo::JS_RETURN) {
1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      rinfo.set_pc(rinfo.pc() + pc_delta);
1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RelocInfo rinfo(pc_, rmode, data);  // we do not try to reuse pool constants
1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::STATEMENT_POSITION) {
1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Adjust code for new modes
1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(RelocInfo::IsJSReturn(rmode)
1701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           || RelocInfo::IsComment(rmode)
1702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           || RelocInfo::IsPosition(rmode));
1703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // these modes do not need an entry in the constant pool
1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(num_prinfo_ < kMaxNumPRInfo);
1706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    prinfo_[num_prinfo_++] = rinfo;
1707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Make sure the constant pool is not emitted in place of the next
1708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // instruction for which we just recorded relocation info
1709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    BlockConstPoolBefore(pc_offset() + kInstrSize);
1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (rinfo.rmode() != RelocInfo::NONE) {
1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Don't record external references unless the heap will be serialized.
1713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
1714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG
1715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (!Serializer::enabled()) {
1716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        Serializer::TooLateToEnableNow();
1717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif
1719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (!Serializer::enabled() && !FLAG_debug_code) {
1720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        return;
1721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(buffer_space() >= kMaxRelocSize);  // too late to grow buffer here
1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    reloc_info_writer.Write(&rinfo);
1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::CheckConstPool(bool force_emit, bool require_jump) {
1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the offset of the next check. It will be overwritten
1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // when a const pool is generated or when const pools are being
1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // blocked for a specific range.
1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_buffer_check_ = pc_offset() + kCheckConstInterval;
1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // There is nothing to do if there are no pending relocation info entries
1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (num_prinfo_ == 0) return;
1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We emit a constant pool at regular intervals of about kDistBetweenPools
1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // or when requested by parameter force_emit (e.g. after each function).
1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We prefer not to emit a jump unless the max distance is reached or if we
1741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // are running low on slots, which can happen if a lot of constants are being
1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // emitted (e.g. --debug-code and many static references).
1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int dist = pc_offset() - last_const_pool_end_;
1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!force_emit && dist < kMaxDistBetweenPools &&
1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      (require_jump || dist < kDistBetweenPools) &&
1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // TODO(1236125): Cleanup the "magic" number below. We know that
1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // the code generation will test every kCheckConstIntervalInst.
1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Thus we are safe as long as we generate less than 7 constant
1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // entries per instruction.
1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      (num_prinfo_ < (kMaxNumPRInfo - (7 * kCheckConstIntervalInst)))) {
1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If we did not return by now, we need to emit the constant pool soon.
1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // However, some small sequences of instructions must not be broken up by the
1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // insertion of a constant pool; such sequences are protected by setting
1758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // no_const_pool_before_, which is checked here. Also, recursive calls to
1759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // CheckConstPool are blocked by no_const_pool_before_.
1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (pc_offset() < no_const_pool_before_) {
1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Emission is currently blocked; make sure we try again as soon as possible
1762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    next_buffer_check_ = no_const_pool_before_;
1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Something is wrong if emission is forced and blocked at the same time
1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!force_emit);
1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
1767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int jump_instr = require_jump ? kInstrSize : 0;
1770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the code buffer is large enough before emitting the constant
1772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // pool and relocation information (include the jump over the pool and the
1773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // constant pool marker).
1774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int max_needed_space =
1775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      jump_instr + kInstrSize + num_prinfo_*(kInstrSize + kMaxRelocSize);
1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (buffer_space() <= (max_needed_space + kGap)) GrowBuffer();
1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Block recursive calls to CheckConstPool
1779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BlockConstPoolBefore(pc_offset() + jump_instr + kInstrSize +
1780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       num_prinfo_*kInstrSize);
1781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Don't bother to check for the emit calls below.
1782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_buffer_check_ = no_const_pool_before_;
1783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit jump over constant pool if necessary
1785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label after_pool;
1786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (require_jump) b(&after_pool);
1787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RecordComment("[ Constant Pool");
1789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Put down constant pool marker
1791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // "Undefined instruction" as specified by A3.1 Instruction set encoding
1792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(0x03000000 | num_prinfo_);
1793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Emit constant pool entries
1795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < num_prinfo_; i++) {
1796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RelocInfo& rinfo = prinfo_[i];
1797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
1798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           rinfo.rmode() != RelocInfo::POSITION &&
1799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           rinfo.rmode() != RelocInfo::STATEMENT_POSITION);
1800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Instr instr = instr_at(rinfo.pc());
1801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Instruction to patch must be a ldr/str [pc, #offset]
1803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // P and U set, B and W clear, Rn == pc, offset12 still 0
1804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT((instr & (7*B25 | P | U | B | W | 15*B16 | Off12Mask)) ==
1805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           (2*B25 | P | U | pc.code()*B16));
1806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int delta = pc_ - rinfo.pc() - 8;
1807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(delta >= -4);  // instr could be ldr pc, [pc, #-4] followed by targ32
1808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (delta < 0) {
1809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      instr &= ~U;
1810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      delta = -delta;
1811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(is_uint12(delta));
1813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr_at_put(rinfo.pc(), instr + delta);
1814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    emit(rinfo.data());
1815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  num_prinfo_ = 0;
1817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  last_const_pool_end_ = pc_offset();
1818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RecordComment("]");
1820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (after_pool.is_linked()) {
1822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bind(&after_pool);
1823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Since a constant pool was just emitted, move the check offset forward by
1826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the standard interval.
1827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_buffer_check_ = pc_offset() + kCheckConstInterval;
1828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
1832