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
54257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Get the CPU features enabled by the build. For cross compilation the
55257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// preprocessor symbols CAN_USE_ARMV7_INSTRUCTIONS and CAN_USE_VFP_INSTRUCTIONS
56257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// can be defined to enable ARMv7 and VFPv3 instructions when building the
57257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// snapshot.
58402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic uint64_t CpuFeaturesImpliedByCompiler() {
59402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  uint64_t answer = 0;
60402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#ifdef CAN_USE_ARMV7_INSTRUCTIONS
61402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  answer |= 1u << ARMv7;
62402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#endif  // def CAN_USE_ARMV7_INSTRUCTIONS
63257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef CAN_USE_VFP_INSTRUCTIONS
64257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  answer |= 1u << VFP3 | 1u << ARMv7;
65257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif  // def CAN_USE_VFP_INSTRUCTIONS
66257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
67257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef __arm__
68402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // If the compiler is allowed to use VFP then we can use VFP too in our code
693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // generation even when generating snapshots. ARMv7 and hardware floating
703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // point support implies VFPv3, see ARM DDI 0406B, page A1-6.
713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#if defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(__VFP_FP__) \
723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    && !defined(__SOFTFP__)
738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  answer |= 1u << VFP3 | 1u << ARMv7;
743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif  // defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(__VFP_FP__)
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // && !defined(__SOFTFP__)
76257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif  // def __arm__
77257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
78402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  return answer;
79402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
80402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
81402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid CpuFeatures::Probe() {
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  unsigned standard_features = (OS::CpuFeaturesImpliedByPlatform() |
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                CpuFeaturesImpliedByCompiler());
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(supported_ == 0 || supported_ == standard_features);
868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef DEBUG
878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  initialized_ = true;
888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif
89257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
90257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the features implied by the OS and the compiler settings. This is the
91257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // minimal set of features which is also alowed for generated code in the
92257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // snapshot.
933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  supported_ |= standard_features;
94257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
95257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (Serializer::enabled()) {
96257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // No probing for features if we might serialize (generate snapshot).
97257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return;
98257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
99257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
100402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#ifndef __arm__
1018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // For the simulator=arm build, use VFP when FLAG_enable_vfp3 is
1028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // enabled. VFPv3 implies ARMv7, see ARM DDI 0406B, page A1-6.
1033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (FLAG_enable_vfp3) {
1048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    supported_ |= 1u << VFP3 | 1u << ARMv7;
1053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
1063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // For the simulator=arm build, use ARMv7 when FLAG_enable_armv7 is enabled
1073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (FLAG_enable_armv7) {
1086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    supported_ |= 1u << ARMv7;
1093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
110402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#else  // def __arm__
111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Probe for additional features not already known to be available.
112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!IsSupported(VFP3) && OS::ArmCpuHasFeature(VFP3)) {
1138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // This implementation also sets the VFP flags if runtime
1148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // detection of VFP returns true. VFPv3 implies ARMv7, see ARM DDI
1158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // 0406B, page A1-6.
1168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    supported_ |= 1u << VFP3 | 1u << ARMv7;
1178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    found_by_runtime_probing_ |= 1u << VFP3 | 1u << ARMv7;
118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!IsSupported(ARMv7) && OS::ArmCpuHasFeature(ARMv7)) {
1213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    supported_ |= 1u << ARMv7;
1223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    found_by_runtime_probing_ |= 1u << ARMv7;
1233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
1246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif
125d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of RelocInfo
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int RelocInfo::kApplyMask = 0;
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool RelocInfo::IsCodedSpecially() {
135f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // The deserializer needs to know whether a pointer is specially coded.  Being
136f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // specially coded on ARM means that it is a movw/movt instruction.  We don't
137f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // generate those yet.
138f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return false;
139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
140f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RelocInfo::PatchCode(byte* instructions, int instruction_count) {
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the code at the current address with the supplied instructions.
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Instr* pc = reinterpret_cast<Instr*>(pc_);
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Instr* instr = reinterpret_cast<Instr*>(instructions);
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < instruction_count; i++) {
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *(pc + i) = *(instr + i);
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indicate that code has changed.
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CPU::FlushICache(pc_, instruction_count * Assembler::kInstrSize);
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Patch the code at the current PC with a call to the target address.
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Additional guard instructions can be added if required.
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the code at the current address with a call to the target.
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNIMPLEMENTED();
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of Operand and MemOperand
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// See assembler-arm-inl.h for inlined constructors
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand::Operand(Handle<Object> handle) {
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = no_reg;
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Verify all Objects referred by code are NOT in new space.
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object* obj = *handle;
17144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!HEAP->InNewSpace(obj));
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (obj->IsHeapObject()) {
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    imm32_ = reinterpret_cast<intptr_t>(handle.location());
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    rmode_ = RelocInfo::EMBEDDED_OBJECT;
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // no relocation needed
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    imm32_ =  reinterpret_cast<intptr_t>(obj);
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    rmode_ = RelocInfo::NONE;
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand::Operand(Register rm, ShiftOp shift_op, int shift_imm) {
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint5(shift_imm));
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(shift_op != ROR || shift_imm != 0);  // use RRX if you mean it
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = rm;
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rs_ = no_reg;
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_op_ = shift_op;
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_imm_ = shift_imm & 31;
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (shift_op == RRX) {
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // encoded as ROR with shift_imm == 0
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(shift_imm == 0);
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift_op_ = ROR;
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shift_imm_ = 0;
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand::Operand(Register rm, ShiftOp shift_op, Register rs) {
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(shift_op != RRX);
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = rm;
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rs_ = no_reg;
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_op_ = shift_op;
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rs_ = rs;
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMemOperand::MemOperand(Register rn, int32_t offset, AddrMode am) {
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rn_ = rn;
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = no_reg;
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  offset_ = offset;
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  am_ = am;
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMemOperand::MemOperand(Register rn, Register rm, AddrMode am) {
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rn_ = rn;
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = rm;
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_op_ = LSL;
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_imm_ = 0;
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  am_ = am;
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMemOperand::MemOperand(Register rn, Register rm,
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       ShiftOp shift_op, int shift_imm, AddrMode am) {
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint5(shift_imm));
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rn_ = rn;
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rm_ = rm;
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_op_ = shift_op;
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  shift_imm_ = shift_imm & 31;
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  am_ = am;
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
2361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Specific instructions, constants, and masks.
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// add(sp, sp, 4) instruction (aka Pop())
2391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kPopInstruction =
2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    al | PostIndex | 4 | LeaveCC | I | kRegister_sp_Code * B16 |
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        kRegister_sp_Code * B12;
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r))
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register r is not encoded.
2441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kPushRegPattern =
2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    al | B26 | 4 | NegPreIndex | kRegister_sp_Code * B16;
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r))
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register r is not encoded.
2481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kPopRegPattern =
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    al | B26 | L | 4 | PostIndex | kRegister_sp_Code * B16;
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// mov lr, pc
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Instr kMovLrPc = al | MOV | kRegister_pc_Code | kRegister_lr_Code * B12;
2526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// ldr rd, [pc, #offset]
2531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kLdrPCMask = kCondMask | 15 * B24 | 7 * B20 | 15 * B16;
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Instr kLdrPCPattern = al | 5 * B24 | L | kRegister_pc_Code * B16;
2556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// blxcc rm
2566ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst Instr kBlxRegMask =
2576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4;
2586ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockconst Instr kBlxRegPattern =
2591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | BLX;
2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst Instr kBlxIp = al | kBlxRegPattern | ip.code();
2619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovMvnMask = 0x6d * B21 | 0xf * B16;
2629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovMvnPattern = 0xd * B21;
2639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovMvnFlip = B22;
2649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovLeaveCCMask = 0xdff * B16;
2659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovLeaveCCPattern = 0x1a0 * B16;
2669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovwMask = 0xff * B20;
2679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovwPattern = 0x30 * B20;
2689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kMovwLeaveCCFlip = 0x5 * B21;
2699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kCmpCmnMask = 0xdd * B20 | 0xf * B12;
2709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kCmpCmnPattern = 0x15 * B20;
2719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kCmpCmnFlip = B21;
2729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kAddSubFlip = 0x6 * B21;
2739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenconst Instr kAndBicFlip = 0xe * B21;
2749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// A mask for the Rd register for push, pop, ldr, str instructions.
2761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kLdrRegFpOffsetPattern =
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    al | B26 | L | Offset | kRegister_fp_Code * B16;
2781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kStrRegFpOffsetPattern =
2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    al | B26 | Offset | kRegister_fp_Code * B16;
2801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kLdrRegFpNegOffsetPattern =
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    al | B26 | L | NegOffset | kRegister_fp_Code * B16;
2821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kStrRegFpNegOffsetPattern =
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    al | B26 | NegOffset | kRegister_fp_Code * B16;
2841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kLdrStrInstrTypeMask = 0xffff0000;
2851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kLdrStrInstrArgumentMask = 0x0000ffff;
2861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockconst Instr kLdrStrOffsetMask = 0x00000fff;
2871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Spare buffer.
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kMinimalBufferSize = 4*KB;
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2938b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochAssembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size)
2948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : AssemblerBase(arg_isolate),
29544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      positions_recorder_(this),
29644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      emit_debug_code_(FLAG_debug_code) {
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (buffer == NULL) {
2983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Do our own buffer management.
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (buffer_size <= kMinimalBufferSize) {
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      buffer_size = kMinimalBufferSize;
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (isolate()->assembler_spare_buffer() != NULL) {
30344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        buffer = isolate()->assembler_spare_buffer();
30444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        isolate()->set_assembler_spare_buffer(NULL);
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (buffer == NULL) {
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      buffer_ = NewArray<byte>(buffer_size);
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      buffer_ = static_cast<byte*>(buffer);
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buffer_size_ = buffer_size;
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    own_buffer_ = true;
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
3163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Use externally provided buffer instead.
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(buffer_size > 0);
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buffer_ = static_cast<byte*>(buffer);
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buffer_size_ = buffer_size;
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    own_buffer_ = false;
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up buffer pointers.
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(buffer_ != NULL);
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pc_ = buffer_;
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
3273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  num_pending_reloc_info_ = 0;
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_buffer_check_ = 0;
3296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const_pool_blocked_nesting_ = 0;
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  no_const_pool_before_ = 0;
3313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  first_const_pool_use_ = -1;
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  last_bound_pos_ = 0;
3333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ClearRecordedAstId();
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAssembler::~Assembler() {
3386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(const_pool_blocked_nesting_ == 0);
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (own_buffer_) {
34044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (isolate()->assembler_spare_buffer() == NULL &&
34144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        buffer_size_ == kMinimalBufferSize) {
34244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate()->set_assembler_spare_buffer(buffer_);
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      DeleteArray(buffer_);
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::GetCode(CodeDesc* desc) {
3513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Emit constant pool if necessary.
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckConstPool(true, false);
3533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(num_pending_reloc_info_ == 0);
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up code descriptor.
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc->buffer = buffer_;
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc->buffer_size = buffer_size_;
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc->instr_size = pc_offset();
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::Align(int m) {
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(m >= 4 && IsPowerOf2(m));
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while ((pc_offset() & (m - 1)) != 0) {
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    nop();
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid Assembler::CodeTargetAlign() {
3729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Preferred alignment of jump targets on some ARM chips.
3739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  Align(8);
3749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
3759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3771e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockCondition Assembler::GetCondition(Instr instr) {
3781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return Instruction::ConditionField(instr);
3791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
3801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3826ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockbool Assembler::IsBranch(Instr instr) {
3836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return (instr & (B27 | B25)) == (B27 | B25);
3846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
3856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3876ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockint Assembler::GetBranchOffset(Instr instr) {
3886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(IsBranch(instr));
3896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Take the jump offset in the lower 24 bits, sign extend it and multiply it
3906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // with 4 to get the offset in bytes.
3911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return ((instr & kImm24Mask) << 8) >> 6;
3926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
3936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3956ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockbool Assembler::IsLdrRegisterImmediate(Instr instr) {
3966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return (instr & (B27 | B26 | B25 | B22 | B20)) == (B26 | B20);
3976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
3986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4006ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockint Assembler::GetLdrRegisterImmediateOffset(Instr instr) {
4016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(IsLdrRegisterImmediate(instr));
4026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool positive = (instr & B23) == B23;
4031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int offset = instr & kOff12Mask;  // Zero extended offset.
4046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return positive ? offset : -offset;
4056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4086ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockInstr Assembler::SetLdrRegisterImmediateOffset(Instr instr, int offset) {
4096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(IsLdrRegisterImmediate(instr));
4106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool positive = offset >= 0;
4116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!positive) offset = -offset;
4126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(is_uint12(offset));
4136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Set bit indicating whether the offset should be added.
4146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  instr = (instr & ~B23) | (positive ? B23 : 0);
4156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Set the actual offset.
4161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (instr & ~kOff12Mask) | offset;
4176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
42050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsenbool Assembler::IsStrRegisterImmediate(Instr instr) {
42150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  return (instr & (B27 | B26 | B25 | B22 | B20)) == B26;
42250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen}
42350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
42450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
42550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian MonsenInstr Assembler::SetStrRegisterImmediateOffset(Instr instr, int offset) {
42650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  ASSERT(IsStrRegisterImmediate(instr));
42750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  bool positive = offset >= 0;
42850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  if (!positive) offset = -offset;
42950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  ASSERT(is_uint12(offset));
43050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  // Set bit indicating whether the offset should be added.
43150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  instr = (instr & ~B23) | (positive ? B23 : 0);
43250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  // Set the actual offset.
4331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (instr & ~kOff12Mask) | offset;
43450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen}
43550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
43650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
43750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsenbool Assembler::IsAddRegisterImmediate(Instr instr) {
43850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  return (instr & (B27 | B26 | B25 | B24 | B23 | B22 | B21)) == (B25 | B23);
43950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen}
44050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
44150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
44250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian MonsenInstr Assembler::SetAddRegisterImmediateOffset(Instr instr, int offset) {
44350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  ASSERT(IsAddRegisterImmediate(instr));
44450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  ASSERT(offset >= 0);
44550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  ASSERT(is_uint12(offset));
44650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  // Set the offset.
4471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (instr & ~kOff12Mask) | offset;
44850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen}
44950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
45050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
451f7060e27768c550ace7ec48ad8c093466db52dfaLeon ClarkeRegister Assembler::GetRd(Instr instr) {
452f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Register reg;
4531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  reg.code_ = Instruction::RdValue(instr);
4541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return reg;
4551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
4561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4581e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockRegister Assembler::GetRn(Instr instr) {
4591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register reg;
4601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  reg.code_ = Instruction::RnValue(instr);
4611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return reg;
4621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
4631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4651e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockRegister Assembler::GetRm(Instr instr) {
4661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register reg;
4671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  reg.code_ = Instruction::RmValue(instr);
468f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return reg;
469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
472f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool Assembler::IsPush(Instr instr) {
473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return ((instr & ~kRdMask) == kPushRegPattern);
474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool Assembler::IsPop(Instr instr) {
478f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return ((instr & ~kRdMask) == kPopRegPattern);
479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
482f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool Assembler::IsStrRegFpOffset(Instr instr) {
483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return ((instr & kLdrStrInstrTypeMask) == kStrRegFpOffsetPattern);
484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
485f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
486f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool Assembler::IsLdrRegFpOffset(Instr instr) {
488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpOffsetPattern);
489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
492f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool Assembler::IsStrRegFpNegOffset(Instr instr) {
493f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return ((instr & kLdrStrInstrTypeMask) == kStrRegFpNegOffsetPattern);
494f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
495f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
496f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkebool Assembler::IsLdrRegFpNegOffset(Instr instr) {
498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpNegOffsetPattern);
499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
5028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangbool Assembler::IsLdrPcImmediateOffset(Instr instr) {
5038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check the instruction is indeed a
5048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // ldr<cond> <Rd>, [pc +/- offset_12].
5051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (instr & (kLdrPCMask & ~kCondMask)) == 0x051f0000;
5061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
5071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockbool Assembler::IsTstImmediate(Instr instr) {
5101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) ==
5111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      (I | TST | S);
5121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
5131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockbool Assembler::IsCmpRegister(Instr instr) {
5161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask | B4)) ==
5171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      (CMP | S);
5181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
5191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockbool Assembler::IsCmpImmediate(Instr instr) {
5221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) ==
5231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      (I | CMP | S);
5248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
5258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5271e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockRegister Assembler::GetCmpImmediateRegister(Instr instr) {
5281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(IsCmpImmediate(instr));
5291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return GetRn(instr);
5301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
5311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Assembler::GetCmpImmediateRawImmediate(Instr instr) {
5341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(IsCmpImmediate(instr));
5351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return instr & kOff12Mask;
5361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
5371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Labels refer to positions in the (to be) generated code.
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// There are bound, linked, and unused labels.
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Bound labels refer to known positions in the already
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// generated code. pos() is the position the label refers to.
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Linked labels refer to unknown positions in the code
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to be generated; pos() is the position of the last
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// instruction using the label.
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The link chain is terminated by a negative code position (must be aligned)
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int kEndOfChain = -4;
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Assembler::target_at(int pos)  {
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Instr instr = instr_at(pos);
5551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if ((instr & ~kImm24Mask) == 0) {
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Emitted label constant, not part of a branch.
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return instr - (Code::kHeaderSize - kHeapObjectTag);
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((instr & 7*B25) == 5*B25);  // b, bl, or blx imm24
5601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int imm26 = ((instr & kImm24Mask) << 8) >> 6;
5611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if ((Instruction::ConditionField(instr) == kSpecialCondition) &&
5621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ((instr & B24) != 0)) {
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // blx uses bit 24 to encode bit 2 of imm26
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    imm26 += 2;
5656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return pos + kPcLoadDelta + imm26;
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::target_at_put(int pos, int target_pos) {
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Instr instr = instr_at(pos);
5721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if ((instr & ~kImm24Mask) == 0) {
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(target_pos == kEndOfChain || target_pos >= 0);
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Emitted label constant, not part of a branch.
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Make label relative to Code* of generated Code object.
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm26 = target_pos - (pos + kPcLoadDelta);
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((instr & 7*B25) == 5*B25);  // b, bl, or blx imm24
5811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (Instruction::ConditionField(instr) == kSpecialCondition) {
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // blx uses bit 24 to encode bit 2 of imm26
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT((imm26 & 1) == 0);
5841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    instr = (instr & ~(B24 | kImm24Mask)) | ((imm26 & 2) >> 1)*B24;
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT((imm26 & 3) == 0);
5871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    instr &= ~kImm24Mask;
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm24 = imm26 >> 2;
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_int24(imm24));
5911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  instr_at_put(pos, instr | (imm24 & kImm24Mask));
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::print(Label* L) {
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (L->is_unused()) {
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("unused label\n");
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (L->is_bound()) {
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("bound label to %d\n", L->pos());
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (L->is_linked()) {
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label l = *L;
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("unbound label");
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while (l.is_linked()) {
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PrintF("@ %d ", l.pos());
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Instr instr = instr_at(l.pos());
6061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if ((instr & ~kImm24Mask) == 0) {
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        PrintF("value\n");
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ASSERT((instr & 7*B25) == 5*B25);  // b, bl, or blx
6101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        Condition cond = Instruction::ConditionField(instr);
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        const char* b;
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        const char* c;
6131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        if (cond == kSpecialCondition) {
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          b = "blx";
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          c = "";
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if ((instr & B24) != 0)
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            b = "bl";
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          else
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            b = "b";
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          switch (cond) {
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case eq: c = "eq"; break;
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case ne: c = "ne"; break;
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case hs: c = "hs"; break;
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case lo: c = "lo"; break;
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case mi: c = "mi"; break;
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case pl: c = "pl"; break;
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case vs: c = "vs"; break;
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case vc: c = "vc"; break;
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case hi: c = "hi"; break;
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case ls: c = "ls"; break;
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case ge: c = "ge"; break;
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case lt: c = "lt"; break;
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case gt: c = "gt"; break;
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case le: c = "le"; break;
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case al: c = ""; break;
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            default:
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              c = "";
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              UNREACHABLE();
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        PrintF("%s%s\n", b, c);
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      next(&l);
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bind_to(Label* L, int pos) {
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(0 <= pos && pos <= pc_offset());  // must have a valid binding position
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (L->is_linked()) {
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int fixup_pos = L->pos();
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    next(L);  // call next before overwriting link with target at fixup_pos
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    target_at_put(fixup_pos, pos);
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  L->bind_to(pos);
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Keep track of the last bound label so we don't eliminate any instructions
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // before a bound label.
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (pos > last_bound_pos_)
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    last_bound_pos_ = pos;
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::link_to(Label* L, Label* appendix) {
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (appendix->is_linked()) {
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (L->is_linked()) {
6723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // Append appendix to L's list.
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int fixup_pos;
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int link = L->pos();
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      do {
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        fixup_pos = link;
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        link = target_at(fixup_pos);
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } while (link > 0);
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(link == kEndOfChain);
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      target_at_put(fixup_pos, appendix->pos());
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
6823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // L is empty, simply use appendix.
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *L = *appendix;
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  appendix->Unuse();  // appendix should not be used anymore
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bind(Label* L) {
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!L->is_bound());  // label can only be bound once
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bind_to(L, pc_offset());
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::next(Label* L) {
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(L->is_linked());
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int link = target_at(L->pos());
69969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (link == kEndOfChain) {
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    L->Unuse();
70169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  } else {
70269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    ASSERT(link >= 0);
70369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    L->link_to(link);
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic Instr EncodeMovwImmediate(uint32_t immediate) {
7099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ASSERT(immediate < 0x10000);
7109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  return ((immediate & 0xf000) << 4) | (immediate & 0xfff);
7119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
7129dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
7139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
7143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Low-level code emission routines depending on the addressing mode.
7159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// If this returns true then you have to use the rotate_imm and immed_8
7169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// that it returns, because it may have already changed the instruction
7179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// to match them!
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool fits_shifter(uint32_t imm32,
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         uint32_t* rotate_imm,
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         uint32_t* immed_8,
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         Instr* instr) {
7223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // imm32 must be unsigned.
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int rot = 0; rot < 16; rot++) {
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t imm8 = (imm32 << 2*rot) | (imm32 >> (32 - 2*rot));
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if ((imm8 <= 0xff)) {
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *rotate_imm = rot;
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *immed_8 = imm8;
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return true;
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
7319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // If the opcode is one with a complementary version and the complementary
7329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // immediate fits, change the opcode.
7339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  if (instr != NULL) {
7349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    if ((*instr & kMovMvnMask) == kMovMvnPattern) {
7359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) {
7369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        *instr ^= kMovMvnFlip;
7379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        return true;
7389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      } else if ((*instr & kMovLeaveCCMask) == kMovLeaveCCPattern) {
7398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        if (CpuFeatures::IsSupported(ARMv7)) {
7409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          if (imm32 < 0x10000) {
7419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen            *instr ^= kMovwLeaveCCFlip;
7429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen            *instr |= EncodeMovwImmediate(imm32);
7439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen            *rotate_imm = *immed_8 = 0;  // Not used for movw.
7449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen            return true;
7459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          }
7469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        }
7479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      }
7489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    } else if ((*instr & kCmpCmnMask) == kCmpCmnPattern) {
7499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      if (fits_shifter(-imm32, rotate_imm, immed_8, NULL)) {
7509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        *instr ^= kCmpCmnFlip;
7519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        return true;
7529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      }
7539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    } else {
7549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      Instr alu_insn = (*instr & kALUMask);
7551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (alu_insn == ADD ||
7561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          alu_insn == SUB) {
7579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        if (fits_shifter(-imm32, rotate_imm, immed_8, NULL)) {
7589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          *instr ^= kAddSubFlip;
7599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          return true;
7609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        }
7611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else if (alu_insn == AND ||
7621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                 alu_insn == BIC) {
7639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) {
7649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          *instr ^= kAndBicFlip;
7659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          return true;
7669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        }
7679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      }
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return false;
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We have to use the temporary register for things that can be relocated even
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// if they can be encoded in the ARM's 12 bits of immediate-offset instruction
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// space.  There is no guarantee that the relocated location can be similarly
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// encoded.
7783e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhubool Operand::must_use_constant_pool() const {
7793e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  if (rmode_ == RelocInfo::EXTERNAL_REFERENCE) {
780d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG
781d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!Serializer::enabled()) {
782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      Serializer::TooLateToEnableNow();
783d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
784402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#endif  // def DEBUG
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return Serializer::enabled();
7863e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  } else if (rmode_ == RelocInfo::NONE) {
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return false;
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
79344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Operand::is_single_instruction(Instr instr) const {
7949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  if (rm_.is_valid()) return true;
7959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  uint32_t dummy1, dummy2;
79644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (must_use_constant_pool() ||
79744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      !fits_shifter(imm32_, &dummy1, &dummy2, &instr)) {
79844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // The immediate operand cannot be encoded as a shifter operand, or use of
79944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // constant pool is required. For a mov instruction not setting the
80044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // condition code additional instruction conventions can be used.
80144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if ((instr & ~kCondMask) == 13*B21) {  // mov, S not set
80244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (must_use_constant_pool() ||
8038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          !CpuFeatures::IsSupported(ARMv7)) {
80444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // mov instruction will be an ldr from constant pool (one instruction).
80544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        return true;
80644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      } else {
80744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // mov instruction will be a mov or movw followed by movt (two
80844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // instructions).
80944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        return false;
81044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
81144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else {
81244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // If this is not a mov or mvn instruction there will always an additional
81344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // instructions - either mov or ldr. The mov might actually be two
81444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // instructions mov or movw followed by movt so including the actual
81544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // instruction two or three instructions will be generated.
81644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return false;
81744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
81844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
81944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // No use of constant pool and the immediate operand can be encoded as a
82044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // shifter operand.
82144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return true;
82244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
8239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
8249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
8259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod1(Instr instr,
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         Register rn,
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         Register rd,
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         const Operand& x) {
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckBuffer();
8311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT((instr & ~(kCondMask | kOpCodeMask | S)) == 0);
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!x.rm_.is_valid()) {
8333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Immediate.
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t rotate_imm;
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t immed_8;
8363e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    if (x.must_use_constant_pool() ||
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) {
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // The immediate operand cannot be encoded as a shifter operand, so load
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // it first to register ip and change the original instruction to use ip.
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // However, if the original instruction is a 'mov rd, x' (not setting the
8413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // condition code), then replace it with a 'ldr rd, [pc]'.
842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CHECK(!rn.is(ip));  // rn should never be ip, or will be trashed
8431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Condition cond = Instruction::ConditionField(instr);
8441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if ((instr & ~kCondMask) == 13*B21) {  // mov, S not set
84544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (x.must_use_constant_pool() ||
8468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            !CpuFeatures::IsSupported(ARMv7)) {
8479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          RecordRelocInfo(x.rmode_, x.imm32_);
8489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          ldr(rd, MemOperand(pc, 0), cond);
8499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        } else {
8509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          // Will probably use movw, will certainly not use constant pool.
8519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          mov(rd, Operand(x.imm32_ & 0xffff), LeaveCC, cond);
8529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          movt(rd, static_cast<uint32_t>(x.imm32_) >> 16, cond);
8539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        }
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
8559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        // If this is not a mov or mvn instruction we may still be able to avoid
8569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        // a constant pool entry by using mvn or movw.
8573e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        if (!x.must_use_constant_pool() &&
8589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen            (instr & kMovMvnMask) != kMovMvnPattern) {
8599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          mov(ip, x, LeaveCC, cond);
8609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        } else {
8619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          RecordRelocInfo(x.rmode_, x.imm32_);
8629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen          ldr(ip, MemOperand(pc, 0), cond);
8639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        }
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        addrmod1(instr, rn, rd, Operand(ip));
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= I | rotate_imm*B8 | immed_8;
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (!x.rs_.is_valid()) {
8703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Immediate shift.
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
8733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Register shift.
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc));
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= x.rs_.code()*B8 | x.shift_op_ | B4 | x.rm_.code();
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(instr | rn.code()*B16 | rd.code()*B12);
87850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  if (rn.is(pc) || x.rm_.is(pc)) {
8793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Block constant pool emission for one instruction after reading pc.
8803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    BlockConstPoolFor(1);
88150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  }
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod2(Instr instr, Register rd, const MemOperand& x) {
8861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT((instr & ~(kCondMask | B | L)) == B26);
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int am = x.am_;
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!x.rm_.is_valid()) {
8893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Immediate offset.
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset_12 = x.offset_;
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (offset_12 < 0) {
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      offset_12 = -offset_12;
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      am ^= U;
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!is_uint12(offset_12)) {
8963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // Immediate offset cannot be encoded, load it first to register ip
8973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // rn (and rd in a load) should never be ip, or will be trashed.
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
8991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      mov(ip, Operand(x.offset_), LeaveCC, Instruction::ConditionField(instr));
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      addrmod2(instr, rd, MemOperand(x.rn_, ip, x.am_));
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(offset_12 >= 0);  // no masking needed
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= offset_12;
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
9063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Register offset (shift_imm_ and shift_op_ are 0) or scaled
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // register offset the constructors make sure than both shift_imm_
9083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // and shift_op_ are initialized.
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!x.rm_.is(pc));
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= B25 | x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod3(Instr instr, Register rd, const MemOperand& x) {
9181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT((instr & ~(kCondMask | L | S6 | H)) == (B4 | B7));
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(x.rn_.is_valid());
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int am = x.am_;
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!x.rm_.is_valid()) {
9223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Immediate offset.
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset_8 = x.offset_;
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (offset_8 < 0) {
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      offset_8 = -offset_8;
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      am ^= U;
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!is_uint8(offset_8)) {
9293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // Immediate offset cannot be encoded, load it first to register ip
9303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // rn (and rd in a load) should never be ip, or will be trashed.
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
9321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      mov(ip, Operand(x.offset_), LeaveCC, Instruction::ConditionField(instr));
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(offset_8 >= 0);  // no masking needed
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= B | (offset_8 >> 4)*B8 | (offset_8 & 0xf);
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (x.shift_imm_ != 0) {
9393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Scaled register offset not supported, load index first
9403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // rn (and rd in a load) should never be ip, or will be trashed.
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    mov(ip, Operand(x.rm_, x.shift_op_, x.shift_imm_), LeaveCC,
9431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        Instruction::ConditionField(instr));
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
9473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Register offset.
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT((am & (P|W)) == P || !x.rm_.is(pc));  // no pc index with writeback
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr |= x.rm_.code();
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod4(Instr instr, Register rn, RegList rl) {
9571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT((instr & ~(kCondMask | P | U | W | L)) == B27);
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(rl != 0);
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!rn.is(pc));
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(instr | rn.code()*B16 | rl);
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod5(Instr instr, CRegister crd, const MemOperand& x) {
9653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Unindexed addressing is not encoded by this function.
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ((B27 | B26),
9671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            (instr & ~(kCondMask | kCoprocessorMask | P | U | N | W | L)));
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(x.rn_.is_valid() && !x.rm_.is_valid());
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int am = x.am_;
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int offset_8 = x.offset_;
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((offset_8 & 3) == 0);  // offset must be an aligned word offset
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  offset_8 >>= 2;
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (offset_8 < 0) {
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    offset_8 = -offset_8;
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    am ^= U;
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint8(offset_8));  // unsigned word offset must fit in a byte
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Post-indexed addressing requires W == 1; different than in addrmod2/3.
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((am & P) == 0)
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    am |= W;
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(offset_8 >= 0);  // no masking needed
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8);
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int target_pos;
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (L->is_bound()) {
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    target_pos = L->pos();
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (L->is_linked()) {
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      target_pos = L->pos();  // L's link
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      target_pos = kEndOfChain;
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    L->link_to(pc_offset());
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Block the emission of the constant pool, since the branch instruction must
10033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // be emitted at the pc offset recorded by the label.
10043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BlockConstPoolFor(1);
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return target_pos - (pc_offset() + kPcLoadDelta);
1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::label_at_put(Label* L, int at_offset) {
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int target_pos;
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (L->is_bound()) {
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    target_pos = L->pos();
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (L->is_linked()) {
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      target_pos = L->pos();  // L's link
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      target_pos = kEndOfChain;
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    L->link_to(at_offset);
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Branch instructions.
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::b(int branch_offset, Condition cond) {
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((branch_offset & 3) == 0);
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm24 = branch_offset >> 2;
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_int24(imm24));
10301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(cond | B27 | B25 | (imm24 & kImm24Mask));
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (cond == al) {
10333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Dead code is a good location to emit the constant pool.
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CheckConstPool(false, false);
10356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bl(int branch_offset, Condition cond) {
1040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  positions_recorder()->WriteRecordedPositions();
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((branch_offset & 3) == 0);
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm24 = branch_offset >> 2;
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_int24(imm24));
10441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(cond | B27 | B25 | B24 | (imm24 & kImm24Mask));
1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::blx(int branch_offset) {  // v5 and above
10493e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  positions_recorder()->WriteRecordedPositions();
1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((branch_offset & 1) == 0);
1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int h = ((branch_offset & 2) >> 1)*B24;
1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm24 = branch_offset >> 2;
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_int24(imm24));
10541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(kSpecialCondition | B27 | B25 | h | (imm24 & kImm24Mask));
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::blx(Register target, Condition cond) {  // v5 and above
10593e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  positions_recorder()->WriteRecordedPositions();
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!target.is(pc));
10611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BLX | target.code());
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bx(Register target, Condition cond) {  // v5 and above, plus v4t
10663e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  positions_recorder()->WriteRecordedPositions();
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!target.is(pc));  // use of pc is actually allowed, but discouraged
10681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BX | target.code());
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Data-processing instructions.
10733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::and_(Register dst, Register src1, const Operand& src2,
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     SBit s, Condition cond) {
10761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | AND | s, src1, dst, src2);
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::eor(Register dst, Register src1, const Operand& src2,
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
10821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | EOR | s, src1, dst, src2);
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::sub(Register dst, Register src1, const Operand& src2,
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
10881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | SUB | s, src1, dst, src2);
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::rsb(Register dst, Register src1, const Operand& src2,
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
10941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | RSB | s, src1, dst, src2);
1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::add(Register dst, Register src1, const Operand& src2,
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
11001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | ADD | s, src1, dst, src2);
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::adc(Register dst, Register src1, const Operand& src2,
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
11061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | ADC | s, src1, dst, src2);
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::sbc(Register dst, Register src1, const Operand& src2,
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
11121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | SBC | s, src1, dst, src2);
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::rsc(Register dst, Register src1, const Operand& src2,
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
11181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | RSC | s, src1, dst, src2);
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::tst(Register src1, const Operand& src2, Condition cond) {
11231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | TST | S, src1, r0, src2);
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::teq(Register src1, const Operand& src2, Condition cond) {
11281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | TEQ | S, src1, r0, src2);
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::cmp(Register src1, const Operand& src2, Condition cond) {
11331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | CMP | S, src1, r0, src2);
11341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
11351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
11361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
11371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Assembler::cmp_raw_immediate(
11381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Register src, int raw_immediate, Condition cond) {
11391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(is_uint12(raw_immediate));
11401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(cond | I | CMP | S | src.code() << 16 | raw_immediate);
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::cmn(Register src1, const Operand& src2, Condition cond) {
11451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | CMN | S, src1, r0, src2);
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::orr(Register dst, Register src1, const Operand& src2,
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
11511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | ORR | s, src1, dst, src2);
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) {
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (dst.is(pc)) {
11573e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    positions_recorder()->WriteRecordedPositions();
1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
11596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Don't allow nop instructions in the form mov rn, rn to be generated using
11608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // the mov instruction. They must be generated using nop(int/NopMarkerTypes)
11618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // or MarkCode(int/NopMarkerTypes) pseudo instructions.
11626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al));
11631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | MOV | s, r0, dst, src);
1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid Assembler::movw(Register reg, uint32_t immediate, Condition cond) {
11689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ASSERT(immediate < 0x10000);
11699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  mov(reg, Operand(immediate), LeaveCC, cond);
11709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
11719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
11729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
11739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid Assembler::movt(Register reg, uint32_t immediate, Condition cond) {
11749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  emit(cond | 0x34*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate));
11759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
11769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
11779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bic(Register dst, Register src1, const Operand& src2,
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
11801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | BIC | s, src1, dst, src2);
1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) {
11851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  addrmod1(cond | MVN | s, r0, dst, src);
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Multiply instructions.
1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mla(Register dst, Register src1, Register src2, Register srcA,
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | A | s | dst.code()*B16 | srcA.code()*B12 |
1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       src2.code()*B8 | B7 | B4 | src1.code());
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mul(Register dst, Register src1, Register src2,
1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    SBit s, Condition cond) {
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // dst goes in bits 16-19 for this instruction!
1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | s | dst.code()*B16 | src2.code()*B8 | B7 | B4 | src1.code());
1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::smlal(Register dstL,
1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register dstH,
1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src1,
1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src2,
1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      SBit s,
1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Condition cond) {
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(dstH));
1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B23 | B22 | A | s | dstH.code()*B16 | dstL.code()*B12 |
1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       src2.code()*B8 | B7 | B4 | src1.code());
1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::smull(Register dstL,
1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register dstH,
1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src1,
1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src2,
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      SBit s,
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Condition cond) {
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(dstH));
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 |
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       src2.code()*B8 | B7 | B4 | src1.code());
1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::umlal(Register dstL,
1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register dstH,
1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src1,
1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src2,
1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      SBit s,
1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Condition cond) {
1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(dstH));
1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B23 | A | s | dstH.code()*B16 | dstL.code()*B12 |
1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       src2.code()*B8 | B7 | B4 | src1.code());
1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::umull(Register dstL,
1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register dstH,
1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src1,
1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register src2,
1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      SBit s,
1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Condition cond) {
1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dstL.is(dstH));
1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B23 | s | dstH.code()*B16 | dstL.code()*B12 |
1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       src2.code()*B8 | B7 | B4 | src1.code());
1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Miscellaneous arithmetic instructions.
1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::clz(Register dst, Register src, Condition cond) {
1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // v5 and above.
1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(pc) && !src.is(pc));
1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B24 | B22 | B21 | 15*B16 | dst.code()*B12 |
12631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block       15*B8 | CLZ | src.code());
1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
126750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen// Saturating instructions.
126850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
126950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen// Unsigned saturate.
127050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsenvoid Assembler::usat(Register dst,
127150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen                     int satpos,
127250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen                     const Operand& src,
127350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen                     Condition cond) {
127450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  // v6 and above.
12758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsSupported(ARMv7));
127650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  ASSERT(!dst.is(pc) && !src.rm_.is(pc));
127750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  ASSERT((satpos >= 0) && (satpos <= 31));
127850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  ASSERT((src.shift_op_ == ASR) || (src.shift_op_ == LSL));
127950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  ASSERT(src.rs_.is(no_reg));
128050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
128150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  int sh = 0;
128250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  if (src.shift_op_ == ASR) {
128350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen      sh = 1;
128450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  }
128550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
128650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  emit(cond | 0x6*B24 | 0xe*B20 | satpos*B16 | dst.code()*B12 |
128750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen       src.shift_imm_*B7 | sh*B6 | 0x1*B4 | src.rm_.code());
128850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen}
128950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
129050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
12917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Bitfield manipulation instructions.
12927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Unsigned bit field extract.
12947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Extracts #width adjacent bits from position #lsb in a register, and
12957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// writes them to the low bits of a destination register.
12967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch//   ubfx dst, src, #lsb, #width
12977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid Assembler::ubfx(Register dst,
12987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     Register src,
12997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     int lsb,
13007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     int width,
13017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     Condition cond) {
13027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // v7 and above.
13038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsSupported(ARMv7));
13047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(!dst.is(pc) && !src.is(pc));
13057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((lsb >= 0) && (lsb <= 31));
13067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((width >= 1) && (width <= (32 - lsb)));
13077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  emit(cond | 0xf*B23 | B22 | B21 | (width - 1)*B16 | dst.code()*B12 |
13087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch       lsb*B7 | B6 | B4 | src.code());
13097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
13107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Signed bit field extract.
13137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Extracts #width adjacent bits from position #lsb in a register, and
13147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// writes them to the low bits of a destination register. The extracted
13157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// value is sign extended to fill the destination register.
13167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch//   sbfx dst, src, #lsb, #width
13177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid Assembler::sbfx(Register dst,
13187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     Register src,
13197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     int lsb,
13207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     int width,
13217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                     Condition cond) {
13227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // v7 and above.
13238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsSupported(ARMv7));
13247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(!dst.is(pc) && !src.is(pc));
13257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((lsb >= 0) && (lsb <= 31));
13267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((width >= 1) && (width <= (32 - lsb)));
13277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  emit(cond | 0xf*B23 | B21 | (width - 1)*B16 | dst.code()*B12 |
13287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch       lsb*B7 | B6 | B4 | src.code());
13297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
13307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Bit field clear.
13337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Sets #width adjacent bits at position #lsb in the destination register
13347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// to zero, preserving the value of the other bits.
13357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch//   bfc dst, #lsb, #width
13367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid Assembler::bfc(Register dst, int lsb, int width, Condition cond) {
13377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // v7 and above.
13388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsSupported(ARMv7));
13397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(!dst.is(pc));
13407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((lsb >= 0) && (lsb <= 31));
13417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((width >= 1) && (width <= (32 - lsb)));
13427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  int msb = lsb + width - 1;
13437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 | 0xf);
13447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
13457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Bit field insert.
13487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Inserts #width adjacent bits from the low bits of the source register
13497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// into position #lsb of the destination register.
13507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch//   bfi dst, src, #lsb, #width
13517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid Assembler::bfi(Register dst,
13527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    Register src,
13537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    int lsb,
13547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    int width,
13557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    Condition cond) {
13567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // v7 and above.
13578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsSupported(ARMv7));
13587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(!dst.is(pc) && !src.is(pc));
13597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((lsb >= 0) && (lsb <= 31));
13607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((width >= 1) && (width <= (32 - lsb)));
13617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  int msb = lsb + width - 1;
13627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 |
13637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch       src.code());
13647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
13657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Status register access instructions.
1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mrs(Register dst, SRegister s, Condition cond) {
1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!dst.is(pc));
1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B24 | s | 15*B16 | dst.code()*B12);
1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::msr(SRegisterFieldMask fields, const Operand& src,
1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(fields >= B16 && fields < B20);  // at least one field set
1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Instr instr;
1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!src.rm_.is_valid()) {
13793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Immediate.
1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t rotate_imm;
1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t immed_8;
13823e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    if (src.must_use_constant_pool() ||
1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) {
13843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      // Immediate operand cannot be encoded, load it first to register ip.
1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      RecordRelocInfo(src.rmode_, src.imm32_);
1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ldr(ip, MemOperand(pc, 0), cond);
1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      msr(fields, Operand(ip), cond);
1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr = I | rotate_imm*B8 | immed_8;
1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!src.rs_.is_valid() && src.shift_imm_ == 0);  // only rm allowed
1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instr = src.rm_.code();
1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | instr | B24 | B21 | fields | 15*B12);
1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Load/Store instructions.
1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (dst.is(pc)) {
14023e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    positions_recorder()->WriteRecordedPositions();
1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod2(cond | B26 | L, dst, src);
1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::str(Register src, const MemOperand& dst, Condition cond) {
1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod2(cond | B26, src, dst);
1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) {
1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod2(cond | B26 | B | L, dst, src);
1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::strb(Register src, const MemOperand& dst, Condition cond) {
1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod2(cond | B26 | B, src, dst);
1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) {
1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod3(cond | L | B7 | H | B4, dst, src);
1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::strh(Register src, const MemOperand& dst, Condition cond) {
1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod3(cond | B7 | H | B4, src, dst);
1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) {
1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod3(cond | L | B7 | S6 | B4, dst, src);
1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) {
1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod3(cond | L | B7 | S6 | H | B4, dst, src);
1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1443f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid Assembler::ldrd(Register dst1, Register dst2,
1444f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                     const MemOperand& src, Condition cond) {
14458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(ARMv7));
144625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  ASSERT(src.rm().is(no_reg));
1447f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(!dst1.is(lr));  // r14.
1448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(0, dst1.code() % 2);
1449f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(dst1.code() + 1, dst2.code());
1450f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  addrmod3(cond | B7 | B6 | B4, dst1, src);
145125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}
145225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
145325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1454f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid Assembler::strd(Register src1, Register src2,
1455f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                     const MemOperand& dst, Condition cond) {
145625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  ASSERT(dst.rm().is(no_reg));
1457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT(!src1.is(lr));  // r14.
1458f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(0, src1.code() % 2);
1459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ASSERT_EQ(src1.code() + 1, src2.code());
14608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(ARMv7));
1461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  addrmod3(cond | B7 | B6 | B5 | B4, src1, dst);
146225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}
146325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
14643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Load/Store multiple instructions.
1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldm(BlockAddrMode am,
1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register base,
1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    RegList dst,
1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
14693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // ABI stack constraint: ldmxx base, {..sp..}  base != sp  is not restartable.
1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(base.is(sp) || (dst & sp.bit()) == 0);
1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod4(cond | B27 | am | L, base, dst);
1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Emit the constant pool after a function return implemented by ldm ..{..pc}.
1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (cond == al && (dst & pc.bit()) != 0) {
1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // There is a slight chance that the ldm instruction was actually a call,
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // in which case it would be wrong to return into the constant pool; we
1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // recognize this case by checking if the emission of the pool was blocked
1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // at the pc of the ldm instruction by a mov lr, pc instruction; if this is
1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // the case, we emit a jump over the pool.
1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CheckConstPool(true, no_const_pool_before_ == pc_offset() - kInstrSize);
1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::stm(BlockAddrMode am,
1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register base,
1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    RegList src,
1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod4(cond | B27 | am, base, src);
1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Exception-generating instructions and debugging support.
14953e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu// Stops with a non-negative code less than kNumOfWatchedStops support
14963e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu// enabling/disabling and a counter feature. See simulator-arm.h .
14973e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhuvoid Assembler::stop(const char* msg, Condition cond, int32_t code) {
1498402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#ifndef __arm__
14993e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(code >= kDefaultStopCode);
15003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  {
15013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // The Simulator will handle the stop instruction and get the message
15023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // address. It expects to find the address just after the svc instruction.
15033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    BlockConstPoolScope block_const_pool(this);
15043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (code >= 0) {
15053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      svc(kStopCode + code, cond);
15063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
15073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      svc(kStopCode + kMaxStopCode, cond);
15083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
15093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    emit(reinterpret_cast<Instr>(msg));
15103e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  }
1511402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#else  // def __arm__
1512402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#ifdef CAN_USE_ARMV5_INSTRUCTIONS
15131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (cond != al) {
15141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Label skip;
15151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    b(&skip, NegateCondition(cond));
15161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    bkpt(0);
15171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    bind(&skip);
15181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
15191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    bkpt(0);
15201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1521402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#else  // ndef CAN_USE_ARMV5_INSTRUCTIONS
1522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  svc(0x9f0001, cond);
1523402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#endif  // ndef CAN_USE_ARMV5_INSTRUCTIONS
1524402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#endif  // def __arm__
1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bkpt(uint32_t imm16) {  // v5 and above
1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint16(imm16));
15301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(al | B24 | B21 | (imm16 >> 4)*B8 | BKPT | (imm16 & 0xf));
1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15343e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhuvoid Assembler::svc(uint32_t imm24, Condition cond) {
1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint24(imm24));
1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | 15*B24 | imm24);
1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Coprocessor instructions.
1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::cdp(Coprocessor coproc,
1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_1,
1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crd,
1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crn,
1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crm,
1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_2,
1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint4(opcode_1) && is_uint3(opcode_2));
1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B27 | B26 | B25 | (opcode_1 & 15)*B20 | crn.code()*B16 |
1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       crd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | crm.code());
1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::cdp2(Coprocessor coproc,
1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int opcode_1,
1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crd,
1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crn,
1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crm,
1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int opcode_2) {  // v5 and above
15601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  cdp(coproc, opcode_1, crd, crn, crm, opcode_2, kSpecialCondition);
1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mcr(Coprocessor coproc,
1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_1,
1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register rd,
1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crn,
1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crm,
1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_2,
1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2));
1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | crn.code()*B16 |
1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mcr2(Coprocessor coproc,
1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int opcode_1,
1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     Register rd,
1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crn,
1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crm,
1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int opcode_2) {  // v5 and above
15831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  mcr(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition);
1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mrc(Coprocessor coproc,
1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_1,
1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register rd,
1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crn,
1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crm,
1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int opcode_2,
1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2));
1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | L | crn.code()*B16 |
1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mrc2(Coprocessor coproc,
1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int opcode_1,
1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     Register rd,
1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crn,
1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crm,
1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int opcode_2) {  // v5 and above
16061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  mrc(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition);
1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldc(Coprocessor coproc,
1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crd,
1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    const MemOperand& src,
1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    LFlag l,
1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  addrmod5(cond | B27 | B26 | l | L | coproc*B8, crd, src);
1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldc(Coprocessor coproc,
1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    CRegister crd,
1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Register rn,
1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int option,
1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    LFlag l,
1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Condition cond) {
16253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Unindexed addressing.
1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_uint8(option));
1627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(cond | B27 | B26 | U | l | L | rn.code()*B16 | crd.code()*B12 |
1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       coproc*B8 | (option & 255));
1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldc2(Coprocessor coproc,
1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crd,
1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     const MemOperand& src,
1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     LFlag l) {  // v5 and above
16361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ldc(coproc, crd, src, l, kSpecialCondition);
1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldc2(Coprocessor coproc,
1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     CRegister crd,
1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     Register rn,
1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int option,
1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     LFlag l) {  // v5 and above
16451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ldc(coproc, crd, rn, option, l, kSpecialCondition);
1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1649d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Support for VFP.
165080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1651d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Assembler::vldr(const DwVfpRegister dst,
1652d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                     const Register base,
1653d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                     int offset,
1654d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                     const Condition cond) {
1655d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Ddst = MEM(Rbase + offset).
1656d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Instruction details available in ARM DDI 0406A, A8-628.
1657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) |
1658d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Vdst(15-12) | 1011(11-8) | offset
16598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
1660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int u = 1;
1661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (offset < 0) {
1662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    offset = -offset;
1663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    u = 0;
1664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1665e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1666756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ASSERT(offset >= 0);
1667e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((offset % 4) == 0 && (offset / 4) < 256) {
1668e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    emit(cond | u*B23 | 0xD1*B20 | base.code()*B16 | dst.code()*B12 |
1669e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         0xB*B8 | ((offset / 4) & 255));
1670e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
1671e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Larger offsets must be handled by computing the correct address
1672e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // in the ip register.
1673e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(!base.is(ip));
1674e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (u == 1) {
1675e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      add(ip, base, Operand(offset));
1676e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
1677e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      sub(ip, base, Operand(offset));
1678e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1679e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    emit(cond | 0xD1*B20 | ip.code()*B16 | dst.code()*B12 | 0xB*B8);
1680e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1681e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1682e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1683e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1684e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid Assembler::vldr(const DwVfpRegister dst,
1685e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const MemOperand& operand,
1686e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const Condition cond) {
1687e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(!operand.rm().is_valid());
1688e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(operand.am_ == Offset);
1689e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  vldr(dst, operand.rn(), operand.offset(), cond);
1690d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1691d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1692d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
16936ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vldr(const SwVfpRegister dst,
16946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     const Register base,
16956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     int offset,
16966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     const Condition cond) {
16976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Sdst = MEM(Rbase + offset).
16986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Instruction details available in ARM DDI 0406A, A8-628.
1699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) |
17006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Vdst(15-12) | 1010(11-8) | offset
17018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
1702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int u = 1;
1703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (offset < 0) {
1704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    offset = -offset;
1705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    u = 0;
1706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
170780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int sd, d;
170880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  dst.split_code(&sd, &d);
1709e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(offset >= 0);
1710e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1711e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((offset % 4) == 0 && (offset / 4) < 256) {
1712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  emit(cond | u*B23 | d*B22 | 0xD1*B20 | base.code()*B16 | sd*B12 |
17136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block       0xA*B8 | ((offset / 4) & 255));
1714e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
1715e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Larger offsets must be handled by computing the correct address
1716e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // in the ip register.
1717e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(!base.is(ip));
1718e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (u == 1) {
1719e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      add(ip, base, Operand(offset));
1720e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
1721e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      sub(ip, base, Operand(offset));
1722e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1723e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    emit(cond | d*B22 | 0xD1*B20 | ip.code()*B16 | sd*B12 | 0xA*B8);
1724e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1725e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1726e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1727e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1728e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid Assembler::vldr(const SwVfpRegister dst,
1729e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const MemOperand& operand,
1730e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const Condition cond) {
1731e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(!operand.rm().is_valid());
1732e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(operand.am_ == Offset);
1733e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  vldr(dst, operand.rn(), operand.offset(), cond);
17346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
17356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1737d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Assembler::vstr(const DwVfpRegister src,
1738d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                     const Register base,
1739d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                     int offset,
1740d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                     const Condition cond) {
1741d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // MEM(Rbase + offset) = Dsrc.
1742d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Instruction details available in ARM DDI 0406A, A8-786.
1743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // cond(31-28) | 1101(27-24)| U000(23-20) | | Rbase(19-16) |
1744d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Vsrc(15-12) | 1011(11-8) | (offset/4)
17458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
1746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int u = 1;
1747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (offset < 0) {
1748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    offset = -offset;
1749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    u = 0;
1750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1751756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ASSERT(offset >= 0);
1752e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((offset % 4) == 0 && (offset / 4) < 256) {
1753e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    emit(cond | u*B23 | 0xD0*B20 | base.code()*B16 | src.code()*B12 |
1754e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         0xB*B8 | ((offset / 4) & 255));
1755e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
1756e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Larger offsets must be handled by computing the correct address
1757e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // in the ip register.
1758e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(!base.is(ip));
1759e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (u == 1) {
1760e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      add(ip, base, Operand(offset));
1761e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
1762e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      sub(ip, base, Operand(offset));
1763e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1764e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    emit(cond | 0xD0*B20 | ip.code()*B16 | src.code()*B12 | 0xB*B8);
1765e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1766e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1767e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1768e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1769e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid Assembler::vstr(const DwVfpRegister src,
1770e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const MemOperand& operand,
1771e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const Condition cond) {
1772e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(!operand.rm().is_valid());
1773e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(operand.am_ == Offset);
1774e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  vstr(src, operand.rn(), operand.offset(), cond);
1775d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1776d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1777d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1778756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid Assembler::vstr(const SwVfpRegister src,
1779756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                     const Register base,
1780756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                     int offset,
1781756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                     const Condition cond) {
1782756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // MEM(Rbase + offset) = SSrc.
1783756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Instruction details available in ARM DDI 0406A, A8-786.
1784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // cond(31-28) | 1101(27-24)| U000(23-20) | Rbase(19-16) |
1785756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Vdst(15-12) | 1010(11-8) | (offset/4)
17868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
1787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int u = 1;
1788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (offset < 0) {
1789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    offset = -offset;
1790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    u = 0;
1791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
179280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int sd, d;
179380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  src.split_code(&sd, &d);
1794e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(offset >= 0);
1795e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((offset % 4) == 0 && (offset / 4) < 256) {
1796e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    emit(cond | u*B23 | d*B22 | 0xD0*B20 | base.code()*B16 | sd*B12 |
1797e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         0xA*B8 | ((offset / 4) & 255));
1798e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
1799e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Larger offsets must be handled by computing the correct address
1800e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // in the ip register.
1801e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(!base.is(ip));
1802e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (u == 1) {
1803e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      add(ip, base, Operand(offset));
1804e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
1805e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      sub(ip, base, Operand(offset));
1806e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1807e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    emit(cond | d*B22 | 0xD0*B20 | ip.code()*B16 | sd*B12 | 0xA*B8);
1808e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1809e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1810e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1811e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1812e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid Assembler::vstr(const SwVfpRegister src,
1813e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const MemOperand& operand,
1814e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     const Condition cond) {
1815e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(!operand.rm().is_valid());
1816e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(operand.am_ == Offset);
1817e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  vldr(src, operand.rn(), operand.offset(), cond);
1818756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
1819756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1820756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
18218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid  Assembler::vldm(BlockAddrMode am,
18228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      Register base,
18238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      DwVfpRegister first,
18248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      DwVfpRegister last,
18258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      Condition cond) {
18268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Instruction details available in ARM DDI 0406A, A8-626.
18278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
18288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // first(15-12) | 1010(11-8) | (count * 2)
18298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
18308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT_LE(first.code(), last.code());
18318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(am == ia || am == ia_w || am == db_w);
18328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!base.is(pc));
18338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
18348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int sd, d;
18358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  first.split_code(&sd, &d);
18368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int count = last.code() - first.code() + 1;
18378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 |
18388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch       0xB*B8 | count*2);
18398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
18408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
18418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
18428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid  Assembler::vstm(BlockAddrMode am,
18438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      Register base,
18448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      DwVfpRegister first,
18458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      DwVfpRegister last,
18468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      Condition cond) {
18478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Instruction details available in ARM DDI 0406A, A8-784.
18488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
18498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // first(15-12) | 1011(11-8) | (count * 2)
18508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
18518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT_LE(first.code(), last.code());
18528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(am == ia || am == ia_w || am == db_w);
18538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!base.is(pc));
18548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
18558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int sd, d;
18568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  first.split_code(&sd, &d);
18578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int count = last.code() - first.code() + 1;
18588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 |
18598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch       0xB*B8 | count*2);
18608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
18618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
18628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid  Assembler::vldm(BlockAddrMode am,
18638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      Register base,
18648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      SwVfpRegister first,
18658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      SwVfpRegister last,
18668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      Condition cond) {
18678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Instruction details available in ARM DDI 0406A, A8-626.
18688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
18698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // first(15-12) | 1010(11-8) | (count/2)
18708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
18718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT_LE(first.code(), last.code());
18728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(am == ia || am == ia_w || am == db_w);
18738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!base.is(pc));
18748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
18758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int sd, d;
18768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  first.split_code(&sd, &d);
18778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int count = last.code() - first.code() + 1;
18788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 |
18798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch       0xA*B8 | count);
18808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
18818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
18828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
18838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid  Assembler::vstm(BlockAddrMode am,
18848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      Register base,
18858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      SwVfpRegister first,
18868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      SwVfpRegister last,
18878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      Condition cond) {
18888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Instruction details available in ARM DDI 0406A, A8-784.
18898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
18908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // first(15-12) | 1011(11-8) | (count/2)
18918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
18928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT_LE(first.code(), last.code());
18938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(am == ia || am == ia_w || am == db_w);
18948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!base.is(pc));
18958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
18968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int sd, d;
18978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  first.split_code(&sd, &d);
18988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int count = last.code() - first.code() + 1;
18998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 |
19008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch       0xA*B8 | count);
19018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
19028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
19033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochstatic void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) {
19043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  uint64_t i;
19053bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  memcpy(&i, &d, 8);
19063bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19073bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  *lo = i & 0xffffffff;
19083bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  *hi = i >> 32;
19093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
19103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Only works for little endian floating point formats.
19123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// We don't support VFP on the mixed endian floating point platform.
19133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochstatic bool FitsVMOVDoubleImmediate(double d, uint32_t *encoding) {
19148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
19153bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // VMOV can accept an immediate of the form:
19173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
19183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //  +/- m * 2^(-n) where 16 <= m <= 31 and 0 <= n <= 7
19193bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
19203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // The immediate is encoded using an 8-bit quantity, comprised of two
19213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // 4-bit fields. For an 8-bit immediate of the form:
19223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
19233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //  [abcdefgh]
19243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
19253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // where a is the MSB and h is the LSB, an immediate 64-bit double can be
19263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // created of the form:
19273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
19283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //  [aBbbbbbb,bbcdefgh,00000000,00000000,
19293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //      00000000,00000000,00000000,00000000]
19303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
19313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // where B = ~b.
19323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //
19333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  uint32_t lo, hi;
19353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  DoubleAsTwoUInt32(d, &lo, &hi);
19363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // The most obvious constraint is the long block of zeroes.
19383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if ((lo != 0) || ((hi & 0xffff) != 0)) {
19393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    return false;
19403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
19413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Bits 62:55 must be all clear or all set.
19433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (((hi & 0x3fc00000) != 0) && ((hi & 0x3fc00000) != 0x3fc00000)) {
19443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    return false;
19453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
19463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Bit 63 must be NOT bit 62.
19483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (((hi ^ (hi << 1)) & (0x40000000)) == 0) {
19493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    return false;
19503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
19513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Create the encoded immediate in the form:
19533bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  //  [00000000,0000abcd,00000000,0000efgh]
19543bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  *encoding  = (hi >> 16) & 0xf;      // Low nybble.
19553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  *encoding |= (hi >> 4) & 0x70000;   // Low three bits of the high nybble.
19563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  *encoding |= (hi >> 12) & 0x80000;  // Top bit of the high nybble.
19573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  return true;
19593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
19603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19613bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19623bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid Assembler::vmov(const DwVfpRegister dst,
19633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                     double imm,
19643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                     const Condition cond) {
19653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Dd = immediate
19663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Instruction details available in ARM DDI 0406B, A8-640.
19678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
19683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  uint32_t enc;
19703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (FitsVMOVDoubleImmediate(imm, &enc)) {
19713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // The double can be encoded in the instruction.
19723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 | 0xB*B8 | enc);
19733bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  } else {
19743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // Synthesise the double from ARM immediates. This could be implemented
19753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // using vldr from a constant pool.
19763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    uint32_t lo, hi;
19773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    DoubleAsTwoUInt32(imm, &lo, &hi);
19783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    if (lo == hi) {
19803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // If the lo and hi parts of the double are equal, the literal is easier
19813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // to create. This is the case with 0.0.
19823bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      mov(ip, Operand(lo));
19833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      vmov(dst, ip, ip);
19843bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    } else {
19853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // Move the low part of the double into the lower of the corresponsing S
19863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // registers of D register dst.
19873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      mov(ip, Operand(lo));
19883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      vmov(dst.low(), ip, cond);
19893bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // Move the high part of the double into the higher of the corresponsing S
19913bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // registers of D register dst.
19923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      mov(ip, Operand(hi));
19933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      vmov(dst.high(), ip, cond);
19943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    }
19953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
19963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
19973bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
19993bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid Assembler::vmov(const SwVfpRegister dst,
20003bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                     const SwVfpRegister src,
20013bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                     const Condition cond) {
20023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Sd = Sm
20033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Instruction details available in ARM DDI 0406B, A8-642.
20048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
200580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int sd, d, sm, m;
200680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  dst.split_code(&sd, &d);
200780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  src.split_code(&sm, &m);
200880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  emit(cond | 0xE*B24 | d*B22 | 0xB*B20 | sd*B12 | 0xA*B8 | B6 | m*B5 | sm);
20093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
20103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
20113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
2012e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vmov(const DwVfpRegister dst,
20138defd9ff6930b4e24729971a61cf7469daf119beSteve Block                     const DwVfpRegister src,
20148defd9ff6930b4e24729971a61cf7469daf119beSteve Block                     const Condition cond) {
20158defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Dd = Dm
20168defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Instruction details available in ARM DDI 0406B, A8-642.
20178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
20188defd9ff6930b4e24729971a61cf7469daf119beSteve Block  emit(cond | 0xE*B24 | 0xB*B20 |
20198defd9ff6930b4e24729971a61cf7469daf119beSteve Block       dst.code()*B12 | 0x5*B9 | B8 | B6 | src.code());
20208defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
20218defd9ff6930b4e24729971a61cf7469daf119beSteve Block
20228defd9ff6930b4e24729971a61cf7469daf119beSteve Block
20238defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid Assembler::vmov(const DwVfpRegister dst,
2024e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Register src1,
2025e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Register src2,
2026e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Condition cond) {
2027d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dm = <Rt,Rt2>.
2028d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-646.
2029d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) |
2030d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
20318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2032d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(!src1.is(pc) && !src2.is(pc));
2033d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xC*B24 | B22 | src2.code()*B16 |
2034d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       src1.code()*B12 | 0xB*B8 | B4 | dst.code());
2035d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2036d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2037d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2038e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vmov(const Register dst1,
2039e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Register dst2,
2040e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src,
2041e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Condition cond) {
2042d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // <Rt,Rt2> = Dm.
2043d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-646.
2044d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) |
2045d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
20468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2047d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(!dst1.is(pc) && !dst2.is(pc));
2048d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 |
2049d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       dst1.code()*B12 | 0xB*B8 | B4 | src.code());
2050d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2051d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2052d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2053e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vmov(const SwVfpRegister dst,
2054d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const Register src,
2055d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const Condition cond) {
2056d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Sn = Rt.
2057d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-642.
2058d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) |
2059d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
20608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2061d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(!src.is(pc));
206280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int sn, n;
206380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  dst.split_code(&sn, &n);
206480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  emit(cond | 0xE*B24 | sn*B16 | src.code()*B12 | 0xA*B8 | n*B7 | B4);
2065d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2066d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2067d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2068e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vmov(const Register dst,
2069e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const SwVfpRegister src,
2070d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const Condition cond) {
2071d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt = Sn.
2072d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-642.
2073d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) |
2074d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
20758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2076d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(!dst.is(pc));
207780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int sn, n;
207880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  src.split_code(&sn, &n);
207980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  emit(cond | 0xE*B24 | B20 | sn*B16 | dst.code()*B12 | 0xA*B8 | n*B7 | B4);
2080d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2081d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2082d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
20836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Type of data to read from or write to VFP register.
20846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Used as specifier in generic vcvt instruction.
20856ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockenum VFPType { S32, U32, F32, F64 };
20866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20886ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool IsSignedVFPType(VFPType type) {
20896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  switch (type) {
20906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case S32:
20916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return true;
20926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case U32:
20936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
20946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    default:
20956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      UNREACHABLE();
20966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
20976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
20986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
20996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21016ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool IsIntegerVFPType(VFPType type) {
21026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  switch (type) {
21036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case S32:
21046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case U32:
21056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return true;
21066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case F32:
21076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case F64:
21086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
21096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    default:
21106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      UNREACHABLE();
21116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
21126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
21136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
21146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21166ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool IsDoubleVFPType(VFPType type) {
21176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  switch (type) {
21186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case F32:
21196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
21206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case F64:
21216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return true;
21226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    default:
21236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      UNREACHABLE();
21246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
21256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
21266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
21276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
212980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Split five bit reg_code based on size of reg_type.
213080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//  32-bit register codes are Vm:M
213180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen//  64-bit register codes are M:Vm
213280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// where Vm is four bits, and M is a single bit.
213380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenstatic void SplitRegCode(VFPType reg_type,
21346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                         int reg_code,
21356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                         int* vm,
21366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                         int* m) {
213780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT((reg_code >= 0) && (reg_code <= 31));
213880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (IsIntegerVFPType(reg_type) || !IsDoubleVFPType(reg_type)) {
213980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // 32 bit type.
21406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    *m  = reg_code & 0x1;
21416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    *vm = reg_code >> 1;
21426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
214380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // 64 bit type.
21446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    *m  = (reg_code & 0x10) >> 4;
21456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    *vm = reg_code & 0x0F;
21466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
21476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
21486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Encode vcvt.src_type.dst_type instruction.
21516ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Instr EncodeVCVT(const VFPType dst_type,
21526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        const int dst_code,
21536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        const VFPType src_type,
21546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        const int src_code,
21551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                        VFPConversionMode mode,
21566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        const Condition cond) {
215780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(src_type != dst_type);
215880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int D, Vd, M, Vm;
215980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SplitRegCode(src_type, src_code, &Vm, &M);
216080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SplitRegCode(dst_type, dst_code, &Vd, &D);
216180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
21626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (IsIntegerVFPType(dst_type) || IsIntegerVFPType(src_type)) {
21636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Conversion between IEEE floating point and 32-bit integer.
21646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Instruction details available in ARM DDI 0406B, A8.6.295.
21656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 1(19) | opc2(18-16) |
21666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Vd(15-12) | 101(11-9) | sz(8) | op(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
21676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!IsIntegerVFPType(dst_type) || !IsIntegerVFPType(src_type));
21686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
216980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    int sz, opc2, op;
21706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (IsIntegerVFPType(dst_type)) {
21726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      opc2 = IsSignedVFPType(dst_type) ? 0x5 : 0x4;
21736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
217490bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner      op = mode;
21756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
21766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ASSERT(IsIntegerVFPType(src_type));
21776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      opc2 = 0x0;
21786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      sz = IsDoubleVFPType(dst_type) ? 0x1 : 0x0;
21796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      op = IsSignedVFPType(src_type) ? 0x1 : 0x0;
21806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
21816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | B19 | opc2*B16 |
21836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            Vd*B12 | 0x5*B9 | sz*B8 | op*B7 | B6 | M*B5 | Vm);
21846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
21856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Conversion between IEEE double and single precision.
21866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Instruction details available in ARM DDI 0406B, A8.6.298.
21876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0111(19-16) |
21886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Vd(15-12) | 101(11-9) | sz(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
218980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    int sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
21906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | 0x7*B16 |
21916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            Vd*B12 | 0x5*B9 | sz*B8 | B7 | B6 | M*B5 | Vm);
21926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
21936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
21946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21966ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_f64_s32(const DwVfpRegister dst,
21976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const SwVfpRegister src,
21981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
21996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
22008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
220190bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(F64, dst.code(), S32, src.code(), mode, cond));
2202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
22056ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_f32_s32(const SwVfpRegister dst,
22066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const SwVfpRegister src,
22071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
22086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
22098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
221090bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(F32, dst.code(), S32, src.code(), mode, cond));
22116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
22126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
22136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
22146ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_f64_u32(const DwVfpRegister dst,
22156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const SwVfpRegister src,
22161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
22176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
22188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
221990bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(F64, dst.code(), U32, src.code(), mode, cond));
22206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
22216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
22226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
22236ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_s32_f64(const SwVfpRegister dst,
22246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const DwVfpRegister src,
22251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
22266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
22278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
222890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(S32, dst.code(), F64, src.code(), mode, cond));
22296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
22306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
22316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
22326ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_u32_f64(const SwVfpRegister dst,
22336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const DwVfpRegister src,
22341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
22356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
22368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
223790bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(U32, dst.code(), F64, src.code(), mode, cond));
22386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
22396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
22406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
22416ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_f64_f32(const DwVfpRegister dst,
22426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const SwVfpRegister src,
22431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
22446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
22458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
224690bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(F64, dst.code(), F32, src.code(), mode, cond));
22476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
22486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
22496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
22506ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::vcvt_f32_f64(const SwVfpRegister dst,
22516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const DwVfpRegister src,
22521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPConversionMode mode,
22536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             const Condition cond) {
22548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
225590bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond));
2256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
225944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Assembler::vneg(const DwVfpRegister dst,
226044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     const DwVfpRegister src,
226144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                     const Condition cond) {
226244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  emit(cond | 0xE*B24 | 0xB*B20 | B16 | dst.code()*B12 |
226344f0eee88ff00398ff7f715fab053374d808c90dSteve Block       0x5*B9 | B8 | B6 | src.code());
226444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
226544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
226644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
22671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Assembler::vabs(const DwVfpRegister dst,
22681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                     const DwVfpRegister src,
22691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                     const Condition cond) {
22701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 |
22711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block       0x5*B9 | B8 | 0x3*B6 | src.code());
22721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
22731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
22741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2275e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vadd(const DwVfpRegister dst,
2276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src1,
2277e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src2,
2278e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Condition cond) {
2279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Dd = vadd(Dn, Dm) double precision floating point addition.
2280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
2281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-536.
2282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) |
2283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0)
22848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 |
2286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       dst.code()*B12 | 0x5*B9 | B8 | src2.code());
2287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2290e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vsub(const DwVfpRegister dst,
2291e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src1,
2292e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src2,
2293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Condition cond) {
2294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Dd = vsub(Dn, Dm) double precision floating point subtraction.
2295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
2296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-784.
2297d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) |
2298d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 1(6) | M=?(5) | 0(4) | Vm(3-0)
22998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2300d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 |
2301d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       dst.code()*B12 | 0x5*B9 | B8 | B6 | src2.code());
2302d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2303d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2304d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vmul(const DwVfpRegister dst,
2306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src1,
2307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src2,
2308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Condition cond) {
2309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Dd = vmul(Dn, Dm) double precision floating point multiplication.
2310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
2311d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-784.
2312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 11100(27-23)| D=?(22) | 10(21-20) | Vn(19-16) |
2313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0)
23148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 | 0x2*B20 | src1.code()*B16 |
2316d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       dst.code()*B12 | 0x5*B9 | B8 | src2.code());
2317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vdiv(const DwVfpRegister dst,
2321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src1,
2322e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src2,
2323e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const Condition cond) {
2324e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Dd = vdiv(Dn, Dm) double precision floating point division.
2325d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
2326d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-584.
2327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 11101(27-23)| D=?(22) | 00(21-20) | Vn(19-16) |
2328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=? | 0(6) | M=?(5) | 0(4) | Vm(3-0)
23298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2330d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 | B23 | src1.code()*B16 |
2331d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       dst.code()*B12 | 0x5*B9 | B8 | src2.code());
2332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2335e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Assembler::vcmp(const DwVfpRegister src1,
2336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                     const DwVfpRegister src2,
2337d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     const Condition cond) {
2338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // vcmp(Dd, Dm) double precision floating point comparison.
2339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-570.
2340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0100 (19-16) |
2341b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=0 | 1(6) | M(5)=? | 0(4) | Vm(3-0)
23428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2343d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 |
2344b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch       src1.code()*B12 | 0x5*B9 | B8 | B6 | src2.code());
2345d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2346d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2347d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2348756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid Assembler::vcmp(const DwVfpRegister src1,
2349756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                     const double src2,
2350756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                     const Condition cond) {
2351756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // vcmp(Dd, Dm) double precision floating point comparison.
2352756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Instruction details available in ARM DDI 0406A, A8-570.
2353756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0101 (19-16) |
2354b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=0 | 1(6) | M(5)=? | 0(4) | 0000(3-0)
23558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2356756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ASSERT(src2 == 0.0);
2357756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 | B16 |
2358b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch       src1.code()*B12 | 0x5*B9 | B8 | B6);
2359756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2360756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2361756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
236290bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brennervoid Assembler::vmsr(Register dst, Condition cond) {
236390bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  // Instruction details available in ARM DDI 0406A, A8-652.
236490bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  // cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) |
236590bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
23668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
236790bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  emit(cond | 0xE*B24 | 0xE*B20 |  B16 |
236890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner       dst.code()*B12 | 0xA*B8 | B4);
236990bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner}
237090bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
237190bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
2372d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::vmrs(Register dst, Condition cond) {
2373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Instruction details available in ARM DDI 0406A, A8-652.
2374d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) |
2375d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
23768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
2377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  emit(cond | 0xE*B24 | 0xF*B20 |  B16 |
2378d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       dst.code()*B12 | 0xA*B8 | B4);
2379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2381d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
23828defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid Assembler::vsqrt(const DwVfpRegister dst,
23838defd9ff6930b4e24729971a61cf7469daf119beSteve Block                      const DwVfpRegister src,
23848defd9ff6930b4e24729971a61cf7469daf119beSteve Block                      const Condition cond) {
23858defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0001 (19-16) |
23868defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Vd(15-12) | 101(11-9) | sz(8)=1 | 11 (7-6) | M(5)=? | 0(4) | Vm(3-0)
23878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(CpuFeatures::IsEnabled(VFP3));
23888defd9ff6930b4e24729971a61cf7469daf119beSteve Block  emit(cond | 0xE*B24 | B23 | 0x3*B20 | B16 |
23898defd9ff6930b4e24729971a61cf7469daf119beSteve Block       dst.code()*B12 | 0x5*B9 | B8 | 3*B6 | src.code());
23908defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
23918defd9ff6930b4e24729971a61cf7469daf119beSteve Block
23928defd9ff6930b4e24729971a61cf7469daf119beSteve Block
23933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Pseudo instructions.
23946ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::nop(int type) {
23956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // This is mov rx, rx.
23966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(0 <= type && type <= 14);  // mov pc, pc is not a nop.
23976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  emit(al | 13*B21 | type*B12 | type);
23986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
23996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
24006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
24018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangbool Assembler::IsNop(Instr instr, int type) {
24021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check for mov rx, rx where x = type.
24038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(0 <= type && type <= 14);  // mov pc, pc is not a nop.
24048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return instr == (al | 13*B21 | type*B12 | type);
24058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
24068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
24078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
2408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockbool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) {
2409d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  uint32_t dummy1;
2410d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  uint32_t dummy2;
2411d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return fits_shifter(imm32, &dummy1, &dummy2, NULL);
2412d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
2413d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2414d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
24153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Debugging.
2416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::RecordJSReturn() {
24173e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  positions_recorder()->WriteRecordedPositions();
2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckBuffer();
2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RecordRelocInfo(RelocInfo::JS_RETURN);
2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid Assembler::RecordDebugBreakSlot() {
24243e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  positions_recorder()->WriteRecordedPositions();
24257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CheckBuffer();
24267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
24277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
24287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::RecordComment(const char* msg) {
2431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_code_comments) {
2432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CheckBuffer();
2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::GrowBuffer() {
2439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!own_buffer_) FATAL("external code buffer is too small");
2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Compute new buffer size.
2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CodeDesc desc;  // the new buffer
2443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (buffer_size_ < 4*KB) {
2444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    desc.buffer_size = 4*KB;
2445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (buffer_size_ < 1*MB) {
2446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    desc.buffer_size = 2*buffer_size_;
2447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    desc.buffer_size = buffer_size_ + 1*MB;
2449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_GT(desc.buffer_size, 0);  // no overflow
2451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up new buffer.
2453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc.buffer = NewArray<byte>(desc.buffer_size);
2454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc.instr_size = pc_offset();
2456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
2457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Copy the data.
2459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int pc_delta = desc.buffer - buffer_;
2460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
2461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  memmove(desc.buffer, buffer_, desc.instr_size);
2462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  memmove(reloc_info_writer.pos() + rc_delta,
2463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          reloc_info_writer.pos(), desc.reloc_size);
2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Switch buffers.
2466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DeleteArray(buffer_);
2467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  buffer_ = desc.buffer;
2468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  buffer_size_ = desc.buffer_size;
2469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pc_ += pc_delta;
2470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               reloc_info_writer.last_pc() + pc_delta);
2472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // None of our relocation types are pc relative pointing outside the code
2474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // buffer nor pc absolute pointing inside the code buffer, so there is no need
24753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // to relocate any emitted relocation entries.
2476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Relocate pending relocation entries.
24783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < num_pending_reloc_info_; i++) {
24793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    RelocInfo& rinfo = pending_reloc_info_[i];
2480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           rinfo.rmode() != RelocInfo::POSITION);
2482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (rinfo.rmode() != RelocInfo::JS_RETURN) {
2483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      rinfo.set_pc(rinfo.pc() + pc_delta);
2484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Assembler::db(uint8_t data) {
2490b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // No relocation info should be pending while using db. db is used
2491b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // to write pure data with no pointers and the constant pool should
2492b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // be emitted before using db.
24933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(num_pending_reloc_info_ == 0);
2494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CheckBuffer();
2495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  *reinterpret_cast<uint8_t*>(pc_) = data;
2496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  pc_ += sizeof(uint8_t);
2497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Assembler::dd(uint32_t data) {
2501b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // No relocation info should be pending while using dd. dd is used
2502b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // to write pure data with no pointers and the constant pool should
2503b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // be emitted before using dd.
25043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(num_pending_reloc_info_ == 0);
2505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CheckBuffer();
2506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  *reinterpret_cast<uint32_t*>(pc_) = data;
2507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  pc_ += sizeof(uint32_t);
2508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
25123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We do not try to reuse pool constants.
25133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RelocInfo rinfo(pc_, rmode, data, NULL);
25147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::DEBUG_BREAK_SLOT) {
25153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Adjust code for new modes.
25167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ASSERT(RelocInfo::IsDebugBreakSlot(rmode)
25177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch           || RelocInfo::IsJSReturn(rmode)
2518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           || RelocInfo::IsComment(rmode)
2519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           || RelocInfo::IsPosition(rmode));
25203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // These modes do not need an entry in the constant pool.
2521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
25223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ASSERT(num_pending_reloc_info_ < kMaxNumPendingRelocInfo);
25233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (num_pending_reloc_info_ == 0) {
25243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      first_const_pool_use_ = pc_offset();
25253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
25263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    pending_reloc_info_[num_pending_reloc_info_++] = rinfo;
2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Make sure the constant pool is not emitted in place of the next
25283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // instruction for which we just recorded relocation info.
25293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    BlockConstPoolFor(1);
2530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (rinfo.rmode() != RelocInfo::NONE) {
2532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Don't record external references unless the heap will be serialized.
2533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
2534d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG
2535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (!Serializer::enabled()) {
2536d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        Serializer::TooLateToEnableNow();
2537d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
2538d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif
253944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (!Serializer::enabled() && !emit_debug_code()) {
2540d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        return;
2541d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
2542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(buffer_space() >= kMaxRelocSize);  // too late to grow buffer here
2544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
25453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RelocInfo reloc_info_with_ast_id(pc_, rmode, RecordedAstId(), NULL);
25463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ClearRecordedAstId();
2547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      reloc_info_writer.Write(&reloc_info_with_ast_id);
2548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
2549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      reloc_info_writer.Write(&rinfo);
2550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
2551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Assembler::BlockConstPoolFor(int instructions) {
25563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int pc_limit = pc_offset() + instructions * kInstrSize;
25573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (no_const_pool_before_ < pc_limit) {
25583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // If there are some pending entries, the constant pool cannot be blocked
25593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // further than first_const_pool_use_ + kMaxDistToPool
25603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ASSERT((num_pending_reloc_info_ == 0) ||
25613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch           (pc_limit < (first_const_pool_use_ + kMaxDistToPool)));
25623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    no_const_pool_before_ = pc_limit;
2563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (next_buffer_check_ < no_const_pool_before_) {
25663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    next_buffer_check_ = no_const_pool_before_;
25673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
25683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
2569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Assembler::CheckConstPool(bool force_emit, bool require_jump) {
25723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Some short sequence of instruction mustn't be broken up by constant pool
25733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // emission, such sequences are protected by calls to BlockConstPoolFor and
25743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // BlockConstPoolScope.
25753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (is_const_pool_blocked()) {
25763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Something is wrong if emission is forced and blocked at the same time.
2577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!force_emit);
2578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
2579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // There is nothing to do if there are no pending constant pool entries.
25823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (num_pending_reloc_info_ == 0)  {
25833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Calculate the offset of the next check.
25843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    next_buffer_check_ = pc_offset() + kCheckPoolInterval;
25853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return;
25863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
25873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
25883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // We emit a constant pool when:
25893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  * requested to do so by parameter force_emit (e.g. after each function).
25903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  * the distance to the first instruction accessing the constant pool is
25913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //    kAvgDistToPool or more.
25923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  * no jump is required and the distance to the first instruction accessing
25933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //    the constant pool is at least kMaxDistToPool / 2.
25943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(first_const_pool_use_ >= 0);
25953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int dist = pc_offset() - first_const_pool_use_;
25963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!force_emit && dist < kAvgDistToPool &&
25973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      (require_jump || (dist < (kMaxDistToPool / 2)))) {
25983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return;
25993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
2600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the code buffer is large enough before emitting the constant
26023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // pool (include the jump over the pool and the constant pool marker and
26033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // the gap to the relocation information).
26043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int jump_instr = require_jump ? kInstrSize : 0;
26053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int needed_space = jump_instr + kInstrSize +
26063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                     num_pending_reloc_info_ * kInstrSize + kGap;
26073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  while (buffer_space() <= needed_space) GrowBuffer();
26083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  {
26103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Block recursive calls to CheckConstPool.
26113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    BlockConstPoolScope block_const_pool(this);
26123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Emit jump over constant pool if necessary.
26143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Label after_pool;
26153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (require_jump) {
26163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      b(&after_pool);
2617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    RecordComment("[ Constant Pool");
26203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Put down constant pool marker "Undefined instruction" as specified by
26223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // A5.6 (ARMv7) Instruction set encoding.
26233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    emit(kConstantPoolMarker | num_pending_reloc_info_);
26243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Emit constant pool entries.
26263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    for (int i = 0; i < num_pending_reloc_info_; i++) {
26273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      RelocInfo& rinfo = pending_reloc_info_[i];
26283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
26293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch             rinfo.rmode() != RelocInfo::POSITION &&
26303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch             rinfo.rmode() != RelocInfo::STATEMENT_POSITION);
26313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Instr instr = instr_at(rinfo.pc());
26333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // Instruction to patch must be 'ldr rd, [pc, #offset]' with offset == 0.
26343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ASSERT(IsLdrPcImmediateOffset(instr) &&
26353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch             GetLdrRegisterImmediateOffset(instr) == 0);
26363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int delta = pc_ - rinfo.pc() - kPcLoadDelta;
26383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // 0 is the smallest delta:
26393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      //   ldr rd, [pc, #0]
26403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      //   constant pool marker
26413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      //   data
26423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ASSERT(is_uint12(delta));
26433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      instr_at_put(rinfo.pc(), SetLdrRegisterImmediateOffset(instr, delta));
26453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      emit(rinfo.data());
26463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    num_pending_reloc_info_ = 0;
26493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    first_const_pool_use_ = -1;
26503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    RecordComment("]");
26523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
26533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (after_pool.is_linked()) {
26543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      bind(&after_pool);
26553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Since a constant pool was just emitted, move the check offset forward by
2659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the standard interval.
26603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  next_buffer_check_ = pc_offset() + kCheckPoolInterval;
2661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
2665f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_ARM
2667