assembler-arm.cc revision 8b112d2025046f85ef7f6be087c6129c872ebad2
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
33d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// The original source code covered by the above license above has been
34d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// modified significantly by Google Inc.
358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_ARM)
40f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "arm/assembler-arm-inl.h"
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "serialize.h"
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef DEBUG
488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochbool CpuFeatures::initialized_ = false;
498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif
508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochunsigned CpuFeatures::supported_ = 0;
518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochunsigned CpuFeatures::found_by_runtime_probing_ = 0;
528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
53402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
54402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#ifdef __arm__
55402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic uint64_t CpuFeaturesImpliedByCompiler() {
56402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  uint64_t answer = 0;
57402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#ifdef CAN_USE_ARMV7_INSTRUCTIONS
58402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  answer |= 1u << ARMv7;
59402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#endif  // def CAN_USE_ARMV7_INSTRUCTIONS
60402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // If the compiler is allowed to use VFP then we can use VFP too in our code
61402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // generation even when generating snapshots.  This won't work for cross
628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // compilation. VFPv3 implies ARMv7, see ARM DDI 0406B, page A1-6.
63402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#if defined(__VFP_FP__) && !defined(__SOFTFP__)
648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  answer |= 1u << VFP3 | 1u << ARMv7;
65402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#endif  // defined(__VFP_FP__) && !defined(__SOFTFP__)
66402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#ifdef CAN_USE_VFP_INSTRUCTIONS
678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  answer |= 1u << VFP3 | 1u << ARMv7;
68402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#endif  // def CAN_USE_VFP_INSTRUCTIONS
69402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  return answer;
70402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
71402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#endif  // def __arm__
72402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
73402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid CpuFeatures::Probe() {
758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!initialized_);
768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef DEBUG
778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  initialized_ = true;
788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif
79402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#ifndef __arm__
808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // For the simulator=arm build, use VFP when FLAG_enable_vfp3 is
818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // enabled. VFPv3 implies ARMv7, see ARM DDI 0406B, page A1-6.
823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (FLAG_enable_vfp3) {
838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    supported_ |= 1u << VFP3 | 1u << ARMv7;
843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // For the simulator=arm build, use ARMv7 when FLAG_enable_armv7 is enabled
863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (FLAG_enable_armv7) {
876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    supported_ |= 1u << ARMv7;
883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
89402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#else  // def __arm__
908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (Serializer::enabled()) {
91402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    supported_ |= OS::CpuFeaturesImpliedByPlatform();
92402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    supported_ |= CpuFeaturesImpliedByCompiler();
93d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return;  // No features if we might serialize.
94d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
95d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
96d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (OS::ArmCpuHasFeature(VFP3)) {
978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // This implementation also sets the VFP flags if runtime
988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // detection of VFP returns true. VFPv3 implies ARMv7, see ARM DDI
998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // 0406B, page A1-6.
1008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    supported_ |= 1u << VFP3 | 1u << ARMv7;
1018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    found_by_runtime_probing_ |= 1u << VFP3 | 1u << ARMv7;
102d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (OS::ArmCpuHasFeature(ARMv7)) {
1053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    supported_ |= 1u << ARMv7;
1063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    found_by_runtime_probing_ |= 1u << ARMv7;
1073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
1086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
109d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
110d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
111d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of RelocInfo
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int RelocInfo::kApplyMask = 0;
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
118f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool RelocInfo::IsCodedSpecially() {
119f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // The deserializer needs to know whether a pointer is specially coded.  Being
120f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // specially coded on ARM means that it is a movw/movt instruction.  We don't
121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // generate those yet.
122f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return false;
123f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
124f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
125f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
126f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RelocInfo::PatchCode(byte* instructions, int instruction_count) {
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the code at the current address with the supplied instructions.
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Instr* pc = reinterpret_cast<Instr*>(pc_);
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Instr* instr = reinterpret_cast<Instr*>(instructions);
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < instruction_count; i++) {
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *(pc + i) = *(instr + i);
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indicate that code has changed.
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CPU::FlushICache(pc_, instruction_count * Assembler::kInstrSize);
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Patch the code at the current PC with a call to the target address.
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Additional guard instructions can be added if required.
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the code at the current address with a call to the target.
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNIMPLEMENTED();
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of Operand and MemOperand
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// See assembler-arm-inl.h for inlined constructors
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand::Operand(Handle<Object> handle) {
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = no_reg;
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Verify all Objects referred by code are NOT in new space.
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object* obj = *handle;
15644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!HEAP->InNewSpace(obj));
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (obj->IsHeapObject()) {
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    imm32_ = reinterpret_cast<intptr_t>(handle.location());
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    rmode_ = RelocInfo::EMBEDDED_OBJECT;
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // no relocation needed
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    imm32_ =  reinterpret_cast<intptr_t>(obj);
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    rmode_ = RelocInfo::NONE;
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand::Operand(Register rm, ShiftOp shift_op, int shift_imm) {
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint5(shift_imm));
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(shift_op != ROR || shift_imm != 0);  // use RRX if you mean it
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = rm;
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rs_ = no_reg;
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_op_ = shift_op;
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_imm_ = shift_imm & 31;
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (shift_op == RRX) {
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // encoded as ROR with shift_imm == 0
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(shift_imm == 0);
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift_op_ = ROR;
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift_imm_ = 0;
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand::Operand(Register rm, ShiftOp shift_op, Register rs) {
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(shift_op != RRX);
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = rm;
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rs_ = no_reg;
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_op_ = shift_op;
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rs_ = rs;
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMemOperand::MemOperand(Register rn, int32_t offset, AddrMode am) {
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rn_ = rn;
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = no_reg;
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  offset_ = offset;
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  am_ = am;
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMemOperand::MemOperand(Register rn, Register rm, AddrMode am) {
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rn_ = rn;
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = rm;
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_op_ = LSL;
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_imm_ = 0;
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  am_ = am;
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMemOperand::MemOperand(Register rn, Register rm,
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       ShiftOp shift_op, int shift_imm, AddrMode am) {
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint5(shift_imm));
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rn_ = rn;
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = rm;
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_op_ = shift_op;
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_imm_ = shift_imm & 31;
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  am_ = am;
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
2211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Specific instructions, constants, and masks.
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// add(sp, sp, 4) instruction (aka Pop())
2241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kPopInstruction =
2251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    al | PostIndex | 4 | LeaveCC | I | sp.code() * B16 | sp.code() * B12;
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r))
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register r is not encoded.
2281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kPushRegPattern =
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    al | B26 | 4 | NegPreIndex | sp.code() * B16;
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r))
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register r is not encoded.
2321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kPopRegPattern =
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    al | B26 | L | 4 | PostIndex | sp.code() * B16;
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// mov lr, pc
2351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kMovLrPc = al | MOV | pc.code() | lr.code() * B12;
2366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// ldr rd, [pc, #offset]
2371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kLdrPCMask = kCondMask | 15 * B24 | 7 * B20 | 15 * B16;
2386ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst Instr kLdrPCPattern = al | 5 * B24 | L | pc.code() * B16;
2396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// blxcc rm
2406ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst Instr kBlxRegMask =
2416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4;
2426ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst Instr kBlxRegPattern =
2431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | BLX;
2449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovMvnMask = 0x6d * B21 | 0xf * B16;
2459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovMvnPattern = 0xd * B21;
2469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovMvnFlip = B22;
2479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovLeaveCCMask = 0xdff * B16;
2489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovLeaveCCPattern = 0x1a0 * B16;
2499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovwMask = 0xff * B20;
2509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovwPattern = 0x30 * B20;
2519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovwLeaveCCFlip = 0x5 * B21;
2529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kCmpCmnMask = 0xdd * B20 | 0xf * B12;
2539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kCmpCmnPattern = 0x15 * B20;
2549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kCmpCmnFlip = B21;
2559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kAddSubFlip = 0x6 * B21;
2569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kAndBicFlip = 0xe * B21;
2579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// A mask for the Rd register for push, pop, ldr, str instructions.
2591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kLdrRegFpOffsetPattern =
260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    al | B26 | L | Offset | fp.code() * B16;
2611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kStrRegFpOffsetPattern =
262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    al | B26 | Offset | fp.code() * B16;
2631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kLdrRegFpNegOffsetPattern =
264f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    al | B26 | L | NegOffset | fp.code() * B16;
2651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kStrRegFpNegOffsetPattern =
266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    al | B26 | NegOffset | fp.code() * B16;
2671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kLdrStrInstrTypeMask = 0xffff0000;
2681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kLdrStrInstrArgumentMask = 0x0000ffff;
2691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kLdrStrOffsetMask = 0x00000fff;
2701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Spare buffer.
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kMinimalBufferSize = 4*KB;
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2768b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochAssembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size)
2778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : AssemblerBase(arg_isolate),
27844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      positions_recorder_(this),
27944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      allow_peephole_optimization_(false),
28044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      emit_debug_code_(FLAG_debug_code) {
281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  allow_peephole_optimization_ = FLAG_peephole_optimization;
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (buffer == NULL) {
2833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Do our own buffer management.
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (buffer_size <= kMinimalBufferSize) {
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      buffer_size = kMinimalBufferSize;
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (isolate()->assembler_spare_buffer() != NULL) {
28844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        buffer = isolate()->assembler_spare_buffer();
28944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        isolate()->set_assembler_spare_buffer(NULL);
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (buffer == NULL) {
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      buffer_ = NewArray<byte>(buffer_size);
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      buffer_ = static_cast<byte*>(buffer);
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buffer_size_ = buffer_size;
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    own_buffer_ = true;
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
3013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Use externally provided buffer instead.
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(buffer_size > 0);
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buffer_ = static_cast<byte*>(buffer);
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buffer_size_ = buffer_size;
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    own_buffer_ = false;
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Setup buffer pointers.
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(buffer_ != NULL);
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pc_ = buffer_;
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  num_prinfo_ = 0;
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_buffer_check_ = 0;
3146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const_pool_blocked_nesting_ = 0;
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  no_const_pool_before_ = 0;
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  last_const_pool_end_ = 0;
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  last_bound_pos_ = 0;
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAssembler::~Assembler() {
3226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(const_pool_blocked_nesting_ == 0);
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (own_buffer_) {
32444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (isolate()->assembler_spare_buffer() == NULL &&
32544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        buffer_size_ == kMinimalBufferSize) {
32644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate()->set_assembler_spare_buffer(buffer_);
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      DeleteArray(buffer_);
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::GetCode(CodeDesc* desc) {
3353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Emit constant pool if necessary.
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckConstPool(true, false);
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(num_prinfo_ == 0);
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Setup code descriptor.
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc->buffer = buffer_;
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc->buffer_size = buffer_size_;
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc->instr_size = pc_offset();
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::Align(int m) {
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(m >= 4 && IsPowerOf2(m));
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while ((pc_offset() & (m - 1)) != 0) {
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    nop();
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid Assembler::CodeTargetAlign() {
3569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Preferred alignment of jump targets on some ARM chips.
3579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  Align(8);
3589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
3599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3611e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockCondition Assembler::GetCondition(Instr instr) {
3621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return Instruction::ConditionField(instr);
3631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
3641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3666ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockbool Assembler::IsBranch(Instr instr) {
3676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return (instr & (B27 | B25)) == (B27 | B25);
3686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
3696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3716ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockint Assembler::GetBranchOffset(Instr instr) {
3726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(IsBranch(instr));
3736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Take the jump offset in the lower 24 bits, sign extend it and multiply it
3746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // with 4 to get the offset in bytes.
3751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return ((instr & kImm24Mask) << 8) >> 6;
3766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
3776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3796ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockbool Assembler::IsLdrRegisterImmediate(Instr instr) {
3806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return (instr & (B27 | B26 | B25 | B22 | B20)) == (B26 | B20);
3816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
3826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3846ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockint Assembler::GetLdrRegisterImmediateOffset(Instr instr) {
3856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(IsLdrRegisterImmediate(instr));
3866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool positive = (instr & B23) == B23;
3871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int offset = instr & kOff12Mask;  // Zero extended offset.
3886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return positive ? offset : -offset;
3896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
3906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3926ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockInstr Assembler::SetLdrRegisterImmediateOffset(Instr instr, int offset) {
3936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(IsLdrRegisterImmediate(instr));
3946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool positive = offset >= 0;
3956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!positive) offset = -offset;
3966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(is_uint12(offset));
3976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Set bit indicating whether the offset should be added.
3986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  instr = (instr & ~B23) | (positive ? B23 : 0);
3996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Set the actual offset.
4001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (instr & ~kOff12Mask) | offset;
4016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
40450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsenbool Assembler::IsStrRegisterImmediate(Instr instr) {
40550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  return (instr & (B27 | B26 | B25 | B22 | B20)) == B26;
40650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen}
40750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
40850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
40950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian MonsenInstr Assembler::SetStrRegisterImmediateOffset(Instr instr, int offset) {
41050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  ASSERT(IsStrRegisterImmediate(instr));
41150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  bool positive = offset >= 0;
41250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  if (!positive) offset = -offset;
41350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  ASSERT(is_uint12(offset));
41450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  // Set bit indicating whether the offset should be added.
41550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  instr = (instr & ~B23) | (positive ? B23 : 0);
41650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  // Set the actual offset.
4171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (instr & ~kOff12Mask) | offset;
41850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen}
41950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
42050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
42150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsenbool Assembler::IsAddRegisterImmediate(Instr instr) {
42250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  return (instr & (B27 | B26 | B25 | B24 | B23 | B22 | B21)) == (B25 | B23);
42350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen}
42450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
42550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
42650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian MonsenInstr Assembler::SetAddRegisterImmediateOffset(Instr instr, int offset) {
42750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  ASSERT(IsAddRegisterImmediate(instr));
42850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  ASSERT(offset >= 0);
42950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  ASSERT(is_uint12(offset));
43050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  // Set the offset.
4311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (instr & ~kOff12Mask) | offset;
43250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen}
43350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
43450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
435f7060e27768c550ace7ec48ad8c093466db52dfaLeon ClarkeRegister Assembler::GetRd(Instr instr) {
436f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register reg;
4371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  reg.code_ = Instruction::RdValue(instr);
4381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return reg;
4391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
4401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4421e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockRegister Assembler::GetRn(Instr instr) {
4431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register reg;
4441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  reg.code_ = Instruction::RnValue(instr);
4451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return reg;
4461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
4471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4491e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockRegister Assembler::GetRm(Instr instr) {
4501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register reg;
4511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  reg.code_ = Instruction::RmValue(instr);
452f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return reg;
453f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
454f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
455f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool Assembler::IsPush(Instr instr) {
457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return ((instr & ~kRdMask) == kPushRegPattern);
458f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
460f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool Assembler::IsPop(Instr instr) {
462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return ((instr & ~kRdMask) == kPopRegPattern);
463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool Assembler::IsStrRegFpOffset(Instr instr) {
467f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return ((instr & kLdrStrInstrTypeMask) == kStrRegFpOffsetPattern);
468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool Assembler::IsLdrRegFpOffset(Instr instr) {
472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpOffsetPattern);
473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool Assembler::IsStrRegFpNegOffset(Instr instr) {
477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return ((instr & kLdrStrInstrTypeMask) == kStrRegFpNegOffsetPattern);
478f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool Assembler::IsLdrRegFpNegOffset(Instr instr) {
482f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpNegOffsetPattern);
483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangbool Assembler::IsLdrPcImmediateOffset(Instr instr) {
4878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check the instruction is indeed a
4888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // ldr<cond> <Rd>, [pc +/- offset_12].
4891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (instr & (kLdrPCMask & ~kCondMask)) == 0x051f0000;
4901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
4911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockbool Assembler::IsTstImmediate(Instr instr) {
4941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) ==
4951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      (I | TST | S);
4961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
4971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockbool Assembler::IsCmpRegister(Instr instr) {
5001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask | B4)) ==
5011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      (CMP | S);
5021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
5031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockbool Assembler::IsCmpImmediate(Instr instr) {
5061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) ==
5071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      (I | CMP | S);
5088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
5098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5111e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockRegister Assembler::GetCmpImmediateRegister(Instr instr) {
5121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(IsCmpImmediate(instr));
5131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return GetRn(instr);
5141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
5151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Assembler::GetCmpImmediateRawImmediate(Instr instr) {
5181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(IsCmpImmediate(instr));
5191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return instr & kOff12Mask;
5201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
5211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Labels refer to positions in the (to be) generated code.
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// There are bound, linked, and unused labels.
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Bound labels refer to known positions in the already
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// generated code. pos() is the position the label refers to.
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Linked labels refer to unknown positions in the code
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to be generated; pos() is the position of the last
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// instruction using the label.
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The link chain is terminated by a negative code position (must be aligned)
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int kEndOfChain = -4;
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Assembler::target_at(int pos)  {
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Instr instr = instr_at(pos);
5391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if ((instr & ~kImm24Mask) == 0) {
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Emitted label constant, not part of a branch.
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return instr - (Code::kHeaderSize - kHeapObjectTag);
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((instr & 7*B25) == 5*B25);  // b, bl, or blx imm24
5441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int imm26 = ((instr & kImm24Mask) << 8) >> 6;
5451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if ((Instruction::ConditionField(instr) == kSpecialCondition) &&
5461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ((instr & B24) != 0)) {
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // blx uses bit 24 to encode bit 2 of imm26
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    imm26 += 2;
5496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return pos + kPcLoadDelta + imm26;
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::target_at_put(int pos, int target_pos) {
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Instr instr = instr_at(pos);
5561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if ((instr & ~kImm24Mask) == 0) {
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(target_pos == kEndOfChain || target_pos >= 0);
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Emitted label constant, not part of a branch.
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Make label relative to Code* of generated Code object.
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm26 = target_pos - (pos + kPcLoadDelta);
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((instr & 7*B25) == 5*B25);  // b, bl, or blx imm24
5651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (Instruction::ConditionField(instr) == kSpecialCondition) {
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // blx uses bit 24 to encode bit 2 of imm26
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT((imm26 & 1) == 0);
5681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    instr = (instr & ~(B24 | kImm24Mask)) | ((imm26 & 2) >> 1)*B24;
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT((imm26 & 3) == 0);
5711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    instr &= ~kImm24Mask;
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm24 = imm26 >> 2;
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_int24(imm24));
5751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  instr_at_put(pos, instr | (imm24 & kImm24Mask));
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::print(Label* L) {
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (L->is_unused()) {
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("unused label\n");
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (L->is_bound()) {
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("bound label to %d\n", L->pos());
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (L->is_linked()) {
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label l = *L;
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("unbound label");
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while (l.is_linked()) {
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PrintF("@ %d ", l.pos());
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Instr instr = instr_at(l.pos());
5901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if ((instr & ~kImm24Mask) == 0) {
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        PrintF("value\n");
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ASSERT((instr & 7*B25) == 5*B25);  // b, bl, or blx
5941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        Condition cond = Instruction::ConditionField(instr);
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        const char* b;
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        const char* c;
5971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        if (cond == kSpecialCondition) {
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          b = "blx";
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          c = "";
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if ((instr & B24) != 0)
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            b = "bl";
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          else
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            b = "b";
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          switch (cond) {
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case eq: c = "eq"; break;
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case ne: c = "ne"; break;
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case hs: c = "hs"; break;
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case lo: c = "lo"; break;
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case mi: c = "mi"; break;
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case pl: c = "pl"; break;
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case vs: c = "vs"; break;
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case vc: c = "vc"; break;
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case hi: c = "hi"; break;
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case ls: c = "ls"; break;
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case ge: c = "ge"; break;
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case lt: c = "lt"; break;
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case gt: c = "gt"; break;
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case le: c = "le"; break;
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case al: c = ""; break;
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            default:
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              c = "";
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              UNREACHABLE();
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        PrintF("%s%s\n", b, c);
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      next(&l);
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bind_to(Label* L, int pos) {
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(0 <= pos && pos <= pc_offset());  // must have a valid binding position
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (L->is_linked()) {
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int fixup_pos = L->pos();
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    next(L);  // call next before overwriting link with target at fixup_pos
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    target_at_put(fixup_pos, pos);
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  L->bind_to(pos);
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Keep track of the last bound label so we don't eliminate any instructions
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // before a bound label.
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (pos > last_bound_pos_)
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    last_bound_pos_ = pos;
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::link_to(Label* L, Label* appendix) {
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (appendix->is_linked()) {
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (L->is_linked()) {
6563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // Append appendix to L's list.
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int fixup_pos;
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int link = L->pos();
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      do {
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        fixup_pos = link;
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        link = target_at(fixup_pos);
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } while (link > 0);
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(link == kEndOfChain);
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      target_at_put(fixup_pos, appendix->pos());
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
6663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // L is empty, simply use appendix.
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *L = *appendix;
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  appendix->Unuse();  // appendix should not be used anymore
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bind(Label* L) {
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!L->is_bound());  // label can only be bound once
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind_to(L, pc_offset());
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::next(Label* L) {
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(L->is_linked());
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int link = target_at(L->pos());
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (link > 0) {
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    L->link_to(link);
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(link == kEndOfChain);
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    L->Unuse();
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic Instr EncodeMovwImmediate(uint32_t immediate) {
6939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ASSERT(immediate < 0x10000);
6949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  return ((immediate & 0xf000) << 4) | (immediate & 0xfff);
6959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
6969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
6979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
6983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Low-level code emission routines depending on the addressing mode.
6999dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// If this returns true then you have to use the rotate_imm and immed_8
7009dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// that it returns, because it may have already changed the instruction
7019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// to match them!
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool fits_shifter(uint32_t imm32,
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         uint32_t* rotate_imm,
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         uint32_t* immed_8,
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         Instr* instr) {
7063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // imm32 must be unsigned.
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int rot = 0; rot < 16; rot++) {
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t imm8 = (imm32 << 2*rot) | (imm32 >> (32 - 2*rot));
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if ((imm8 <= 0xff)) {
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *rotate_imm = rot;
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *immed_8 = imm8;
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return true;
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
7159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // If the opcode is one with a complementary version and the complementary
7169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // immediate fits, change the opcode.
7179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  if (instr != NULL) {
7189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    if ((*instr & kMovMvnMask) == kMovMvnPattern) {
7199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) {
7209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        *instr ^= kMovMvnFlip;
7219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        return true;
7229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      } else if ((*instr & kMovLeaveCCMask) == kMovLeaveCCPattern) {
7238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        if (CpuFeatures::IsSupported(ARMv7)) {
7249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          if (imm32 < 0x10000) {
7259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen            *instr ^= kMovwLeaveCCFlip;
7269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen            *instr |= EncodeMovwImmediate(imm32);
7279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen            *rotate_imm = *immed_8 = 0;  // Not used for movw.
7289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen            return true;
7299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          }
7309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        }
7319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      }
7329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    } else if ((*instr & kCmpCmnMask) == kCmpCmnPattern) {
7339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      if (fits_shifter(-imm32, rotate_imm, immed_8, NULL)) {
7349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        *instr ^= kCmpCmnFlip;
7359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        return true;
7369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      }
7379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    } else {
7389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      Instr alu_insn = (*instr & kALUMask);
7391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (alu_insn == ADD ||
7401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          alu_insn == SUB) {
7419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        if (fits_shifter(-imm32, rotate_imm, immed_8, NULL)) {
7429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          *instr ^= kAddSubFlip;
7439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          return true;
7449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        }
7451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else if (alu_insn == AND ||
7461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                 alu_insn == BIC) {
7479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) {
7489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          *instr ^= kAndBicFlip;
7499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          return true;
7509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        }
7519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      }
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return false;
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We have to use the temporary register for things that can be relocated even
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// if they can be encoded in the ARM's 12 bits of immediate-offset instruction
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// space.  There is no guarantee that the relocated location can be similarly
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// encoded.
7623e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhubool Operand::must_use_constant_pool() const {
7633e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  if (rmode_ == RelocInfo::EXTERNAL_REFERENCE) {
764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG
765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!Serializer::enabled()) {
766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Serializer::TooLateToEnableNow();
767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
768402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#endif  // def DEBUG
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return Serializer::enabled();
7703e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  } else if (rmode_ == RelocInfo::NONE) {
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return false;
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
77744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Operand::is_single_instruction(Instr instr) const {
7789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  if (rm_.is_valid()) return true;
7799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  uint32_t dummy1, dummy2;
78044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (must_use_constant_pool() ||
78144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      !fits_shifter(imm32_, &dummy1, &dummy2, &instr)) {
78244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // The immediate operand cannot be encoded as a shifter operand, or use of
78344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // constant pool is required. For a mov instruction not setting the
78444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // condition code additional instruction conventions can be used.
78544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if ((instr & ~kCondMask) == 13*B21) {  // mov, S not set
78644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (must_use_constant_pool() ||
7878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          !CpuFeatures::IsSupported(ARMv7)) {
78844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // mov instruction will be an ldr from constant pool (one instruction).
78944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        return true;
79044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      } else {
79144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // mov instruction will be a mov or movw followed by movt (two
79244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // instructions).
79344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        return false;
79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
79544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else {
79644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // If this is not a mov or mvn instruction there will always an additional
79744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // instructions - either mov or ldr. The mov might actually be two
79844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // instructions mov or movw followed by movt so including the actual
79944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // instruction two or three instructions will be generated.
80044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return false;
80144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
80244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
80344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // No use of constant pool and the immediate operand can be encoded as a
80444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // shifter operand.
80544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return true;
80644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
8079dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
8089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
8099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod1(Instr instr,
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         Register rn,
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         Register rd,
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         const Operand& x) {
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckBuffer();
8151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT((instr & ~(kCondMask | kOpCodeMask | S)) == 0);
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!x.rm_.is_valid()) {
8173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Immediate.
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t rotate_imm;
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t immed_8;
8203e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    if (x.must_use_constant_pool() ||
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) {
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // The immediate operand cannot be encoded as a shifter operand, so load
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // it first to register ip and change the original instruction to use ip.
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // However, if the original instruction is a 'mov rd, x' (not setting the
8253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // condition code), then replace it with a 'ldr rd, [pc]'.
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CHECK(!rn.is(ip));  // rn should never be ip, or will be trashed
8271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Condition cond = Instruction::ConditionField(instr);
8281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if ((instr & ~kCondMask) == 13*B21) {  // mov, S not set
82944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (x.must_use_constant_pool() ||
8308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            !CpuFeatures::IsSupported(ARMv7)) {
8319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          RecordRelocInfo(x.rmode_, x.imm32_);
8329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          ldr(rd, MemOperand(pc, 0), cond);
8339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        } else {
8349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          // Will probably use movw, will certainly not use constant pool.
8359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          mov(rd, Operand(x.imm32_ & 0xffff), LeaveCC, cond);
8369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          movt(rd, static_cast<uint32_t>(x.imm32_) >> 16, cond);
8379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        }
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
8399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        // If this is not a mov or mvn instruction we may still be able to avoid
8409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        // a constant pool entry by using mvn or movw.
8413e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        if (!x.must_use_constant_pool() &&
8429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen            (instr & kMovMvnMask) != kMovMvnPattern) {
8439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          mov(ip, x, LeaveCC, cond);
8449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        } else {
8459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          RecordRelocInfo(x.rmode_, x.imm32_);
8469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          ldr(ip, MemOperand(pc, 0), cond);
8479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        }
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        addrmod1(instr, rn, rd, Operand(ip));
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= I | rotate_imm*B8 | immed_8;
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (!x.rs_.is_valid()) {
8543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Immediate shift.
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
8573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Register shift.
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc));
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= x.rs_.code()*B8 | x.shift_op_ | B4 | x.rm_.code();
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(instr | rn.code()*B16 | rd.code()*B12);
86250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  if (rn.is(pc) || x.rm_.is(pc)) {
8633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Block constant pool emission for one instruction after reading pc.
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    BlockConstPoolBefore(pc_offset() + kInstrSize);
86550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  }
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod2(Instr instr, Register rd, const MemOperand& x) {
8701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT((instr & ~(kCondMask | B | L)) == B26);
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int am = x.am_;
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!x.rm_.is_valid()) {
8733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Immediate offset.
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset_12 = x.offset_;
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (offset_12 < 0) {
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      offset_12 = -offset_12;
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      am ^= U;
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!is_uint12(offset_12)) {
8803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // Immediate offset cannot be encoded, load it first to register ip
8813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // rn (and rd in a load) should never be ip, or will be trashed.
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
8831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      mov(ip, Operand(x.offset_), LeaveCC, Instruction::ConditionField(instr));
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      addrmod2(instr, rd, MemOperand(x.rn_, ip, x.am_));
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(offset_12 >= 0);  // no masking needed
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= offset_12;
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
8903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Register offset (shift_imm_ and shift_op_ are 0) or scaled
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // register offset the constructors make sure than both shift_imm_
8923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // and shift_op_ are initialized.
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!x.rm_.is(pc));
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= B25 | x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod3(Instr instr, Register rd, const MemOperand& x) {
9021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT((instr & ~(kCondMask | L | S6 | H)) == (B4 | B7));
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(x.rn_.is_valid());
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int am = x.am_;
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!x.rm_.is_valid()) {
9063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Immediate offset.
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset_8 = x.offset_;
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (offset_8 < 0) {
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      offset_8 = -offset_8;
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      am ^= U;
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!is_uint8(offset_8)) {
9133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // Immediate offset cannot be encoded, load it first to register ip
9143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // rn (and rd in a load) should never be ip, or will be trashed.
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
9161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      mov(ip, Operand(x.offset_), LeaveCC, Instruction::ConditionField(instr));
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(offset_8 >= 0);  // no masking needed
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= B | (offset_8 >> 4)*B8 | (offset_8 & 0xf);
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (x.shift_imm_ != 0) {
9233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Scaled register offset not supported, load index first
9243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // rn (and rd in a load) should never be ip, or will be trashed.
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(ip, Operand(x.rm_, x.shift_op_, x.shift_imm_), LeaveCC,
9271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        Instruction::ConditionField(instr));
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
9313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Register offset.
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT((am & (P|W)) == P || !x.rm_.is(pc));  // no pc index with writeback
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= x.rm_.code();
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod4(Instr instr, Register rn, RegList rl) {
9411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT((instr & ~(kCondMask | P | U | W | L)) == B27);
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(rl != 0);
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!rn.is(pc));
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(instr | rn.code()*B16 | rl);
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod5(Instr instr, CRegister crd, const MemOperand& x) {
9493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Unindexed addressing is not encoded by this function.
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ((B27 | B26),
9511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            (instr & ~(kCondMask | kCoprocessorMask | P | U | N | W | L)));
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(x.rn_.is_valid() && !x.rm_.is_valid());
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int am = x.am_;
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int offset_8 = x.offset_;
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((offset_8 & 3) == 0);  // offset must be an aligned word offset
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  offset_8 >>= 2;
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (offset_8 < 0) {
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    offset_8 = -offset_8;
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    am ^= U;
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint8(offset_8));  // unsigned word offset must fit in a byte
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Post-indexed addressing requires W == 1; different than in addrmod2/3.
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((am & P) == 0)
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    am |= W;
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(offset_8 >= 0);  // no masking needed
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8);
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int target_pos;
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (L->is_bound()) {
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    target_pos = L->pos();
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (L->is_linked()) {
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      target_pos = L->pos();  // L's link
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      target_pos = kEndOfChain;
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    L->link_to(pc_offset());
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Block the emission of the constant pool, since the branch instruction must
9873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // be emitted at the pc offset recorded by the label.
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BlockConstPoolBefore(pc_offset() + kInstrSize);
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return target_pos - (pc_offset() + kPcLoadDelta);
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::label_at_put(Label* L, int at_offset) {
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int target_pos;
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (L->is_bound()) {
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    target_pos = L->pos();
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (L->is_linked()) {
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      target_pos = L->pos();  // L's link
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      target_pos = kEndOfChain;
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    L->link_to(at_offset);
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Branch instructions.
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::b(int branch_offset, Condition cond) {
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((branch_offset & 3) == 0);
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm24 = branch_offset >> 2;
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_int24(imm24));
10141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(cond | B27 | B25 | (imm24 & kImm24Mask));
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (cond == al) {
10173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Dead code is a good location to emit the constant pool.
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CheckConstPool(false, false);
10196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bl(int branch_offset, Condition cond) {
1024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  positions_recorder()->WriteRecordedPositions();
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((branch_offset & 3) == 0);
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm24 = branch_offset >> 2;
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_int24(imm24));
10281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(cond | B27 | B25 | B24 | (imm24 & kImm24Mask));
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::blx(int branch_offset) {  // v5 and above
10333e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  positions_recorder()->WriteRecordedPositions();
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((branch_offset & 1) == 0);
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int h = ((branch_offset & 2) >> 1)*B24;
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm24 = branch_offset >> 2;
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_int24(imm24));
10381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(kSpecialCondition | B27 | B25 | h | (imm24 & kImm24Mask));
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::blx(Register target, Condition cond) {  // v5 and above
10433e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  positions_recorder()->WriteRecordedPositions();
1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!target.is(pc));
10451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BLX | target.code());
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bx(Register target, Condition cond) {  // v5 and above, plus v4t
10503e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  positions_recorder()->WriteRecordedPositions();
1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!target.is(pc));  // use of pc is actually allowed, but discouraged
10521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BX | target.code());
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Data-processing instructions.
10573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::and_(Register dst, Register src1, const Operand& src2,
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     SBit s, Condition cond) {
10601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | AND | s, src1, dst, src2);
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::eor(Register dst, Register src1, const Operand& src2,
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
10661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | EOR | s, src1, dst, src2);
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::sub(Register dst, Register src1, const Operand& src2,
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
10721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | SUB | s, src1, dst, src2);
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::rsb(Register dst, Register src1, const Operand& src2,
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
10781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | RSB | s, src1, dst, src2);
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::add(Register dst, Register src1, const Operand& src2,
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
10841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | ADD | s, src1, dst, src2);
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Eliminate pattern: push(r), pop()
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   str(src, MemOperand(sp, 4, NegPreIndex), al);
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   add(sp, sp, Operand(kPointerSize));
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Both instructions can be eliminated.
1090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (can_peephole_optimize(2) &&
10913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // Pattern.
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      instr_at(pc_ - 1 * kInstrSize) == kPopInstruction &&
10931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      (instr_at(pc_ - 2 * kInstrSize) & ~kRdMask) == kPushRegPattern) {
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pc_ -= 2 * kInstrSize;
1095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (FLAG_print_peephole_optimization) {
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PrintF("%x push(reg)/pop() eliminated\n", pc_offset());
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::adc(Register dst, Register src1, const Operand& src2,
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
11041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | ADC | s, src1, dst, src2);
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::sbc(Register dst, Register src1, const Operand& src2,
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
11101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | SBC | s, src1, dst, src2);
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::rsc(Register dst, Register src1, const Operand& src2,
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
11161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | RSC | s, src1, dst, src2);
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::tst(Register src1, const Operand& src2, Condition cond) {
11211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | TST | S, src1, r0, src2);
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::teq(Register src1, const Operand& src2, Condition cond) {
11261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | TEQ | S, src1, r0, src2);
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::cmp(Register src1, const Operand& src2, Condition cond) {
11311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | CMP | S, src1, r0, src2);
11321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
11331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
11341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
11351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Assembler::cmp_raw_immediate(
11361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Register src, int raw_immediate, Condition cond) {
11371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(is_uint12(raw_immediate));
11381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(cond | I | CMP | S | src.code() << 16 | raw_immediate);
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::cmn(Register src1, const Operand& src2, Condition cond) {
11431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | CMN | S, src1, r0, src2);
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::orr(Register dst, Register src1, const Operand& src2,
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
11491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | ORR | s, src1, dst, src2);
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) {
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (dst.is(pc)) {
11553e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    positions_recorder()->WriteRecordedPositions();
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
11576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Don't allow nop instructions in the form mov rn, rn to be generated using
11588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // the mov instruction. They must be generated using nop(int/NopMarkerTypes)
11598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // or MarkCode(int/NopMarkerTypes) pseudo instructions.
11606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al));
11611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | MOV | s, r0, dst, src);
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid Assembler::movw(Register reg, uint32_t immediate, Condition cond) {
11669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ASSERT(immediate < 0x10000);
11679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  mov(reg, Operand(immediate), LeaveCC, cond);
11689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
11699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
11709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
11719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid Assembler::movt(Register reg, uint32_t immediate, Condition cond) {
11729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  emit(cond | 0x34*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate));
11739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
11749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
11759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bic(Register dst, Register src1, const Operand& src2,
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
11781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | BIC | s, src1, dst, src2);
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) {
11831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | MVN | s, r0, dst, src);
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Multiply instructions.
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mla(Register dst, Register src1, Register src2, Register srcA,
1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | A | s | dst.code()*B16 | srcA.code()*B12 |
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       src2.code()*B8 | B7 | B4 | src1.code());
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mul(Register dst, Register src1, Register src2,
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // dst goes in bits 16-19 for this instruction!
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | s | dst.code()*B16 | src2.code()*B8 | B7 | B4 | src1.code());
1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::smlal(Register dstL,
1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register dstH,
1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src1,
1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src2,
1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      SBit s,
1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Condition cond) {
1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(dstH));
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B23 | B22 | A | s | dstH.code()*B16 | dstL.code()*B12 |
1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       src2.code()*B8 | B7 | B4 | src1.code());
1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::smull(Register dstL,
1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register dstH,
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src1,
1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src2,
1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      SBit s,
1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Condition cond) {
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(dstH));
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 |
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       src2.code()*B8 | B7 | B4 | src1.code());
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::umlal(Register dstL,
1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register dstH,
1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src1,
1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src2,
1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      SBit s,
1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Condition cond) {
1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(dstH));
1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B23 | A | s | dstH.code()*B16 | dstL.code()*B12 |
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       src2.code()*B8 | B7 | B4 | src1.code());
1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::umull(Register dstL,
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register dstH,
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src1,
1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src2,
1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      SBit s,
1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Condition cond) {
1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(dstH));
1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B23 | s | dstH.code()*B16 | dstL.code()*B12 |
1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       src2.code()*B8 | B7 | B4 | src1.code());
1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Miscellaneous arithmetic instructions.
1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::clz(Register dst, Register src, Condition cond) {
1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // v5 and above.
1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(pc) && !src.is(pc));
1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B24 | B22 | B21 | 15*B16 | dst.code()*B12 |
12611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block       15*B8 | CLZ | src.code());
1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
126550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen// Saturating instructions.
126650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
126750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen// Unsigned saturate.
126850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsenvoid Assembler::usat(Register dst,
126950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen                     int satpos,
127050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen                     const Operand& src,
127150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen                     Condition cond) {
127250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  // v6 and above.
12738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsSupported(ARMv7));
127450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  ASSERT(!dst.is(pc) && !src.rm_.is(pc));
127550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  ASSERT((satpos >= 0) && (satpos <= 31));
127650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  ASSERT((src.shift_op_ == ASR) || (src.shift_op_ == LSL));
127750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  ASSERT(src.rs_.is(no_reg));
127850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
127950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  int sh = 0;
128050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  if (src.shift_op_ == ASR) {
128150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen      sh = 1;
128250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  }
128350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
128450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  emit(cond | 0x6*B24 | 0xe*B20 | satpos*B16 | dst.code()*B12 |
128550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen       src.shift_imm_*B7 | sh*B6 | 0x1*B4 | src.rm_.code());
128650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen}
128750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
128850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
12897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Bitfield manipulation instructions.
12907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Unsigned bit field extract.
12927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Extracts #width adjacent bits from position #lsb in a register, and
12937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// writes them to the low bits of a destination register.
12947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch//   ubfx dst, src, #lsb, #width
12957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid Assembler::ubfx(Register dst,
12967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     Register src,
12977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     int lsb,
12987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     int width,
12997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     Condition cond) {
13007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // v7 and above.
13018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsSupported(ARMv7));
13027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(!dst.is(pc) && !src.is(pc));
13037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((lsb >= 0) && (lsb <= 31));
13047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((width >= 1) && (width <= (32 - lsb)));
13057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  emit(cond | 0xf*B23 | B22 | B21 | (width - 1)*B16 | dst.code()*B12 |
13067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch       lsb*B7 | B6 | B4 | src.code());
13077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
13087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Signed bit field extract.
13117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Extracts #width adjacent bits from position #lsb in a register, and
13127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// writes them to the low bits of a destination register. The extracted
13137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// value is sign extended to fill the destination register.
13147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch//   sbfx dst, src, #lsb, #width
13157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid Assembler::sbfx(Register dst,
13167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     Register src,
13177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     int lsb,
13187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     int width,
13197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     Condition cond) {
13207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // v7 and above.
13218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsSupported(ARMv7));
13227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(!dst.is(pc) && !src.is(pc));
13237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((lsb >= 0) && (lsb <= 31));
13247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((width >= 1) && (width <= (32 - lsb)));
13257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  emit(cond | 0xf*B23 | B21 | (width - 1)*B16 | dst.code()*B12 |
13267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch       lsb*B7 | B6 | B4 | src.code());
13277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
13287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Bit field clear.
13317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Sets #width adjacent bits at position #lsb in the destination register
13327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// to zero, preserving the value of the other bits.
13337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch//   bfc dst, #lsb, #width
13347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid Assembler::bfc(Register dst, int lsb, int width, Condition cond) {
13357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // v7 and above.
13368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsSupported(ARMv7));
13377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(!dst.is(pc));
13387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((lsb >= 0) && (lsb <= 31));
13397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((width >= 1) && (width <= (32 - lsb)));
13407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  int msb = lsb + width - 1;
13417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 | 0xf);
13427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
13437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Bit field insert.
13467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Inserts #width adjacent bits from the low bits of the source register
13477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// into position #lsb of the destination register.
13487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch//   bfi dst, src, #lsb, #width
13497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid Assembler::bfi(Register dst,
13507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    Register src,
13517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    int lsb,
13527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    int width,
13537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    Condition cond) {
13547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // v7 and above.
13558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsSupported(ARMv7));
13567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(!dst.is(pc) && !src.is(pc));
13577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((lsb >= 0) && (lsb <= 31));
13587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((width >= 1) && (width <= (32 - lsb)));
13597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  int msb = lsb + width - 1;
13607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 |
13617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch       src.code());
13627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
13637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Status register access instructions.
1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mrs(Register dst, SRegister s, Condition cond) {
1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(pc));
1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B24 | s | 15*B16 | dst.code()*B12);
1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::msr(SRegisterFieldMask fields, const Operand& src,
1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(fields >= B16 && fields < B20);  // at least one field set
1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Instr instr;
1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!src.rm_.is_valid()) {
13773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Immediate.
1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t rotate_imm;
1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t immed_8;
13803e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    if (src.must_use_constant_pool() ||
1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) {
13823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // Immediate operand cannot be encoded, load it first to register ip.
1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      RecordRelocInfo(src.rmode_, src.imm32_);
1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ldr(ip, MemOperand(pc, 0), cond);
1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      msr(fields, Operand(ip), cond);
1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr = I | rotate_imm*B8 | immed_8;
1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!src.rs_.is_valid() && src.shift_imm_ == 0);  // only rm allowed
1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr = src.rm_.code();
1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | instr | B24 | B21 | fields | 15*B12);
1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Load/Store instructions.
1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (dst.is(pc)) {
14003e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    positions_recorder()->WriteRecordedPositions();
1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod2(cond | B26 | L, dst, src);
1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1404f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Eliminate pattern: push(ry), pop(rx)
1405f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   str(ry, MemOperand(sp, 4, NegPreIndex), al)
1406f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //   ldr(rx, MemOperand(sp, 4, PostIndex), al)
1407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Both instructions can be eliminated if ry = rx.
1408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If ry != rx, a register copy from ry to rx is inserted
1409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // after eliminating the push and the pop instructions.
14107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (can_peephole_optimize(2)) {
14117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Instr push_instr = instr_at(pc_ - 2 * kInstrSize);
14127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Instr pop_instr = instr_at(pc_ - 1 * kInstrSize);
14137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
14147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (IsPush(push_instr) && IsPop(pop_instr)) {
14151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (Instruction::RdValue(pop_instr) != Instruction::RdValue(push_instr)) {
14167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        // For consecutive push and pop on different registers,
14177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        // we delete both the push & pop and insert a register move.
14187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        // push ry, pop rx --> mov rx, ry
14197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        Register reg_pushed, reg_popped;
14207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        reg_pushed = GetRd(push_instr);
14217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        reg_popped = GetRd(pop_instr);
14227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        pc_ -= 2 * kInstrSize;
14237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        // Insert a mov instruction, which is better than a pair of push & pop
14247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        mov(reg_popped, reg_pushed);
14257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        if (FLAG_print_peephole_optimization) {
14267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          PrintF("%x push/pop (diff reg) replaced by a reg move\n",
14277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                 pc_offset());
14287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        }
14297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      } else {
14307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        // For consecutive push and pop on the same register,
14317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        // both the push and the pop can be deleted.
14327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        pc_ -= 2 * kInstrSize;
14337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        if (FLAG_print_peephole_optimization) {
14347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          PrintF("%x push/pop (same reg) eliminated\n", pc_offset());
14357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        }
1436f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
1437f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1438f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1439f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1440f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (can_peephole_optimize(2)) {
1441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Instr str_instr = instr_at(pc_ - 2 * kInstrSize);
1442f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Instr ldr_instr = instr_at(pc_ - 1 * kInstrSize);
1443f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1444f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if ((IsStrRegFpOffset(str_instr) &&
1445f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         IsLdrRegFpOffset(ldr_instr)) ||
1446f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke       (IsStrRegFpNegOffset(str_instr) &&
1447f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         IsLdrRegFpNegOffset(ldr_instr))) {
1448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if ((ldr_instr & kLdrStrInstrArgumentMask) ==
1449f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            (str_instr & kLdrStrInstrArgumentMask)) {
1450f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Pattern: Ldr/str same fp+offset, same register.
1451f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        //
1452f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // The following:
1453f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // str rx, [fp, #-12]
1454f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // ldr rx, [fp, #-12]
1455f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        //
1456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Becomes:
1457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // str rx, [fp, #-12]
1458f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        pc_ -= 1 * kInstrSize;
1460f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (FLAG_print_peephole_optimization) {
1461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          PrintF("%x str/ldr (fp + same offset), same reg\n", pc_offset());
1462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      } else if ((ldr_instr & kLdrStrOffsetMask) ==
1464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 (str_instr & kLdrStrOffsetMask)) {
1465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Pattern: Ldr/str same fp+offset, different register.
1466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        //
1467f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // The following:
1468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // str rx, [fp, #-12]
1469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // ldr ry, [fp, #-12]
1470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        //
1471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Becomes:
1472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // str rx, [fp, #-12]
1473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // mov ry, rx
1474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        Register reg_stored, reg_loaded;
1476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        reg_stored = GetRd(str_instr);
1477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        reg_loaded = GetRd(ldr_instr);
1478f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        pc_ -= 1 * kInstrSize;
1479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        // Insert a mov instruction, which is better than ldr.
1480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        mov(reg_loaded, reg_stored);
1481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (FLAG_print_peephole_optimization) {
1482f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          PrintF("%x str/ldr (fp + same offset), diff reg \n", pc_offset());
1483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
1485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    }
1486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (can_peephole_optimize(3)) {
1489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Instr mem_write_instr = instr_at(pc_ - 3 * kInstrSize);
1490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Instr ldr_instr = instr_at(pc_ - 2 * kInstrSize);
1491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    Instr mem_read_instr = instr_at(pc_ - 1 * kInstrSize);
1492f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (IsPush(mem_write_instr) &&
1493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        IsPop(mem_read_instr)) {
1494f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      if ((IsLdrRegFpOffset(ldr_instr) ||
1495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        IsLdrRegFpNegOffset(ldr_instr))) {
14961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        if (Instruction::RdValue(mem_write_instr) ==
14971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                  Instruction::RdValue(mem_read_instr)) {
1498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Pattern: push & pop from/to same register,
1499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // with a fp+offset ldr in between
1500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          //
1501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // The following:
1502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // str rx, [sp, #-4]!
1503f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // ldr rz, [fp, #-24]
1504f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // ldr rx, [sp], #+4
1505f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          //
1506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Becomes:
1507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // if(rx == rz)
1508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          //   delete all
1509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // else
1510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          //   ldr rz, [fp, #-24]
1511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
15121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          if (Instruction::RdValue(mem_write_instr) ==
15131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block              Instruction::RdValue(ldr_instr)) {
1514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            pc_ -= 3 * kInstrSize;
1515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          } else {
1516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            pc_ -= 3 * kInstrSize;
1517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            // Reinsert back the ldr rz.
1518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            emit(ldr_instr);
1519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          }
1520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          if (FLAG_print_peephole_optimization) {
1521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            PrintF("%x push/pop -dead ldr fp+offset in middle\n", pc_offset());
1522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          }
1523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else {
1524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Pattern: push & pop from/to different registers
1525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // with a fp+offset ldr in between
1526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          //
1527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // The following:
1528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // str rx, [sp, #-4]!
1529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // ldr rz, [fp, #-24]
1530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // ldr ry, [sp], #+4
1531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          //
1532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // Becomes:
1533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // if(ry == rz)
1534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          //   mov ry, rx;
1535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // else if(rx != rz)
1536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          //   ldr rz, [fp, #-24]
1537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          //   mov ry, rx
1538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          // else if((ry != rz) || (rx == rz)) becomes:
1539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          //   mov ry, rx
1540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          //   ldr rz, [fp, #-24]
1541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          Register reg_pushed, reg_popped;
15431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          if (Instruction::RdValue(mem_read_instr) ==
15441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block              Instruction::RdValue(ldr_instr)) {
1545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            reg_pushed = GetRd(mem_write_instr);
1546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            reg_popped = GetRd(mem_read_instr);
1547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            pc_ -= 3 * kInstrSize;
1548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            mov(reg_popped, reg_pushed);
15491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          } else if (Instruction::RdValue(mem_write_instr) !=
15501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                     Instruction::RdValue(ldr_instr)) {
1551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            reg_pushed = GetRd(mem_write_instr);
1552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            reg_popped = GetRd(mem_read_instr);
1553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            pc_ -= 3 * kInstrSize;
1554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            emit(ldr_instr);
1555f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            mov(reg_popped, reg_pushed);
15561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          } else if ((Instruction::RdValue(mem_read_instr) !=
15571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      Instruction::RdValue(ldr_instr)) ||
15581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                     (Instruction::RdValue(mem_write_instr) ==
15591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      Instruction::RdValue(ldr_instr))) {
1560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            reg_pushed = GetRd(mem_write_instr);
1561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            reg_popped = GetRd(mem_read_instr);
1562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            pc_ -= 3 * kInstrSize;
1563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            mov(reg_popped, reg_pushed);
1564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            emit(ldr_instr);
1565f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          }
1566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          if (FLAG_print_peephole_optimization) {
1567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            PrintF("%x push/pop (ldr fp+off in middle)\n", pc_offset());
1568f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          }
1569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }
1570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }
1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::str(Register src, const MemOperand& dst, Condition cond) {
1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod2(cond | B26, src, dst);
1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Eliminate pattern: pop(), push(r)
1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //     add sp, sp, #4 LeaveCC, al; str r, [sp, #-4], al
1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ->  str r, [sp, 0], al
1582f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (can_peephole_optimize(2) &&
15833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu     // Pattern.
1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     instr_at(pc_ - 1 * kInstrSize) == (kPushRegPattern | src.code() * B12) &&
1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     instr_at(pc_ - 2 * kInstrSize) == kPopInstruction) {
1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pc_ -= 2 * kInstrSize;
1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    emit(al | B26 | 0 | Offset | sp.code() * B16 | src.code() * B12);
1588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    if (FLAG_print_peephole_optimization) {
1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PrintF("%x pop()/push(reg) eliminated\n", pc_offset());
1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) {
1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod2(cond | B26 | B | L, dst, src);
1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::strb(Register src, const MemOperand& dst, Condition cond) {
1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod2(cond | B26 | B, src, dst);
1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) {
1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod3(cond | L | B7 | H | B4, dst, src);
1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::strh(Register src, const MemOperand& dst, Condition cond) {
1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod3(cond | B7 | H | B4, src, dst);
1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) {
1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod3(cond | L | B7 | S6 | B4, dst, src);
1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) {
1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod3(cond | L | B7 | S6 | H | B4, dst, src);
1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid Assembler::ldrd(Register dst1, Register dst2,
1626f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                     const MemOperand& src, Condition cond) {
16278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(ARMv7));
162825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  ASSERT(src.rm().is(no_reg));
1629f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(!dst1.is(lr));  // r14.
1630f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(0, dst1.code() % 2);
1631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(dst1.code() + 1, dst2.code());
1632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  addrmod3(cond | B7 | B6 | B4, dst1, src);
163325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}
163425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
163525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid Assembler::strd(Register src1, Register src2,
1637f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                     const MemOperand& dst, Condition cond) {
163825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  ASSERT(dst.rm().is(no_reg));
1639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(!src1.is(lr));  // r14.
1640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(0, src1.code() % 2);
1641f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(src1.code() + 1, src2.code());
16428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(ARMv7));
1643f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  addrmod3(cond | B7 | B6 | B5 | B4, src1, dst);
164425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}
164525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
16463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Load/Store multiple instructions.
1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldm(BlockAddrMode am,
1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register base,
1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    RegList dst,
1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
16513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // ABI stack constraint: ldmxx base, {..sp..}  base != sp  is not restartable.
1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(base.is(sp) || (dst & sp.bit()) == 0);
1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod4(cond | B27 | am | L, base, dst);
1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Emit the constant pool after a function return implemented by ldm ..{..pc}.
1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (cond == al && (dst & pc.bit()) != 0) {
1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // There is a slight chance that the ldm instruction was actually a call,
1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // in which case it would be wrong to return into the constant pool; we
1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // recognize this case by checking if the emission of the pool was blocked
1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // at the pc of the ldm instruction by a mov lr, pc instruction; if this is
1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // the case, we emit a jump over the pool.
1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CheckConstPool(true, no_const_pool_before_ == pc_offset() - kInstrSize);
1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::stm(BlockAddrMode am,
1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register base,
1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    RegList src,
1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod4(cond | B27 | am, base, src);
1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Exception-generating instructions and debugging support.
16773e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu// Stops with a non-negative code less than kNumOfWatchedStops support
16783e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu// enabling/disabling and a counter feature. See simulator-arm.h .
16793e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhuvoid Assembler::stop(const char* msg, Condition cond, int32_t code) {
1680402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#ifndef __arm__
16813e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(code >= kDefaultStopCode);
16823e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // The Simulator will handle the stop instruction and get the message address.
16833e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // It expects to find the address just after the svc instruction.
16843e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  BlockConstPoolFor(2);
16853e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  if (code >= 0) {
16861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    svc(kStopCode + code, cond);
16873e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  } else {
16881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    svc(kStopCode + kMaxStopCode, cond);
16893e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  }
16903e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  emit(reinterpret_cast<Instr>(msg));
1691402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#else  // def __arm__
1692402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#ifdef CAN_USE_ARMV5_INSTRUCTIONS
16931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (cond != al) {
16941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Label skip;
16951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    b(&skip, NegateCondition(cond));
16961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    bkpt(0);
16971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    bind(&skip);
16981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
16991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    bkpt(0);
17001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1701402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#else  // ndef CAN_USE_ARMV5_INSTRUCTIONS
1702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  svc(0x9f0001, cond);
1703402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#endif  // ndef CAN_USE_ARMV5_INSTRUCTIONS
1704402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#endif  // def __arm__
1705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bkpt(uint32_t imm16) {  // v5 and above
1709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint16(imm16));
17101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(al | B24 | B21 | (imm16 >> 4)*B8 | BKPT | (imm16 & 0xf));
1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhuvoid Assembler::svc(uint32_t imm24, Condition cond) {
1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint24(imm24));
1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | 15*B24 | imm24);
1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Coprocessor instructions.
1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::cdp(Coprocessor coproc,
1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_1,
1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crd,
1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crn,
1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crm,
1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_2,
1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint4(opcode_1) && is_uint3(opcode_2));
1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B27 | B26 | B25 | (opcode_1 & 15)*B20 | crn.code()*B16 |
1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       crd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | crm.code());
1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::cdp2(Coprocessor coproc,
1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int opcode_1,
1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crd,
1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crn,
1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crm,
1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int opcode_2) {  // v5 and above
17401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  cdp(coproc, opcode_1, crd, crn, crm, opcode_2, kSpecialCondition);
1741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mcr(Coprocessor coproc,
1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_1,
1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register rd,
1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crn,
1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crm,
1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_2,
1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2));
1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | crn.code()*B16 |
1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
1754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mcr2(Coprocessor coproc,
1758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int opcode_1,
1759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     Register rd,
1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crn,
1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crm,
1762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int opcode_2) {  // v5 and above
17631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  mcr(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition);
1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mrc(Coprocessor coproc,
1768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_1,
1769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register rd,
1770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crn,
1771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crm,
1772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_2,
1773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2));
1775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | L | crn.code()*B16 |
1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mrc2(Coprocessor coproc,
1781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int opcode_1,
1782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     Register rd,
1783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crn,
1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crm,
1785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int opcode_2) {  // v5 and above
17861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  mrc(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition);
1787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldc(Coprocessor coproc,
1791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crd,
1792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    const MemOperand& src,
1793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    LFlag l,
1794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod5(cond | B27 | B26 | l | L | coproc*B8, crd, src);
1796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldc(Coprocessor coproc,
1800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crd,
1801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register rn,
1802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int option,
1803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    LFlag l,
1804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
18053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Unindexed addressing.
1806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint8(option));
1807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B27 | B26 | U | l | L | rn.code()*B16 | crd.code()*B12 |
1808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       coproc*B8 | (option & 255));
1809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldc2(Coprocessor coproc,
1813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crd,
1814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     const MemOperand& src,
1815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     LFlag l) {  // v5 and above
18161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ldc(coproc, crd, src, l, kSpecialCondition);
1817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldc2(Coprocessor coproc,
1821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crd,
1822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     Register rn,
1823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int option,
1824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     LFlag l) {  // v5 and above
18251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ldc(coproc, crd, rn, option, l, kSpecialCondition);
1826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1829d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Support for VFP.
183080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1831d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Assembler::vldr(const DwVfpRegister dst,
1832d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                     const Register base,
1833d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                     int offset,
1834d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                     const Condition cond) {
1835d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Ddst = MEM(Rbase + offset).
1836d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Instruction details available in ARM DDI 0406A, A8-628.
1837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) |
1838d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Vdst(15-12) | 1011(11-8) | offset
18398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
1840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int u = 1;
1841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (offset < 0) {
1842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    offset = -offset;
1843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    u = 0;
1844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1845e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1846756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ASSERT(offset >= 0);
1847e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((offset % 4) == 0 && (offset / 4) < 256) {
1848e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    emit(cond | u*B23 | 0xD1*B20 | base.code()*B16 | dst.code()*B12 |
1849e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         0xB*B8 | ((offset / 4) & 255));
1850e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
1851e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Larger offsets must be handled by computing the correct address
1852e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // in the ip register.
1853e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(!base.is(ip));
1854e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (u == 1) {
1855e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      add(ip, base, Operand(offset));
1856e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
1857e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      sub(ip, base, Operand(offset));
1858e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1859e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    emit(cond | 0xD1*B20 | ip.code()*B16 | dst.code()*B12 | 0xB*B8);
1860e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1861e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1862e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1863e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1864e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid Assembler::vldr(const DwVfpRegister dst,
1865e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const MemOperand& operand,
1866e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const Condition cond) {
1867e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(!operand.rm().is_valid());
1868e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(operand.am_ == Offset);
1869e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  vldr(dst, operand.rn(), operand.offset(), cond);
1870d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1871d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1872d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
18736ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vldr(const SwVfpRegister dst,
18746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     const Register base,
18756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     int offset,
18766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     const Condition cond) {
18776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Sdst = MEM(Rbase + offset).
18786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Instruction details available in ARM DDI 0406A, A8-628.
1879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) |
18806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Vdst(15-12) | 1010(11-8) | offset
18818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
1882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int u = 1;
1883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (offset < 0) {
1884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    offset = -offset;
1885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    u = 0;
1886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
188780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int sd, d;
188880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  dst.split_code(&sd, &d);
1889e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(offset >= 0);
1890e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1891e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((offset % 4) == 0 && (offset / 4) < 256) {
1892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  emit(cond | u*B23 | d*B22 | 0xD1*B20 | base.code()*B16 | sd*B12 |
18936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block       0xA*B8 | ((offset / 4) & 255));
1894e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
1895e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Larger offsets must be handled by computing the correct address
1896e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // in the ip register.
1897e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(!base.is(ip));
1898e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (u == 1) {
1899e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      add(ip, base, Operand(offset));
1900e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
1901e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      sub(ip, base, Operand(offset));
1902e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1903e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    emit(cond | d*B22 | 0xD1*B20 | ip.code()*B16 | sd*B12 | 0xA*B8);
1904e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1905e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1906e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1907e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1908e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid Assembler::vldr(const SwVfpRegister dst,
1909e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const MemOperand& operand,
1910e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const Condition cond) {
1911e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(!operand.rm().is_valid());
1912e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(operand.am_ == Offset);
1913e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  vldr(dst, operand.rn(), operand.offset(), cond);
19146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
19156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1917d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Assembler::vstr(const DwVfpRegister src,
1918d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                     const Register base,
1919d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                     int offset,
1920d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                     const Condition cond) {
1921d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // MEM(Rbase + offset) = Dsrc.
1922d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Instruction details available in ARM DDI 0406A, A8-786.
1923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // cond(31-28) | 1101(27-24)| U000(23-20) | | Rbase(19-16) |
1924d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Vsrc(15-12) | 1011(11-8) | (offset/4)
19258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
1926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int u = 1;
1927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (offset < 0) {
1928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    offset = -offset;
1929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    u = 0;
1930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1931756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ASSERT(offset >= 0);
1932e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((offset % 4) == 0 && (offset / 4) < 256) {
1933e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    emit(cond | u*B23 | 0xD0*B20 | base.code()*B16 | src.code()*B12 |
1934e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         0xB*B8 | ((offset / 4) & 255));
1935e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
1936e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Larger offsets must be handled by computing the correct address
1937e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // in the ip register.
1938e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(!base.is(ip));
1939e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (u == 1) {
1940e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      add(ip, base, Operand(offset));
1941e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
1942e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      sub(ip, base, Operand(offset));
1943e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1944e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    emit(cond | 0xD0*B20 | ip.code()*B16 | src.code()*B12 | 0xB*B8);
1945e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1946e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1947e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1948e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1949e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid Assembler::vstr(const DwVfpRegister src,
1950e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const MemOperand& operand,
1951e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const Condition cond) {
1952e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(!operand.rm().is_valid());
1953e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(operand.am_ == Offset);
1954e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  vstr(src, operand.rn(), operand.offset(), cond);
1955d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1956d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1957d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1958756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid Assembler::vstr(const SwVfpRegister src,
1959756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                     const Register base,
1960756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                     int offset,
1961756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                     const Condition cond) {
1962756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // MEM(Rbase + offset) = SSrc.
1963756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Instruction details available in ARM DDI 0406A, A8-786.
1964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // cond(31-28) | 1101(27-24)| U000(23-20) | Rbase(19-16) |
1965756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Vdst(15-12) | 1010(11-8) | (offset/4)
19668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
1967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int u = 1;
1968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (offset < 0) {
1969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    offset = -offset;
1970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    u = 0;
1971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
197280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int sd, d;
197380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  src.split_code(&sd, &d);
1974e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(offset >= 0);
1975e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((offset % 4) == 0 && (offset / 4) < 256) {
1976e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    emit(cond | u*B23 | d*B22 | 0xD0*B20 | base.code()*B16 | sd*B12 |
1977e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         0xA*B8 | ((offset / 4) & 255));
1978e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
1979e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Larger offsets must be handled by computing the correct address
1980e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // in the ip register.
1981e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(!base.is(ip));
1982e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (u == 1) {
1983e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      add(ip, base, Operand(offset));
1984e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
1985e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      sub(ip, base, Operand(offset));
1986e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1987e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    emit(cond | d*B22 | 0xD0*B20 | ip.code()*B16 | sd*B12 | 0xA*B8);
1988e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1989e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1990e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1991e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1992e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid Assembler::vstr(const SwVfpRegister src,
1993e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const MemOperand& operand,
1994e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const Condition cond) {
1995e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(!operand.rm().is_valid());
1996e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(operand.am_ == Offset);
1997e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  vldr(src, operand.rn(), operand.offset(), cond);
1998756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
1999756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2000756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
20018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid  Assembler::vldm(BlockAddrMode am,
20028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      Register base,
20038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      DwVfpRegister first,
20048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      DwVfpRegister last,
20058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      Condition cond) {
20068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Instruction details available in ARM DDI 0406A, A8-626.
20078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
20088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // first(15-12) | 1010(11-8) | (count * 2)
20098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
20108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT_LE(first.code(), last.code());
20118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(am == ia || am == ia_w || am == db_w);
20128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!base.is(pc));
20138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
20148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int sd, d;
20158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  first.split_code(&sd, &d);
20168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int count = last.code() - first.code() + 1;
20178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 |
20188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch       0xB*B8 | count*2);
20198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
20208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
20218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
20228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid  Assembler::vstm(BlockAddrMode am,
20238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      Register base,
20248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      DwVfpRegister first,
20258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      DwVfpRegister last,
20268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      Condition cond) {
20278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Instruction details available in ARM DDI 0406A, A8-784.
20288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
20298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // first(15-12) | 1011(11-8) | (count * 2)
20308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
20318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT_LE(first.code(), last.code());
20328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(am == ia || am == ia_w || am == db_w);
20338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!base.is(pc));
20348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
20358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int sd, d;
20368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  first.split_code(&sd, &d);
20378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int count = last.code() - first.code() + 1;
20388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 |
20398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch       0xB*B8 | count*2);
20408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
20418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
20428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid  Assembler::vldm(BlockAddrMode am,
20438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      Register base,
20448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      SwVfpRegister first,
20458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      SwVfpRegister last,
20468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      Condition cond) {
20478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Instruction details available in ARM DDI 0406A, A8-626.
20488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
20498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // first(15-12) | 1010(11-8) | (count/2)
20508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
20518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT_LE(first.code(), last.code());
20528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(am == ia || am == ia_w || am == db_w);
20538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!base.is(pc));
20548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
20558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int sd, d;
20568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  first.split_code(&sd, &d);
20578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int count = last.code() - first.code() + 1;
20588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 |
20598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch       0xA*B8 | count);
20608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
20618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
20628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
20638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid  Assembler::vstm(BlockAddrMode am,
20648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      Register base,
20658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      SwVfpRegister first,
20668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      SwVfpRegister last,
20678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      Condition cond) {
20688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Instruction details available in ARM DDI 0406A, A8-784.
20698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
20708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // first(15-12) | 1011(11-8) | (count/2)
20718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
20728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT_LE(first.code(), last.code());
20738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(am == ia || am == ia_w || am == db_w);
20748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!base.is(pc));
20758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
20768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int sd, d;
20778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  first.split_code(&sd, &d);
20788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int count = last.code() - first.code() + 1;
20798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 |
20808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch       0xA*B8 | count);
20818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
20828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
20833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochstatic void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) {
20843bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  uint64_t i;
20853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  memcpy(&i, &d, 8);
20863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
20873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  *lo = i & 0xffffffff;
20883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  *hi = i >> 32;
20893bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
20903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
20913bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Only works for little endian floating point formats.
20923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// We don't support VFP on the mixed endian floating point platform.
20933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochstatic bool FitsVMOVDoubleImmediate(double d, uint32_t *encoding) {
20948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
20953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
20963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // VMOV can accept an immediate of the form:
20973bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
20983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //  +/- m * 2^(-n) where 16 <= m <= 31 and 0 <= n <= 7
20993bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
21003bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // The immediate is encoded using an 8-bit quantity, comprised of two
21013bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // 4-bit fields. For an 8-bit immediate of the form:
21023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
21033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //  [abcdefgh]
21043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
21053bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // where a is the MSB and h is the LSB, an immediate 64-bit double can be
21063bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // created of the form:
21073bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
21083bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //  [aBbbbbbb,bbcdefgh,00000000,00000000,
21093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //      00000000,00000000,00000000,00000000]
21103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
21113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // where B = ~b.
21123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
21133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
21143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  uint32_t lo, hi;
21153bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  DoubleAsTwoUInt32(d, &lo, &hi);
21163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
21173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // The most obvious constraint is the long block of zeroes.
21183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if ((lo != 0) || ((hi & 0xffff) != 0)) {
21193bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    return false;
21203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
21213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
21223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Bits 62:55 must be all clear or all set.
21233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (((hi & 0x3fc00000) != 0) && ((hi & 0x3fc00000) != 0x3fc00000)) {
21243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    return false;
21253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
21263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
21273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Bit 63 must be NOT bit 62.
21283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (((hi ^ (hi << 1)) & (0x40000000)) == 0) {
21293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    return false;
21303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
21313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
21323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Create the encoded immediate in the form:
21333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //  [00000000,0000abcd,00000000,0000efgh]
21343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  *encoding  = (hi >> 16) & 0xf;      // Low nybble.
21353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  *encoding |= (hi >> 4) & 0x70000;   // Low three bits of the high nybble.
21363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  *encoding |= (hi >> 12) & 0x80000;  // Top bit of the high nybble.
21373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
21383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  return true;
21393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
21403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
21413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
21423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid Assembler::vmov(const DwVfpRegister dst,
21433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                     double imm,
21443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                     const Condition cond) {
21453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Dd = immediate
21463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Instruction details available in ARM DDI 0406B, A8-640.
21478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
21483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
21493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  uint32_t enc;
21503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (FitsVMOVDoubleImmediate(imm, &enc)) {
21513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // The double can be encoded in the instruction.
21523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 | 0xB*B8 | enc);
21533bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  } else {
21543bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // Synthesise the double from ARM immediates. This could be implemented
21553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // using vldr from a constant pool.
21563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    uint32_t lo, hi;
21573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    DoubleAsTwoUInt32(imm, &lo, &hi);
21583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
21593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    if (lo == hi) {
21603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // If the lo and hi parts of the double are equal, the literal is easier
21613bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // to create. This is the case with 0.0.
21623bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      mov(ip, Operand(lo));
21633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      vmov(dst, ip, ip);
21643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    } else {
21653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // Move the low part of the double into the lower of the corresponsing S
21663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // registers of D register dst.
21673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      mov(ip, Operand(lo));
21683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      vmov(dst.low(), ip, cond);
21693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
21703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // Move the high part of the double into the higher of the corresponsing S
21713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // registers of D register dst.
21723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      mov(ip, Operand(hi));
21733bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      vmov(dst.high(), ip, cond);
21743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    }
21753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
21763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
21773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
21783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
21793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid Assembler::vmov(const SwVfpRegister dst,
21803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                     const SwVfpRegister src,
21813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                     const Condition cond) {
21823bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Sd = Sm
21833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Instruction details available in ARM DDI 0406B, A8-642.
21848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
218580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int sd, d, sm, m;
218680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  dst.split_code(&sd, &d);
218780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  src.split_code(&sm, &m);
218880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  emit(cond | 0xE*B24 | d*B22 | 0xB*B20 | sd*B12 | 0xA*B8 | B6 | m*B5 | sm);
21893bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
21903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
21913bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
2192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vmov(const DwVfpRegister dst,
21938defd9ff6930b4e24729971a61cf7469daf119beSteve Block                     const DwVfpRegister src,
21948defd9ff6930b4e24729971a61cf7469daf119beSteve Block                     const Condition cond) {
21958defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Dd = Dm
21968defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Instruction details available in ARM DDI 0406B, A8-642.
21978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
21988defd9ff6930b4e24729971a61cf7469daf119beSteve Block  emit(cond | 0xE*B24 | 0xB*B20 |
21998defd9ff6930b4e24729971a61cf7469daf119beSteve Block       dst.code()*B12 | 0x5*B9 | B8 | B6 | src.code());
22008defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
22018defd9ff6930b4e24729971a61cf7469daf119beSteve Block
22028defd9ff6930b4e24729971a61cf7469daf119beSteve Block
22038defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid Assembler::vmov(const DwVfpRegister dst,
2204e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Register src1,
2205e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Register src2,
2206e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Condition cond) {
2207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dm = <Rt,Rt2>.
2208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-646.
2209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) |
2210d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
22118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2212d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(!src1.is(pc) && !src2.is(pc));
2213d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xC*B24 | B22 | src2.code()*B16 |
2214d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       src1.code()*B12 | 0xB*B8 | B4 | dst.code());
2215d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2218e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vmov(const Register dst1,
2219e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Register dst2,
2220e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src,
2221e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Condition cond) {
2222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // <Rt,Rt2> = Dm.
2223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-646.
2224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) |
2225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
22268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(!dst1.is(pc) && !dst2.is(pc));
2228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 |
2229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       dst1.code()*B12 | 0xB*B8 | B4 | src.code());
2230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2233e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vmov(const SwVfpRegister dst,
2234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const Register src,
2235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const Condition cond) {
2236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Sn = Rt.
2237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-642.
2238d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) |
2239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
22408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(!src.is(pc));
224280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int sn, n;
224380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  dst.split_code(&sn, &n);
224480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  emit(cond | 0xE*B24 | sn*B16 | src.code()*B12 | 0xA*B8 | n*B7 | B4);
2245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2248e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vmov(const Register dst,
2249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const SwVfpRegister src,
2250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const Condition cond) {
2251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt = Sn.
2252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-642.
2253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) |
2254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
22558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(!dst.is(pc));
225780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int sn, n;
225880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  src.split_code(&sn, &n);
225980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  emit(cond | 0xE*B24 | B20 | sn*B16 | dst.code()*B12 | 0xA*B8 | n*B7 | B4);
2260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2262d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
22636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Type of data to read from or write to VFP register.
22646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Used as specifier in generic vcvt instruction.
22656ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockenum VFPType { S32, U32, F32, F64 };
22666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
22676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
22686ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool IsSignedVFPType(VFPType type) {
22696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  switch (type) {
22706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case S32:
22716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return true;
22726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case U32:
22736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
22746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    default:
22756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      UNREACHABLE();
22766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
22776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
22786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
22796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
22806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
22816ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool IsIntegerVFPType(VFPType type) {
22826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  switch (type) {
22836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case S32:
22846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case U32:
22856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return true;
22866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case F32:
22876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case F64:
22886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
22896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    default:
22906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      UNREACHABLE();
22916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
22926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
22936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
22946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
22956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
22966ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool IsDoubleVFPType(VFPType type) {
22976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  switch (type) {
22986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case F32:
22996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
23006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case F64:
23016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return true;
23026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    default:
23036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      UNREACHABLE();
23046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
23056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
23066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
23076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
23086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
230980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Split five bit reg_code based on size of reg_type.
231080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//  32-bit register codes are Vm:M
231180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//  64-bit register codes are M:Vm
231280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// where Vm is four bits, and M is a single bit.
231380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenstatic void SplitRegCode(VFPType reg_type,
23146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                         int reg_code,
23156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                         int* vm,
23166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                         int* m) {
231780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT((reg_code >= 0) && (reg_code <= 31));
231880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (IsIntegerVFPType(reg_type) || !IsDoubleVFPType(reg_type)) {
231980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // 32 bit type.
23206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    *m  = reg_code & 0x1;
23216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    *vm = reg_code >> 1;
23226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
232380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // 64 bit type.
23246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    *m  = (reg_code & 0x10) >> 4;
23256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    *vm = reg_code & 0x0F;
23266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
23276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
23286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
23296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
23306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Encode vcvt.src_type.dst_type instruction.
23316ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Instr EncodeVCVT(const VFPType dst_type,
23326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        const int dst_code,
23336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        const VFPType src_type,
23346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        const int src_code,
23351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                        VFPConversionMode mode,
23366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        const Condition cond) {
233780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(src_type != dst_type);
233880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int D, Vd, M, Vm;
233980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SplitRegCode(src_type, src_code, &Vm, &M);
234080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SplitRegCode(dst_type, dst_code, &Vd, &D);
234180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
23426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (IsIntegerVFPType(dst_type) || IsIntegerVFPType(src_type)) {
23436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Conversion between IEEE floating point and 32-bit integer.
23446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Instruction details available in ARM DDI 0406B, A8.6.295.
23456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 1(19) | opc2(18-16) |
23466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Vd(15-12) | 101(11-9) | sz(8) | op(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
23476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!IsIntegerVFPType(dst_type) || !IsIntegerVFPType(src_type));
23486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
234980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    int sz, opc2, op;
23506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
23516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (IsIntegerVFPType(dst_type)) {
23526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      opc2 = IsSignedVFPType(dst_type) ? 0x5 : 0x4;
23536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
235490bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner      op = mode;
23556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
23566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ASSERT(IsIntegerVFPType(src_type));
23576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      opc2 = 0x0;
23586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      sz = IsDoubleVFPType(dst_type) ? 0x1 : 0x0;
23596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      op = IsSignedVFPType(src_type) ? 0x1 : 0x0;
23606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
23616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
23626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | B19 | opc2*B16 |
23636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            Vd*B12 | 0x5*B9 | sz*B8 | op*B7 | B6 | M*B5 | Vm);
23646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
23656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Conversion between IEEE double and single precision.
23666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Instruction details available in ARM DDI 0406B, A8.6.298.
23676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0111(19-16) |
23686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Vd(15-12) | 101(11-9) | sz(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
236980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    int sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
23706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | 0x7*B16 |
23716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            Vd*B12 | 0x5*B9 | sz*B8 | B7 | B6 | M*B5 | Vm);
23726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
23736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
23746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
23756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
23766ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_f64_s32(const DwVfpRegister dst,
23776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const SwVfpRegister src,
23781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
23796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
23808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
238190bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(F64, dst.code(), S32, src.code(), mode, cond));
2382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
23856ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_f32_s32(const SwVfpRegister dst,
23866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const SwVfpRegister src,
23871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
23886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
23898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
239090bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(F32, dst.code(), S32, src.code(), mode, cond));
23916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
23926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
23936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
23946ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_f64_u32(const DwVfpRegister dst,
23956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const SwVfpRegister src,
23961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
23976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
23988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
239990bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(F64, dst.code(), U32, src.code(), mode, cond));
24006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
24016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
24026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
24036ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_s32_f64(const SwVfpRegister dst,
24046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const DwVfpRegister src,
24051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
24066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
24078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
240890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(S32, dst.code(), F64, src.code(), mode, cond));
24096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
24106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
24116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
24126ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_u32_f64(const SwVfpRegister dst,
24136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const DwVfpRegister src,
24141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
24156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
24168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
241790bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(U32, dst.code(), F64, src.code(), mode, cond));
24186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
24196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
24206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
24216ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_f64_f32(const DwVfpRegister dst,
24226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const SwVfpRegister src,
24231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
24246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
24258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
242690bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(F64, dst.code(), F32, src.code(), mode, cond));
24276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
24286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
24296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
24306ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_f32_f64(const SwVfpRegister dst,
24316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const DwVfpRegister src,
24321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
24336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
24348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
243590bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond));
2436d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2437d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2438d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
243944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::vneg(const DwVfpRegister dst,
244044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     const DwVfpRegister src,
244144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     const Condition cond) {
244244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  emit(cond | 0xE*B24 | 0xB*B20 | B16 | dst.code()*B12 |
244344f0eee88ff00398ff7f715fab053374d808c90dSteve Block       0x5*B9 | B8 | B6 | src.code());
244444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
244544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
244644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
24471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Assembler::vabs(const DwVfpRegister dst,
24481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                     const DwVfpRegister src,
24491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                     const Condition cond) {
24501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 |
24511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block       0x5*B9 | B8 | 0x3*B6 | src.code());
24521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
24531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
24541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vadd(const DwVfpRegister dst,
2456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src1,
2457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src2,
2458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Condition cond) {
2459e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Dd = vadd(Dn, Dm) double precision floating point addition.
2460d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
2461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-536.
2462d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) |
2463d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0)
24648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2465d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 |
2466d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       dst.code()*B12 | 0x5*B9 | B8 | src2.code());
2467d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2469d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2470e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vsub(const DwVfpRegister dst,
2471e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src1,
2472e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src2,
2473e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Condition cond) {
2474e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Dd = vsub(Dn, Dm) double precision floating point subtraction.
2475d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
2476d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-784.
2477d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) |
2478d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 1(6) | M=?(5) | 0(4) | Vm(3-0)
24798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2480d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 |
2481d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       dst.code()*B12 | 0x5*B9 | B8 | B6 | src2.code());
2482d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2483d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2484d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vmul(const DwVfpRegister dst,
2486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src1,
2487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src2,
2488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Condition cond) {
2489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Dd = vmul(Dn, Dm) double precision floating point multiplication.
2490d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
2491d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-784.
2492d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 11100(27-23)| D=?(22) | 10(21-20) | Vn(19-16) |
2493d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0)
24948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2495d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 | 0x2*B20 | src1.code()*B16 |
2496d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       dst.code()*B12 | 0x5*B9 | B8 | src2.code());
2497d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2499d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2500e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vdiv(const DwVfpRegister dst,
2501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src1,
2502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src2,
2503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Condition cond) {
2504e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Dd = vdiv(Dn, Dm) double precision floating point division.
2505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
2506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-584.
2507d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 11101(27-23)| D=?(22) | 00(21-20) | Vn(19-16) |
2508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=? | 0(6) | M=?(5) | 0(4) | Vm(3-0)
25098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 | B23 | src1.code()*B16 |
2511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       dst.code()*B12 | 0x5*B9 | B8 | src2.code());
2512d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2514d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vcmp(const DwVfpRegister src1,
2516e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src2,
2517d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const Condition cond) {
2518d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // vcmp(Dd, Dm) double precision floating point comparison.
2519d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-570.
2520d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0100 (19-16) |
2521b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=0 | 1(6) | M(5)=? | 0(4) | Vm(3-0)
25228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 |
2524b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch       src1.code()*B12 | 0x5*B9 | B8 | B6 | src2.code());
2525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2527d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2528756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid Assembler::vcmp(const DwVfpRegister src1,
2529756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                     const double src2,
2530756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                     const Condition cond) {
2531756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // vcmp(Dd, Dm) double precision floating point comparison.
2532756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Instruction details available in ARM DDI 0406A, A8-570.
2533756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0101 (19-16) |
2534b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=0 | 1(6) | M(5)=? | 0(4) | 0000(3-0)
25358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2536756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ASSERT(src2 == 0.0);
2537756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 | B16 |
2538b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch       src1.code()*B12 | 0x5*B9 | B8 | B6);
2539756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2540756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2541756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
254290bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brennervoid Assembler::vmsr(Register dst, Condition cond) {
254390bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  // Instruction details available in ARM DDI 0406A, A8-652.
254490bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  // cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) |
254590bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
25468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
254790bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(cond | 0xE*B24 | 0xE*B20 |  B16 |
254890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner       dst.code()*B12 | 0xA*B8 | B4);
254990bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner}
255090bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
255190bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
2552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::vmrs(Register dst, Condition cond) {
2553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-652.
2554d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) |
2555d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
25568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2557d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 | 0xF*B20 |  B16 |
2558d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       dst.code()*B12 | 0xA*B8 | B4);
2559d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2560d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2561d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
25628defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid Assembler::vsqrt(const DwVfpRegister dst,
25638defd9ff6930b4e24729971a61cf7469daf119beSteve Block                      const DwVfpRegister src,
25648defd9ff6930b4e24729971a61cf7469daf119beSteve Block                      const Condition cond) {
25658defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0001 (19-16) |
25668defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Vd(15-12) | 101(11-9) | sz(8)=1 | 11 (7-6) | M(5)=? | 0(4) | Vm(3-0)
25678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
25688defd9ff6930b4e24729971a61cf7469daf119beSteve Block  emit(cond | 0xE*B24 | B23 | 0x3*B20 | B16 |
25698defd9ff6930b4e24729971a61cf7469daf119beSteve Block       dst.code()*B12 | 0x5*B9 | B8 | 3*B6 | src.code());
25708defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
25718defd9ff6930b4e24729971a61cf7469daf119beSteve Block
25728defd9ff6930b4e24729971a61cf7469daf119beSteve Block
25733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Pseudo instructions.
25746ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::nop(int type) {
25756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // This is mov rx, rx.
25766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(0 <= type && type <= 14);  // mov pc, pc is not a nop.
25776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  emit(al | 13*B21 | type*B12 | type);
25786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
25796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
25806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
25818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangbool Assembler::IsNop(Instr instr, int type) {
25821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check for mov rx, rx where x = type.
25838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(0 <= type && type <= 14);  // mov pc, pc is not a nop.
25848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return instr == (al | 13*B21 | type*B12 | type);
25858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
25868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
25878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
2588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockbool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) {
2589d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  uint32_t dummy1;
2590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  uint32_t dummy2;
2591d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return fits_shifter(imm32, &dummy1, &dummy2, NULL);
2592d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2593d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2594d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2595d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::BlockConstPoolFor(int instructions) {
2596d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  BlockConstPoolBefore(pc_offset() + instructions * kInstrSize);
2597d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2598d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
26003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Debugging.
2601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::RecordJSReturn() {
26023e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  positions_recorder()->WriteRecordedPositions();
2603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckBuffer();
2604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RecordRelocInfo(RelocInfo::JS_RETURN);
2605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid Assembler::RecordDebugBreakSlot() {
26093e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  positions_recorder()->WriteRecordedPositions();
26107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CheckBuffer();
26117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
26127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
26137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
26147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::RecordComment(const char* msg) {
2616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_code_comments) {
2617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CheckBuffer();
2618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
2619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::GrowBuffer() {
2624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!own_buffer_) FATAL("external code buffer is too small");
2625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Compute new buffer size.
2627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CodeDesc desc;  // the new buffer
2628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (buffer_size_ < 4*KB) {
2629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    desc.buffer_size = 4*KB;
2630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (buffer_size_ < 1*MB) {
2631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    desc.buffer_size = 2*buffer_size_;
2632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    desc.buffer_size = buffer_size_ + 1*MB;
2634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_GT(desc.buffer_size, 0);  // no overflow
2636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Setup new buffer.
2638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc.buffer = NewArray<byte>(desc.buffer_size);
2639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc.instr_size = pc_offset();
2641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
2642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Copy the data.
2644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int pc_delta = desc.buffer - buffer_;
2645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
2646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  memmove(desc.buffer, buffer_, desc.instr_size);
2647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  memmove(reloc_info_writer.pos() + rc_delta,
2648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          reloc_info_writer.pos(), desc.reloc_size);
2649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Switch buffers.
2651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DeleteArray(buffer_);
2652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  buffer_ = desc.buffer;
2653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  buffer_size_ = desc.buffer_size;
2654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pc_ += pc_delta;
2655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               reloc_info_writer.last_pc() + pc_delta);
2657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // None of our relocation types are pc relative pointing outside the code
2659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // buffer nor pc absolute pointing inside the code buffer, so there is no need
26603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // to relocate any emitted relocation entries.
2661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Relocate pending relocation entries.
2663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < num_prinfo_; i++) {
2664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RelocInfo& rinfo = prinfo_[i];
2665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
2666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           rinfo.rmode() != RelocInfo::POSITION);
2667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (rinfo.rmode() != RelocInfo::JS_RETURN) {
2668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      rinfo.set_pc(rinfo.pc() + pc_delta);
2669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Assembler::db(uint8_t data) {
2675b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // No relocation info should be pending while using db. db is used
2676b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // to write pure data with no pointers and the constant pool should
2677b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // be emitted before using db.
2678b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ASSERT(num_prinfo_ == 0);
2679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CheckBuffer();
2680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  *reinterpret_cast<uint8_t*>(pc_) = data;
2681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  pc_ += sizeof(uint8_t);
2682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Assembler::dd(uint32_t data) {
2686b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // No relocation info should be pending while using dd. dd is used
2687b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // to write pure data with no pointers and the constant pool should
2688b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // be emitted before using dd.
2689b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ASSERT(num_prinfo_ == 0);
2690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CheckBuffer();
2691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  *reinterpret_cast<uint32_t*>(pc_) = data;
2692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  pc_ += sizeof(uint32_t);
2693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RelocInfo rinfo(pc_, rmode, data);  // we do not try to reuse pool constants
26987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::DEBUG_BREAK_SLOT) {
26993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Adjust code for new modes.
27007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ASSERT(RelocInfo::IsDebugBreakSlot(rmode)
27017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch           || RelocInfo::IsJSReturn(rmode)
2702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           || RelocInfo::IsComment(rmode)
2703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           || RelocInfo::IsPosition(rmode));
27043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // These modes do not need an entry in the constant pool.
2705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(num_prinfo_ < kMaxNumPRInfo);
2707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    prinfo_[num_prinfo_++] = rinfo;
2708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Make sure the constant pool is not emitted in place of the next
27093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // instruction for which we just recorded relocation info.
2710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    BlockConstPoolBefore(pc_offset() + kInstrSize);
2711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (rinfo.rmode() != RelocInfo::NONE) {
2713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Don't record external references unless the heap will be serialized.
2714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
2715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG
2716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (!Serializer::enabled()) {
2717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        Serializer::TooLateToEnableNow();
2718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
2719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif
272044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (!Serializer::enabled() && !emit_debug_code()) {
2721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        return;
2722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
2723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(buffer_space() >= kMaxRelocSize);  // too late to grow buffer here
2725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    reloc_info_writer.Write(&rinfo);
2726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::CheckConstPool(bool force_emit, bool require_jump) {
2731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the offset of the next check. It will be overwritten
2732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // when a const pool is generated or when const pools are being
2733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // blocked for a specific range.
2734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_buffer_check_ = pc_offset() + kCheckConstInterval;
2735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // There is nothing to do if there are no pending relocation info entries.
2737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (num_prinfo_ == 0) return;
2738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We emit a constant pool at regular intervals of about kDistBetweenPools
2740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // or when requested by parameter force_emit (e.g. after each function).
2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We prefer not to emit a jump unless the max distance is reached or if we
2742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // are running low on slots, which can happen if a lot of constants are being
2743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // emitted (e.g. --debug-code and many static references).
2744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int dist = pc_offset() - last_const_pool_end_;
2745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!force_emit && dist < kMaxDistBetweenPools &&
2746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      (require_jump || dist < kDistBetweenPools) &&
2747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // TODO(1236125): Cleanup the "magic" number below. We know that
2748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // the code generation will test every kCheckConstIntervalInst.
2749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Thus we are safe as long as we generate less than 7 constant
2750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // entries per instruction.
2751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      (num_prinfo_ < (kMaxNumPRInfo - (7 * kCheckConstIntervalInst)))) {
2752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
2753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If we did not return by now, we need to emit the constant pool soon.
2756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // However, some small sequences of instructions must not be broken up by the
2758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // insertion of a constant pool; such sequences are protected by setting
27596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // either const_pool_blocked_nesting_ or no_const_pool_before_, which are
27606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // both checked here. Also, recursive calls to CheckConstPool are blocked by
27616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // no_const_pool_before_.
27626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (const_pool_blocked_nesting_ > 0 || pc_offset() < no_const_pool_before_) {
27633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Emission is currently blocked; make sure we try again as soon as
27643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // possible.
27656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (const_pool_blocked_nesting_ > 0) {
27666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      next_buffer_check_ = pc_offset() + kInstrSize;
27676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
27686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      next_buffer_check_ = no_const_pool_before_;
27696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Something is wrong if emission is forced and blocked at the same time.
2772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!force_emit);
2773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
2774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int jump_instr = require_jump ? kInstrSize : 0;
2777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the code buffer is large enough before emitting the constant
2779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // pool and relocation information (include the jump over the pool and the
2780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // constant pool marker).
2781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int max_needed_space =
2782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      jump_instr + kInstrSize + num_prinfo_*(kInstrSize + kMaxRelocSize);
2783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (buffer_space() <= (max_needed_space + kGap)) GrowBuffer();
2784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Block recursive calls to CheckConstPool.
2786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BlockConstPoolBefore(pc_offset() + jump_instr + kInstrSize +
2787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       num_prinfo_*kInstrSize);
2788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Don't bother to check for the emit calls below.
2789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_buffer_check_ = no_const_pool_before_;
2790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Emit jump over constant pool if necessary.
2792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label after_pool;
2793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (require_jump) b(&after_pool);
2794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RecordComment("[ Constant Pool");
2796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Put down constant pool marker "Undefined instruction" as specified by
279844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // A5.6 (ARMv7) Instruction set encoding.
279944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  emit(kConstantPoolMarker | num_prinfo_);
2800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Emit constant pool entries.
2802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < num_prinfo_; i++) {
2803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RelocInfo& rinfo = prinfo_[i];
2804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
2805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           rinfo.rmode() != RelocInfo::POSITION &&
2806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           rinfo.rmode() != RelocInfo::STATEMENT_POSITION);
2807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Instr instr = instr_at(rinfo.pc());
2808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Instruction to patch must be a ldr/str [pc, #offset].
28103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // P and U set, B and W clear, Rn == pc, offset12 still 0.
28111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT((instr & (7*B25 | P | U | B | W | 15*B16 | kOff12Mask)) ==
2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           (2*B25 | P | U | pc.code()*B16));
2813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int delta = pc_ - rinfo.pc() - 8;
2814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(delta >= -4);  // instr could be ldr pc, [pc, #-4] followed by targ32
2815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (delta < 0) {
2816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      instr &= ~U;
2817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      delta = -delta;
2818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(is_uint12(delta));
2820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr_at_put(rinfo.pc(), instr + delta);
2821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    emit(rinfo.data());
2822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  num_prinfo_ = 0;
2824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  last_const_pool_end_ = pc_offset();
2825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RecordComment("]");
2827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (after_pool.is_linked()) {
2829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bind(&after_pool);
2830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Since a constant pool was just emitted, move the check offset forward by
2833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the standard interval.
2834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_buffer_check_ = pc_offset() + kCheckConstInterval;
2835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
2839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_ARM
2841