assembler-arm.cc revision f7060e27768c550ace7ec48ad8c093466db52dfa
1a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek// Copyright (c) 1994-2006 Sun Microsystems Inc.
25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// All Rights Reserved.
35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// Redistribution and use in source and binary forms, with or without
50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// modification, are permitted provided that the following conditions
60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// are met:
75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// - Redistributions of source code must retain the above copyright notice,
95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// this list of conditions and the following disclaimer.
105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// - Redistribution in binary form must reproduce the above copyright
125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// notice, this list of conditions and the following disclaimer in the
135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// documentation and/or other materials provided with the
14500d3297d2a21edeac4d46cbcbe21bc2352c2a28Chris Lattner// distribution.
1519510856727e0e14a3696b2a72c35163bff2a71fJohn McCall//
1619510856727e0e14a3696b2a72c35163bff2a71fJohn McCall// - Neither the name of Sun Microsystems or the names of contributors may
1719510856727e0e14a3696b2a72c35163bff2a71fJohn McCall// be used to endorse or promote products derived from this software without
185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// specific prior written permission.
195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22891dca671a80c865c6def7259f170ba785e4faaaChris Lattner// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2591fa0b7759b575045142abd6ee48c076297ad77bSteve Naroff// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2691fa0b7759b575045142abd6ee48c076297ad77bSteve Naroff// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2791fa0b7759b575045142abd6ee48c076297ad77bSteve Naroff// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2891fa0b7759b575045142abd6ee48c076297ad77bSteve Naroff// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2991fa0b7759b575045142abd6ee48c076297ad77bSteve Naroff// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// OF THE POSSIBILITY OF SUCH DAMAGE.
321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
33c464ae8444edb6d07ea49b7a0eae1674c0fa1bb8Douglas Gregor// The original source code covered by the above license above has been
3423c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor// modified significantly by Google Inc.
35dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor// Copyright 2010 the V8 project authors. All rights reserved.
36c464ae8444edb6d07ea49b7a0eae1674c0fa1bb8Douglas Gregor
37c464ae8444edb6d07ea49b7a0eae1674c0fa1bb8Douglas Gregor#include "v8.h"
38861cf3effdc0fbc97d401539bc3050da76b2476fSteve Naroff
395ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner#if defined(V8_TARGET_ARCH_ARM)
405ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner
415ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner#include "arm/assembler-arm-inl.h"
425ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner#include "serialize.h"
435ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner
445ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattnernamespace v8 {
455ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattnernamespace internal {
465ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner
475ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner// Safe default is no features.
485ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattnerunsigned CpuFeatures::supported_ = 0;
495ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattnerunsigned CpuFeatures::enabled_ = 0;
505ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattnerunsigned CpuFeatures::found_by_runtime_probing_ = 0;
515ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner
525ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner
535ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner#ifdef __arm__
545ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattnerstatic uint64_t CpuFeaturesImpliedByCompiler() {
555ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner  uint64_t answer = 0;
565ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner#ifdef CAN_USE_ARMV7_INSTRUCTIONS
575ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner  answer |= 1u << ARMv7;
58d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall#endif  // def CAN_USE_ARMV7_INSTRUCTIONS
595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // If the compiler is allowed to use VFP then we can use VFP too in our code
605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // generation even when generating snapshots.  This won't work for cross
615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // compilation.
625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#if defined(__VFP_FP__) && !defined(__SOFTFP__)
631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  answer |= 1u << VFP3;
645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#endif  // defined(__VFP_FP__) && !defined(__SOFTFP__)
651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump#ifdef CAN_USE_VFP_INSTRUCTIONS
66d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  answer |= 1u << VFP3;
675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#endif  // def CAN_USE_VFP_INSTRUCTIONS
685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  return answer;
69c09cba67d0ad01e53e0fed07322e95dd281bcfd9Ted Kremenek}
70c09cba67d0ad01e53e0fed07322e95dd281bcfd9Ted Kremenek#endif  // def __arm__
711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
73df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattnervoid CpuFeatures::Probe() {
745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#ifndef __arm__
755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // For the simulator=arm build, use VFP when FLAG_enable_vfp3 is enabled.
76d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  if (FLAG_enable_vfp3) {
775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    supported_ |= 1u << VFP3;
785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
79c09cba67d0ad01e53e0fed07322e95dd281bcfd9Ted Kremenek  // For the simulator=arm build, use ARMv7 when FLAG_enable_armv7 is enabled
805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  if (FLAG_enable_armv7) {
811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    supported_ |= 1u << ARMv7;
82df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  }
835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#else  // def __arm__
841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (Serializer::enabled()) {
855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    supported_ |= OS::CpuFeaturesImpliedByPlatform();
865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    supported_ |= CpuFeaturesImpliedByCompiler();
871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    return;  // No features if we might serialize.
885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
90d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  if (OS::ArmCpuHasFeature(VFP3)) {
911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    // This implementation also sets the VFP flags if
92c09cba67d0ad01e53e0fed07322e95dd281bcfd9Ted Kremenek    // runtime detection of VFP returns true.
93c09cba67d0ad01e53e0fed07322e95dd281bcfd9Ted Kremenek    supported_ |= 1u << VFP3;
94c09cba67d0ad01e53e0fed07322e95dd281bcfd9Ted Kremenek    found_by_runtime_probing_ |= 1u << VFP3;
955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
97dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  if (OS::ArmCpuHasFeature(ARMv7)) {
98dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    supported_ |= 1u << ARMv7;
99dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    found_by_runtime_probing_ |= 1u << ARMv7;
100dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  }
101dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff#endif
102dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff}
1031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
104dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
1051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// -----------------------------------------------------------------------------
106dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff// Implementation of RelocInfo
107dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
108dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroffconst int RelocInfo::kApplyMask = 0;
109dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
1101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
111dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroffbool RelocInfo::IsCodedSpecially() {
112dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  // The deserializer needs to know whether a pointer is specially coded.  Being
113dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  // specially coded on ARM means that it is a movw/movt instruction.  We don't
114dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  // generate those yet.
115dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  return false;
116dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff}
117dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
118dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
119dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
120dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroffvoid RelocInfo::PatchCode(byte* instructions, int instruction_count) {
121dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  // Patch the code at the current address with the supplied instructions.
122dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  Instr* pc = reinterpret_cast<Instr*>(pc_);
123dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  Instr* instr = reinterpret_cast<Instr*>(instructions);
124dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  for (int i = 0; i < instruction_count; i++) {
125d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall    *(pc + i) = *(instr + i);
126dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  }
127861cf3effdc0fbc97d401539bc3050da76b2476fSteve Naroff
128dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  // Indicate that code has changed.
129dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  CPU::FlushICache(pc_, instruction_count * Assembler::kInstrSize);
1301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}
1313b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor
1323b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor
13323c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor// Patch the code at the current PC with a call to the target address.
134dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor// Additional guard instructions can be added if required.
1353b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregorvoid RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
1363b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor  // Patch the code at the current address with a call to the target.
137df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  UNIMPLEMENTED();
138dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff}
139d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall
140dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
14163e963cdffca9530f920dbab58b9b4eecb2a582cFariborz Jahanian// -----------------------------------------------------------------------------
142dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff// Implementation of Operand and MemOperand
1437ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff// See assembler-arm-inl.h for inlined constructors
144dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
1455512ba538f3f6b0576623f680fa7d930fa085ccdFariborz JahanianOperand::Operand(Handle<Object> handle) {
1465512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian  rm_ = no_reg;
147dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  // Verify all Objects referred by code are NOT in new space.
148dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  Object* obj = *handle;
149dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  ASSERT(!Heap::InNewSpace(obj));
15033ced0b8550f3e7169f326944731ee02e9338659Douglas Gregor  if (obj->IsHeapObject()) {
15123c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor    imm32_ = reinterpret_cast<intptr_t>(handle.location());
152dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor    rmode_ = RelocInfo::EMBEDDED_OBJECT;
15333ced0b8550f3e7169f326944731ee02e9338659Douglas Gregor  } else {
15433ced0b8550f3e7169f326944731ee02e9338659Douglas Gregor    // no relocation needed
155527fe23f8cbc6a4da1737a547a2517bc92fa88c8Steve Naroff    imm32_ =  reinterpret_cast<intptr_t>(obj);
156df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner    rmode_ = RelocInfo::NONE;
157dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  }
158dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff}
15905511fa6349ef0820a778f8c840d0b64e05e9aeeFariborz Jahanian
16005511fa6349ef0820a778f8c840d0b64e05e9aeeFariborz Jahanian
161527fe23f8cbc6a4da1737a547a2517bc92fa88c8Steve NaroffOperand::Operand(Register rm, ShiftOp shift_op, int shift_imm) {
162d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  ASSERT(is_uint5(shift_imm));
163dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  ASSERT(shift_op != ROR || shift_imm != 0);  // use RRX if you mean it
164df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  rm_ = rm;
165dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  rs_ = no_reg;
166dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  shift_op_ = shift_op;
167d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  shift_imm_ = shift_imm & 31;
168dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  if (shift_op == RRX) {
169dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    // encoded as ROR with shift_imm == 0
1705512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian    ASSERT(shift_imm == 0);
1715512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian    shift_op_ = ROR;
172d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall    shift_imm_ = 0;
1735512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian  }
1745512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian}
1755512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian
17671b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis
177d226f65006733ed7f709c3174f22ce33391cb58fJohn McCallOperand::Operand(Register rm, ShiftOp shift_op, Register rs) {
17805511fa6349ef0820a778f8c840d0b64e05e9aeeFariborz Jahanian  ASSERT(shift_op != RRX);
1795512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian  rm_ = rm;
1805512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian  rs_ = no_reg;
1815512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian  shift_op_ = shift_op;
182d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  rs_ = rs;
1835512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian}
1845512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian
1855512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian
1865512ba538f3f6b0576623f680fa7d930fa085ccdFariborz JahanianMemOperand::MemOperand(Register rn, int32_t offset, AddrMode am) {
1875512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian  rn_ = rn;
1885512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian  rm_ = no_reg;
1895512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian  offset_ = offset;
1905512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian  am_ = am;
19183c481ade785a919ba21a33f9a8b1b21c1212fb3Fariborz Jahanian}
19283c481ade785a919ba21a33f9a8b1b21c1212fb3Fariborz Jahanian
19383c481ade785a919ba21a33f9a8b1b21c1212fb3Fariborz JahanianMemOperand::MemOperand(Register rn, Register rm, AddrMode am) {
1945512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian  rn_ = rn;
1955512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian  rm_ = rm;
196dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  shift_op_ = LSL;
197dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  shift_imm_ = 0;
198dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  am_ = am;
199dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff}
2007ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff
201df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner
202dac269b65eed82182fc3e96566dedd6562dfe11eSteve NaroffMemOperand::MemOperand(Register rn, Register rm,
2033b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor                       ShiftOp shift_op, int shift_imm, AddrMode am) {
2043b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor  ASSERT(is_uint5(shift_imm));
2053b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor  rn_ = rn;
20623c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor  rm_ = rm;
207dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor  shift_op_ = shift_op;
2083b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor  shift_imm_ = shift_imm & 31;
2093b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor  am_ = am;
210df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner}
211dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
212d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall
213dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff// -----------------------------------------------------------------------------
214dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff// Implementation of Assembler.
215dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
216dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff// Instruction encoding bits.
217dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroffenum {
218d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  H   = 1 << 5,   // halfword (or byte)
21971b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis  S6  = 1 << 6,   // signed (or unsigned)
22071b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis  L   = 1 << 20,  // load (or store)
22106036d3709955a53297b4cbe14e20db88f321470Chris Lattner  S   = 1 << 20,  // set condition code (or leave unchanged)
22271b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis  W   = 1 << 21,  // writeback base register (or leave unchanged)
22371b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis  A   = 1 << 21,  // accumulate in multiply instruction (or not)
224d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  B   = 1 << 22,  // unsigned byte (or word)
2251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  N   = 1 << 22,  // long (or short)
226d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  U   = 1 << 23,  // positive (or negative) offset/index
2271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  P   = 1 << 24,  // offset/pre-indexed addressing (or post-indexed addressing)
22806036d3709955a53297b4cbe14e20db88f321470Chris Lattner  I   = 1 << 25,  // immediate shifter operand (or not)
229beaaccd8e2a8748f77b66e2b330fb9136937e14cJay Foad
23018df52bbb5d28ca082064d31ae7558dbdae52377Douglas Gregor  B4  = 1 << 4,
23106036d3709955a53297b4cbe14e20db88f321470Chris Lattner  B5  = 1 << 5,
2321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  B6  = 1 << 6,
233df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  B7  = 1 << 7,
23483c481ade785a919ba21a33f9a8b1b21c1212fb3Fariborz Jahanian  B8  = 1 << 8,
235dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  B9  = 1 << 9,
23625e077d59a8e8e43b65882b69610a3d5e2aaf53cFariborz Jahanian  B12 = 1 << 12,
2375512ba538f3f6b0576623f680fa7d930fa085ccdFariborz Jahanian  B16 = 1 << 16,
238dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  B18 = 1 << 18,
239dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  B19 = 1 << 19,
240d0014540005f2a5ab837365db6bd40f479406758John McCall  B20 = 1 << 20,
241d0014540005f2a5ab837365db6bd40f479406758John McCall  B21 = 1 << 21,
242d0014540005f2a5ab837365db6bd40f479406758John McCall  B22 = 1 << 22,
243d0014540005f2a5ab837365db6bd40f479406758John McCall  B23 = 1 << 23,
244d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  B24 = 1 << 24,
245d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  B25 = 1 << 25,
246d0014540005f2a5ab837365db6bd40f479406758John McCall  B26 = 1 << 26,
247d0014540005f2a5ab837365db6bd40f479406758John McCall  B27 = 1 << 27,
248d0014540005f2a5ab837365db6bd40f479406758John McCall
249d0014540005f2a5ab837365db6bd40f479406758John McCall  // Instruction bit masks.
250d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  RdMask     = 15 << 12,  // in str instruction
251d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  CondMask   = 15 << 28,
252d0014540005f2a5ab837365db6bd40f479406758John McCall  CoprocessorMask = 15 << 8,
253d0014540005f2a5ab837365db6bd40f479406758John McCall  OpCodeMask = 15 << 21,  // in data-processing instructions
254d0014540005f2a5ab837365db6bd40f479406758John McCall  Imm24Mask  = (1 << 24) - 1,
255d0014540005f2a5ab837365db6bd40f479406758John McCall  Off12Mask  = (1 << 12) - 1,
256d0014540005f2a5ab837365db6bd40f479406758John McCall  // Reserved condition.
257d0014540005f2a5ab837365db6bd40f479406758John McCall  nv = 15 << 28
258d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall};
259d0014540005f2a5ab837365db6bd40f479406758John McCall
260d0014540005f2a5ab837365db6bd40f479406758John McCall
261d0014540005f2a5ab837365db6bd40f479406758John McCall// add(sp, sp, 4) instruction (aka Pop())
262d226f65006733ed7f709c3174f22ce33391cb58fJohn McCallstatic const Instr kPopInstruction =
263d0014540005f2a5ab837365db6bd40f479406758John McCall    al | 4 * B21 | 4 | LeaveCC | I | sp.code() * B16 | sp.code() * B12;
264d0014540005f2a5ab837365db6bd40f479406758John McCall// str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r))
265d0014540005f2a5ab837365db6bd40f479406758John McCall// register r is not encoded.
266d0014540005f2a5ab837365db6bd40f479406758John McCallstatic const Instr kPushRegPattern =
267d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall    al | B26 | 4 | NegPreIndex | sp.code() * B16;
268d0014540005f2a5ab837365db6bd40f479406758John McCall// ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r))
269d0014540005f2a5ab837365db6bd40f479406758John McCall// register r is not encoded.
270d0014540005f2a5ab837365db6bd40f479406758John McCallstatic const Instr kPopRegPattern =
271d0014540005f2a5ab837365db6bd40f479406758John McCall    al | B26 | L | 4 | PostIndex | sp.code() * B16;
272d0014540005f2a5ab837365db6bd40f479406758John McCall// mov lr, pc
273d0014540005f2a5ab837365db6bd40f479406758John McCallconst Instr kMovLrPc = al | 13*B21 | pc.code() | lr.code() * B12;
274d0014540005f2a5ab837365db6bd40f479406758John McCall// ldr rd, [pc, #offset]
275d0014540005f2a5ab837365db6bd40f479406758John McCallconst Instr kLdrPCMask = CondMask | 15 * B24 | 7 * B20 | 15 * B16;
276d0014540005f2a5ab837365db6bd40f479406758John McCallconst Instr kLdrPCPattern = al | 5 * B24 | L | pc.code() * B16;
277d0014540005f2a5ab837365db6bd40f479406758John McCall// blxcc rm
278d0014540005f2a5ab837365db6bd40f479406758John McCallconst Instr kBlxRegMask =
279d0014540005f2a5ab837365db6bd40f479406758John McCall    15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4;
280d0014540005f2a5ab837365db6bd40f479406758John McCallconst Instr kBlxRegPattern =
281d0014540005f2a5ab837365db6bd40f479406758John McCall    B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | 3 * B4;
282d0014540005f2a5ab837365db6bd40f479406758John McCall// A mask for the Rd register for push, pop, ldr, str instructions.
283d0014540005f2a5ab837365db6bd40f479406758John McCallconst Instr kRdMask = 0x0000f000;
284d0014540005f2a5ab837365db6bd40f479406758John McCallstatic const int kRdShift = 12;
285d226f65006733ed7f709c3174f22ce33391cb58fJohn McCallstatic const Instr kLdrRegFpOffsetPattern =
28623c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor    al | B26 | L | Offset | fp.code() * B16;
287d0014540005f2a5ab837365db6bd40f479406758John McCallstatic const Instr kStrRegFpOffsetPattern =
288d0014540005f2a5ab837365db6bd40f479406758John McCall    al | B26 | Offset | fp.code() * B16;
289d0014540005f2a5ab837365db6bd40f479406758John McCallstatic const Instr kLdrRegFpNegOffsetPattern =
290d0014540005f2a5ab837365db6bd40f479406758John McCall    al | B26 | L | NegOffset | fp.code() * B16;
291d0014540005f2a5ab837365db6bd40f479406758John McCallstatic const Instr kStrRegFpNegOffsetPattern =
292d0014540005f2a5ab837365db6bd40f479406758John McCall    al | B26 | NegOffset | fp.code() * B16;
293d0014540005f2a5ab837365db6bd40f479406758John McCallstatic const Instr kLdrStrInstrTypeMask = 0xffff0000;
294d0014540005f2a5ab837365db6bd40f479406758John McCallstatic const Instr kLdrStrInstrArgumentMask = 0x0000ffff;
295d0014540005f2a5ab837365db6bd40f479406758John McCallstatic const Instr kLdrStrOffsetMask = 0x00000fff;
296d0014540005f2a5ab837365db6bd40f479406758John McCall
297dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff// Spare buffer.
298dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroffstatic const int kMinimalBufferSize = 4*KB;
299dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroffstatic byte* spare_buffer_ = NULL;
300294494e1cce92043562b4680c613df7fd028c02eSteve Naroff
3013536b443bc50d58a79f14fca9b6842541a434854Steve NaroffAssembler::Assembler(void* buffer, int buffer_size) {
302dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  if (buffer == NULL) {
303dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    // Do our own buffer management.
304dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    if (buffer_size <= kMinimalBufferSize) {
305294494e1cce92043562b4680c613df7fd028c02eSteve Naroff      buffer_size = kMinimalBufferSize;
306294494e1cce92043562b4680c613df7fd028c02eSteve Naroff
307294494e1cce92043562b4680c613df7fd028c02eSteve Naroff      if (spare_buffer_ != NULL) {
308294494e1cce92043562b4680c613df7fd028c02eSteve Naroff        buffer = spare_buffer_;
309d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall        spare_buffer_ = NULL;
310cb53b361bce341c8591333c6997f62e480acc0b4Chris Lattner      }
311d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall    }
312d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall    if (buffer == NULL) {
313682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner      buffer_ = NewArray<byte>(buffer_size);
31400933591a2795d09dd1acff12a2d21bce7cb12c5Fariborz Jahanian    } else {
3151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      buffer_ = static_cast<byte*>(buffer);
316782f2f52b78d8ca785110398a7f7b56b830b9ac7Ted Kremenek    }
317bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner    buffer_size_ = buffer_size;
318294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    own_buffer_ = true;
319e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner
320df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  } else {
321d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall    // Use externally provided buffer instead.
322df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner    ASSERT(buffer_size > 0);
32325e077d59a8e8e43b65882b69610a3d5e2aaf53cFariborz Jahanian    buffer_ = static_cast<byte*>(buffer);
3243536b443bc50d58a79f14fca9b6842541a434854Steve Naroff    buffer_size_ = buffer_size;
3253536b443bc50d58a79f14fca9b6842541a434854Steve Naroff    own_buffer_ = false;
326b6d74a158a9c002e3c0fcbda8ad8d0ccbb2e5088Chris Lattner  }
327b6d74a158a9c002e3c0fcbda8ad8d0ccbb2e5088Chris Lattner
328294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  // Setup buffer pointers.
329294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  ASSERT(buffer_ != NULL);
33005511fa6349ef0820a778f8c840d0b64e05e9aeeFariborz Jahanian  pc_ = buffer_;
33105511fa6349ef0820a778f8c840d0b64e05e9aeeFariborz Jahanian  reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
332d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  num_prinfo_ = 0;
333d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  next_buffer_check_ = 0;
334d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  const_pool_blocked_nesting_ = 0;
335d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  no_const_pool_before_ = 0;
33605511fa6349ef0820a778f8c840d0b64e05e9aeeFariborz Jahanian  last_const_pool_end_ = 0;
33705511fa6349ef0820a778f8c840d0b64e05e9aeeFariborz Jahanian  last_bound_pos_ = 0;
338e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner  current_statement_position_ = RelocInfo::kNoPosition;
339e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner  current_position_ = RelocInfo::kNoPosition;
340294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  written_statement_position_ = current_statement_position_;
341e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner  written_position_ = current_position_;
342e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner}
3431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
344bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner
345e82a10fbba9e33b253119c7c1e0a9801caef486dChris LattnerAssembler::~Assembler() {
346e3a2ca7e30601cdd31c77a830f4cc487851e8096Fariborz Jahanian  ASSERT(const_pool_blocked_nesting_ == 0);
3471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (own_buffer_) {
348b6ac2451bfed36206c5cec7217372c4299f67f2bDouglas Gregor    if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
349b6ac2451bfed36206c5cec7217372c4299f67f2bDouglas Gregor      spare_buffer_ = buffer_;
35023c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor    } else {
351e6b1bb6e7fe906d164637ca33503b8fafdbc99e5Douglas Gregor      DeleteArray(buffer_);
352e6b1bb6e7fe906d164637ca33503b8fafdbc99e5Douglas Gregor    }
353dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor  }
354b6ac2451bfed36206c5cec7217372c4299f67f2bDouglas Gregor}
355b6ac2451bfed36206c5cec7217372c4299f67f2bDouglas Gregor
356e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner
357e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattnervoid Assembler::GetCode(CodeDesc* desc) {
3581fd80116b49782c367ff5d5f50a8b76dd8a5d7f7Chris Lattner  // Emit constant pool if necessary.
3591fd80116b49782c367ff5d5f50a8b76dd8a5d7f7Chris Lattner  CheckConstPool(true, false);
3601fd80116b49782c367ff5d5f50a8b76dd8a5d7f7Chris Lattner  ASSERT(num_prinfo_ == 0);
3611fd80116b49782c367ff5d5f50a8b76dd8a5d7f7Chris Lattner
3621fd80116b49782c367ff5d5f50a8b76dd8a5d7f7Chris Lattner  // Setup code descriptor.
3631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  desc->buffer = buffer_;
3644985aceceb9b9261b876b515d32726175c13a775Steve Naroff  desc->buffer_size = buffer_size_;
3654985aceceb9b9261b876b515d32726175c13a775Steve Naroff  desc->instr_size = pc_offset();
366bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
367e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner}
368e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner
3691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
370e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattnervoid Assembler::Align(int m) {
371e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner  ASSERT(m >= 4 && IsPowerOf2(m));
372c464ae8444edb6d07ea49b7a0eae1674c0fa1bb8Douglas Gregor  while ((pc_offset() & (m - 1)) != 0) {
37323c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor    nop();
374dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor  }
375c464ae8444edb6d07ea49b7a0eae1674c0fa1bb8Douglas Gregor}
376c464ae8444edb6d07ea49b7a0eae1674c0fa1bb8Douglas Gregor
377c464ae8444edb6d07ea49b7a0eae1674c0fa1bb8Douglas Gregor
378a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattnerbool Assembler::IsNop(Instr instr, int type) {
3791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Check for mov rx, rx.
380a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner  ASSERT(0 <= type && type <= 14);  // mov pc, pc is not a nop.
381782f2f52b78d8ca785110398a7f7b56b830b9ac7Ted Kremenek  return instr == (al | 13*B21 | type*B12 | type);
382782f2f52b78d8ca785110398a7f7b56b830b9ac7Ted Kremenek}
383e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner
384c3d43b783dfb1a1502aa8b31ab1985cf237b1f77Douglas Gregor
385c3d43b783dfb1a1502aa8b31ab1985cf237b1f77Douglas Gregorbool Assembler::IsBranch(Instr instr) {
386c3d43b783dfb1a1502aa8b31ab1985cf237b1f77Douglas Gregor  return (instr & (B27 | B25)) == (B27 | B25);
387c3d43b783dfb1a1502aa8b31ab1985cf237b1f77Douglas Gregor}
388bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner
3891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
390bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattnerint Assembler::GetBranchOffset(Instr instr) {
391bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner  ASSERT(IsBranch(instr));
392bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner  // Take the jump offset in the lower 24 bits, sign extend it and multiply it
393a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner  // with 4 to get the offset in bytes.
394a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner  return ((instr & Imm24Mask) << 8) >> 6;
395bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner}
396bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner
397bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner
398bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattnerbool Assembler::IsLdrRegisterImmediate(Instr instr) {
399f6ed85533583dae18a44ddc4be6cfc4d68749e36Chris Lattner  return (instr & (B27 | B26 | B25 | B22 | B20)) == (B26 | B20);
400bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner}
401a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner
402a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner
4031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpint Assembler::GetLdrRegisterImmediateOffset(Instr instr) {
404a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner  ASSERT(IsLdrRegisterImmediate(instr));
405a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner  bool positive = (instr & B23) == B23;
406a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner  int offset = instr & Off12Mask;  // Zero extended offset.
407bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner  return positive ? offset : -offset;
408e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner}
409bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner
410a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner
411bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris LattnerInstr Assembler::SetLdrRegisterImmediateOffset(Instr instr, int offset) {
412a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner  ASSERT(IsLdrRegisterImmediate(instr));
4131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  bool positive = offset >= 0;
414a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner  if (!positive) offset = -offset;
415f6ed85533583dae18a44ddc4be6cfc4d68749e36Chris Lattner  ASSERT(is_uint12(offset));
416f6ed85533583dae18a44ddc4be6cfc4d68749e36Chris Lattner  // Set bit indicating whether the offset should be added.
417f6ed85533583dae18a44ddc4be6cfc4d68749e36Chris Lattner  instr = (instr & ~B23) | (positive ? B23 : 0);
418e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner  // Set the actual offset.
4191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return (instr & ~Off12Mask) | offset;
4208ca329c00e72f301cbaaa42229b20a2f5bc793e5Chris Lattner}
4214ad9685b3e2d5e2923c9cda7baaf7973ef0b1c62Douglas Gregor
4224ad9685b3e2d5e2923c9cda7baaf7973ef0b1c62Douglas Gregor
4231eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpRegister Assembler::GetRd(Instr instr) {
424d0014540005f2a5ab837365db6bd40f479406758John McCall  Register reg;
425d0014540005f2a5ab837365db6bd40f479406758John McCall  reg.code_ = ((instr & kRdMask) >> kRdShift);
426bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall  return reg;
427e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner}
428e82a10fbba9e33b253119c7c1e0a9801caef486dChris Lattner
429bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall
4301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpbool Assembler::IsPush(Instr instr) {
431a1fed7e3beebf9bb1bc85123f283be3eb631c120Chris Lattner  return ((instr & ~kRdMask) == kPushRegPattern);
432a1fed7e3beebf9bb1bc85123f283be3eb631c120Chris Lattner}
433a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner
434f28b264437053fb0deacc9ba02b18a0966f7290aSteve Naroff
435294494e1cce92043562b4680c613df7fd028c02eSteve Naroffbool Assembler::IsPop(Instr instr) {
436bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner  return ((instr & ~kRdMask) == kPopRegPattern);
437bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner}
438bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner
439c464ae8444edb6d07ea49b7a0eae1674c0fa1bb8Douglas Gregor
44023c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregorbool Assembler::IsStrRegFpOffset(Instr instr) {
441dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor  return ((instr & kLdrStrInstrTypeMask) == kStrRegFpOffsetPattern);
442c464ae8444edb6d07ea49b7a0eae1674c0fa1bb8Douglas Gregor}
443bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner
444bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner
445bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattnerbool Assembler::IsLdrRegFpOffset(Instr instr) {
4461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpOffsetPattern);
447a2449b2bf739545494241e189b59587d5ca5c2c1Chris Lattner}
448bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner
44923c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor
4501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpbool Assembler::IsStrRegFpNegOffset(Instr instr) {
451beaaccd8e2a8748f77b66e2b330fb9136937e14cJay Foad  return ((instr & kLdrStrInstrTypeMask) == kStrRegFpNegOffsetPattern);
452beaaccd8e2a8748f77b66e2b330fb9136937e14cJay Foad}
453294494e1cce92043562b4680c613df7fd028c02eSteve Naroff
454294494e1cce92043562b4680c613df7fd028c02eSteve Naroff
455d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanianbool Assembler::IsLdrRegFpNegOffset(Instr instr) {
456d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian  return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpNegOffsetPattern);
457d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian}
458d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian
459d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian
460d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian// Labels refer to positions in the (to be) generated code.
461d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian// There are bound, linked, and unused labels.
462d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian//
463d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian// Bound labels refer to known positions in the already
464d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian// generated code. pos() is the position the label refers to.
465d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian//
466d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian// Linked labels refer to unknown positions in the code
467d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian// to be generated; pos() is the position of the last
468d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian// instruction using the label.
469d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian
470d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian
471d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall// The link chain is terminated by a negative code position (must be aligned)
472d226f65006733ed7f709c3174f22ce33391cb58fJohn McCallconst int kEndOfChain = -4;
4734ad9685b3e2d5e2923c9cda7baaf7973ef0b1c62Douglas Gregor
4748ca329c00e72f301cbaaa42229b20a2f5bc793e5Chris Lattner
475dd5b5f2bb73d037745940431b71eb98393d12d4fChris Lattnerint Assembler::target_at(int pos)  {
4761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Instr instr = instr_at(pos);
477cd9f4b31c4fe5b77b5519cc17b4583fab912bad1Chris Lattner  if ((instr & ~Imm24Mask) == 0) {
478ece8e71d12b6f4cb2dc501297afef126dab8ad74Steve Naroff    // Emitted label constant, not part of a branch.
47923c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor    return instr - (Code::kHeaderSize - kHeapObjectTag);
480dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor  }
481ece8e71d12b6f4cb2dc501297afef126dab8ad74Steve Naroff  ASSERT((instr & 7*B25) == 5*B25);  // b, bl, or blx imm24
482d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian  int imm26 = ((instr & Imm24Mask) << 8) >> 6;
4831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if ((instr & CondMask) == nv && (instr & B24) != 0) {
484f6ed85533583dae18a44ddc4be6cfc4d68749e36Chris Lattner    // blx uses bit 24 to encode bit 2 of imm26
485f6ed85533583dae18a44ddc4be6cfc4d68749e36Chris Lattner    imm26 += 2;
486f6ed85533583dae18a44ddc4be6cfc4d68749e36Chris Lattner  }
487f6ed85533583dae18a44ddc4be6cfc4d68749e36Chris Lattner  return pos + kPcLoadDelta + imm26;
488f6ed85533583dae18a44ddc4be6cfc4d68749e36Chris Lattner}
4891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
490156b061e4918a5e7ecd8eb317975de0e6be2688bChris Lattner
4911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid Assembler::target_at_put(int pos, int target_pos) {
49292e62b02226410bcad8584541b8f1ff4d35ebab9Chris Lattner  Instr instr = instr_at(pos);
493e00da7c2f47d4a3d9615c1056a8a65e459113de3Chris Lattner  if ((instr & ~Imm24Mask) == 0) {
49492e62b02226410bcad8584541b8f1ff4d35ebab9Chris Lattner    ASSERT(target_pos == kEndOfChain || target_pos >= 0);
495e00da7c2f47d4a3d9615c1056a8a65e459113de3Chris Lattner    // Emitted label constant, not part of a branch.
49692e62b02226410bcad8584541b8f1ff4d35ebab9Chris Lattner    // Make label relative to Code* of generated Code object.
497e00da7c2f47d4a3d9615c1056a8a65e459113de3Chris Lattner    instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
49892e62b02226410bcad8584541b8f1ff4d35ebab9Chris Lattner    return;
499e00da7c2f47d4a3d9615c1056a8a65e459113de3Chris Lattner  }
50092e62b02226410bcad8584541b8f1ff4d35ebab9Chris Lattner  int imm26 = target_pos - (pos + kPcLoadDelta);
501e00da7c2f47d4a3d9615c1056a8a65e459113de3Chris Lattner  ASSERT((instr & 7*B25) == 5*B25);  // b, bl, or blx imm24
50292e62b02226410bcad8584541b8f1ff4d35ebab9Chris Lattner  if ((instr & CondMask) == nv) {
503e00da7c2f47d4a3d9615c1056a8a65e459113de3Chris Lattner    // blx uses bit 24 to encode bit 2 of imm26
50492e62b02226410bcad8584541b8f1ff4d35ebab9Chris Lattner    ASSERT((imm26 & 1) == 0);
505e00da7c2f47d4a3d9615c1056a8a65e459113de3Chris Lattner    instr = (instr & ~(B24 | Imm24Mask)) | ((imm26 & 2) >> 1)*B24;
506156b061e4918a5e7ecd8eb317975de0e6be2688bChris Lattner  } else {
507156b061e4918a5e7ecd8eb317975de0e6be2688bChris Lattner    ASSERT((imm26 & 3) == 0);
508dd5b5f2bb73d037745940431b71eb98393d12d4fChris Lattner    instr &= ~Imm24Mask;
5091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  }
5104ad9685b3e2d5e2923c9cda7baaf7973ef0b1c62Douglas Gregor  int imm24 = imm26 >> 2;
5114ad9685b3e2d5e2923c9cda7baaf7973ef0b1c62Douglas Gregor  ASSERT(is_int24(imm24));
51223c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor  instr_at_put(pos, instr | (imm24 & Imm24Mask));
5134ad9685b3e2d5e2923c9cda7baaf7973ef0b1c62Douglas Gregor}
5144ad9685b3e2d5e2923c9cda7baaf7973ef0b1c62Douglas Gregor
51523c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor
5164ad9685b3e2d5e2923c9cda7baaf7973ef0b1c62Douglas Gregorvoid Assembler::print(Label* L) {
517dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor  if (L->is_unused()) {
5184ad9685b3e2d5e2923c9cda7baaf7973ef0b1c62Douglas Gregor    PrintF("unused label\n");
5194ad9685b3e2d5e2923c9cda7baaf7973ef0b1c62Douglas Gregor  } else if (L->is_bound()) {
5208ca329c00e72f301cbaaa42229b20a2f5bc793e5Chris Lattner    PrintF("bound label to %d\n", L->pos());
5211ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner  } else if (L->is_linked()) {
5228ca329c00e72f301cbaaa42229b20a2f5bc793e5Chris Lattner    Label l = *L;
5238ca329c00e72f301cbaaa42229b20a2f5bc793e5Chris Lattner    PrintF("unbound label");
5248ca329c00e72f301cbaaa42229b20a2f5bc793e5Chris Lattner    while (l.is_linked()) {
5251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      PrintF("@ %d ", l.pos());
526e013d685c6689ac7ae103ee88acf573422d1ed6aDaniel Dunbar      Instr instr = instr_at(l.pos());
5278ca329c00e72f301cbaaa42229b20a2f5bc793e5Chris Lattner      if ((instr & ~Imm24Mask) == 0) {
5288ca329c00e72f301cbaaa42229b20a2f5bc793e5Chris Lattner        PrintF("value\n");
529156b061e4918a5e7ecd8eb317975de0e6be2688bChris Lattner      } else {
5301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        ASSERT((instr & 7*B25) == 5*B25);  // b, bl, or blx
531e0097db2848c463a534c18c235c6d3e53f2f1b87Fariborz Jahanian        int cond = instr & CondMask;
532e0097db2848c463a534c18c235c6d3e53f2f1b87Fariborz Jahanian        const char* b;
533156b061e4918a5e7ecd8eb317975de0e6be2688bChris Lattner        const char* c;
5348ca329c00e72f301cbaaa42229b20a2f5bc793e5Chris Lattner        if (cond == nv) {
5358ca329c00e72f301cbaaa42229b20a2f5bc793e5Chris Lattner          b = "blx";
5368ca329c00e72f301cbaaa42229b20a2f5bc793e5Chris Lattner          c = "";
5378ca329c00e72f301cbaaa42229b20a2f5bc793e5Chris Lattner        } else {
538156b061e4918a5e7ecd8eb317975de0e6be2688bChris Lattner          if ((instr & B24) != 0)
5398ca329c00e72f301cbaaa42229b20a2f5bc793e5Chris Lattner            b = "bl";
540e00da7c2f47d4a3d9615c1056a8a65e459113de3Chris Lattner          else
541a9500f05ba6c09bbd84d342236863833067cd816Chris Lattner            b = "b";
542cd9f4b31c4fe5b77b5519cc17b4583fab912bad1Chris Lattner
543cd9f4b31c4fe5b77b5519cc17b4583fab912bad1Chris Lattner          switch (cond) {
544cd9f4b31c4fe5b77b5519cc17b4583fab912bad1Chris Lattner            case eq: c = "eq"; break;
5451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump            case ne: c = "ne"; break;
546156b061e4918a5e7ecd8eb317975de0e6be2688bChris Lattner            case hs: c = "hs"; break;
547156b061e4918a5e7ecd8eb317975de0e6be2688bChris Lattner            case lo: c = "lo"; break;
5481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump            case mi: c = "mi"; break;
549156b061e4918a5e7ecd8eb317975de0e6be2688bChris Lattner            case pl: c = "pl"; break;
550d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian            case vs: c = "vs"; break;
5511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump            case vc: c = "vc"; break;
552156b061e4918a5e7ecd8eb317975de0e6be2688bChris Lattner            case hi: c = "hi"; break;
553d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian            case ls: c = "ls"; break;
554d0f97d1716a138a8d9e0df8e5af77334663723d8Fariborz Jahanian            case ge: c = "ge"; break;
5553536b443bc50d58a79f14fca9b6842541a434854Steve Naroff            case lt: c = "lt"; break;
5561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump            case gt: c = "gt"; break;
5573536b443bc50d58a79f14fca9b6842541a434854Steve Naroff            case le: c = "le"; break;
558294494e1cce92043562b4680c613df7fd028c02eSteve Naroff            case al: c = ""; break;
559294494e1cce92043562b4680c613df7fd028c02eSteve Naroff            default:
560294494e1cce92043562b4680c613df7fd028c02eSteve Naroff              c = "";
561294494e1cce92043562b4680c613df7fd028c02eSteve Naroff              UNREACHABLE();
5624985aceceb9b9261b876b515d32726175c13a775Steve Naroff          }
5634985aceceb9b9261b876b515d32726175c13a775Steve Naroff        }
5644985aceceb9b9261b876b515d32726175c13a775Steve Naroff        PrintF("%s%s\n", b, c);
565d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall      }
566d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall      next(&l);
567df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner    }
568294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  } else {
5691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
570bef1185418705e16012b3dd50cd7c260c8d6b79cSteve Naroff  }
5711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}
572d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall
5733536b443bc50d58a79f14fca9b6842541a434854Steve Naroff
5742bd42fadafddc8acf744b57a970bdc96a077c617Steve Naroffvoid Assembler::bind_to(Label* L, int pos) {
575f28b264437053fb0deacc9ba02b18a0966f7290aSteve Naroff  ASSERT(0 <= pos && pos <= pc_offset());  // must have a valid binding position
576294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  while (L->is_linked()) {
577294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    int fixup_pos = L->pos();
578294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    next(L);  // call next before overwriting link with target at fixup_pos
579294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    target_at_put(fixup_pos, pos);
580294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  }
581294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  L->bind_to(pos);
582294494e1cce92043562b4680c613df7fd028c02eSteve Naroff
583294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  // Keep track of the last bound label so we don't eliminate any instructions
584294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  // before a bound label.
585294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  if (pos > last_bound_pos_)
5862fc5c2428ecb450a3256c8316b93b8655cb76a0fChris Lattner    last_bound_pos_ = pos;
587ff38491c18b060526d754765b952f4a497a89416Chris Lattner}
588ff38491c18b060526d754765b952f4a497a89416Chris Lattner
589ff38491c18b060526d754765b952f4a497a89416Chris Lattner
590ff38491c18b060526d754765b952f4a497a89416Chris Lattnervoid Assembler::link_to(Label* L, Label* appendix) {
591ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  if (appendix->is_linked()) {
592ff38491c18b060526d754765b952f4a497a89416Chris Lattner    if (L->is_linked()) {
5939298d9655aed28b2d9f6cc65c81401b209f03fdcChris Lattner      // Append appendix to L's list.
594ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      int fixup_pos;
595ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      int link = L->pos();
596ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      do {
597ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson        fixup_pos = link;
598ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson        link = target_at(fixup_pos);
599ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      } while (link > 0);
600ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      ASSERT(link == kEndOfChain);
601ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      target_at_put(fixup_pos, appendix->pos());
602ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    } else {
603ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      // L is empty, simply use appendix.
604ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      *L = *appendix;
605ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    }
606ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  }
607ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  appendix->Unuse();  // appendix should not be used anymore
608ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson}
609ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson
610ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson
611ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlssonvoid Assembler::bind(Label* L) {
612ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  ASSERT(!L->is_bound());  // label can only be bound once
613ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  bind_to(L, pc_offset());
614ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson}
615ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson
616ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson
617ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlssonvoid Assembler::next(Label* L) {
618ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  ASSERT(L->is_linked());
619ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  int link = target_at(L->pos());
620ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  if (link > 0) {
621ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    L->link_to(link);
622ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  } else {
623ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    ASSERT(link == kEndOfChain);
624ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    L->Unuse();
625ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  }
626ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson}
627ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson
628ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson
629ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson// Low-level code emission routines depending on the addressing mode.
630ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlssonstatic bool fits_shifter(uint32_t imm32,
631ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson                         uint32_t* rotate_imm,
632ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson                         uint32_t* immed_8,
633ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson                         Instr* instr) {
634ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  // imm32 must be unsigned.
635ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  for (int rot = 0; rot < 16; rot++) {
636ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    uint32_t imm8 = (imm32 << 2*rot) | (imm32 >> (32 - 2*rot));
637ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    if ((imm8 <= 0xff)) {
638ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      *rotate_imm = rot;
639ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      *immed_8 = imm8;
640ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      return true;
641ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    }
642ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  }
643ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  // If the opcode is mov or mvn and if ~imm32 fits, change the opcode.
644ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  if (instr != NULL && (*instr & 0xd*B21) == 0xd*B21) {
645ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) {
646ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      *instr ^= 0x2*B21;
647ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson      return true;
648ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson    }
649ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  }
650ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson  return false;
651ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson}
652ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson
653ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson
654ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson// We have to use the temporary register for things that can be relocated even
655ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlsson// if they can be encoded in the ARM's 12 bits of immediate-offset instruction
656ff38491c18b060526d754765b952f4a497a89416Chris Lattner// space.  There is no guarantee that the relocated location can be similarly
657ff38491c18b060526d754765b952f4a497a89416Chris Lattner// encoded.
658ef048ef393960728bdc82cd5c45035bde7013b6aAnders Carlssonstatic bool MustUseIp(RelocInfo::Mode rmode) {
659ff38491c18b060526d754765b952f4a497a89416Chris Lattner  if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
6604b6c9051c6522894978c9ba6a819a659d102db36Fariborz Jahanian#ifdef DEBUG
661ff38491c18b060526d754765b952f4a497a89416Chris Lattner    if (!Serializer::enabled()) {
662d064951b0dcc95f8604d0d69ae82d9ecbd38c796Fariborz Jahanian      Serializer::TooLateToEnableNow();
663294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    }
664294494e1cce92043562b4680c613df7fd028c02eSteve Naroff#endif  // def DEBUG
6650196cab54007ff072ec2642da8911c6b7e8d3fb5Fariborz Jahanian    return Serializer::enabled();
6660196cab54007ff072ec2642da8911c6b7e8d3fb5Fariborz Jahanian  } else if (rmode == RelocInfo::NONE) {
667335a2d4122e41343fe11a775889b8bec5b14be60Fariborz Jahanian    return false;
6683ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian  }
6693ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian  return true;
6703ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian}
6711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6725ffb14b7e88e587cd2f78dcc3a966a64108920f0Chris Lattner
6730196cab54007ff072ec2642da8911c6b7e8d3fb5Fariborz Jahanianvoid Assembler::addrmod1(Instr instr,
6740196cab54007ff072ec2642da8911c6b7e8d3fb5Fariborz Jahanian                         Register rn,
675a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek                         Register rd,
676e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner                         const Operand& x) {
677e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner  CheckBuffer();
678294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  ASSERT((instr & ~(CondMask | OpCodeMask | S)) == 0);
679294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  if (!x.rm_.is_valid()) {
680294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    // Immediate.
681294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    uint32_t rotate_imm;
682294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    uint32_t immed_8;
683a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek    if (MustUseIp(x.rmode_) ||
684e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner        !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) {
685cb53b361bce341c8591333c6997f62e480acc0b4Chris Lattner      // The immediate operand cannot be encoded as a shifter operand, so load
686e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner      // it first to register ip and change the original instruction to use ip.
6871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      // However, if the original instruction is a 'mov rd, x' (not setting the
688e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner      // condition code), then replace it with a 'ldr rd, [pc]'.
689e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner      RecordRelocInfo(x.rmode_, x.imm32_);
690a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek      CHECK(!rn.is(ip));  // rn should never be ip, or will be trashed
691e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner      Condition cond = static_cast<Condition>(instr & CondMask);
6921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      if ((instr & ~CondMask) == 13*B21) {  // mov, S not set
693a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek        ldr(rd, MemOperand(pc, 0), cond);
694e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner      } else {
695e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner        ldr(ip, MemOperand(pc, 0), cond);
696a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek        addrmod1(instr, rn, rd, Operand(ip));
697a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek      }
698a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek      return;
699a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek    }
700a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek    instr |= I | rotate_imm*B8 | immed_8;
701a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek  } else if (!x.rs_.is_valid()) {
702e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner    // Immediate shift.
703a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek    instr |= x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
704e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner  } else {
705e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner    // Register shift.
706e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner    ASSERT(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc));
707e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner    instr |= x.rs_.code()*B8 | x.shift_op_ | B4 | x.rm_.code();
7081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  }
709e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner  emit(instr | rn.code()*B16 | rd.code()*B12);
710e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner  if (rn.is(pc) || x.rm_.is(pc))
711e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner    // Block constant pool emission for one instruction after reading pc.
712e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner    BlockConstPoolBefore(pc_offset() + kInstrSize);
713e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner}
714e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner
715e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner
716e8b724d481c9547de2ee6f442be594b38ada452dChris Lattnervoid Assembler::addrmod2(Instr instr, Register rd, const MemOperand& x) {
717e8b724d481c9547de2ee6f442be594b38ada452dChris Lattner  ASSERT((instr & ~(CondMask | B | L)) == B26);
718a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek  int am = x.am_;
719df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  if (!x.rm_.is_valid()) {
7201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    // Immediate offset.
7214a76b292c9c3f60a257636e21d76b6ce1c12f8c4Chris Lattner    int offset_12 = x.offset_;
722e8904e992ca5e821b199c4577e8b5e5b17a33b1dChris Lattner    if (offset_12 < 0) {
7231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      offset_12 = -offset_12;
72419d74e1494fe399f0e2a94e9419c095f8214851bFariborz Jahanian      am ^= U;
725a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek    }
7264fa7afd07421e7276d1717e4fdf43a5fdd65a622Steve Naroff    if (!is_uint12(offset_12)) {
7274a76b292c9c3f60a257636e21d76b6ce1c12f8c4Chris Lattner      // Immediate offset cannot be encoded, load it first to register ip
728809070a886684cb5b92eb0e00a6581ab1fa6b17aDouglas Gregor      // rn (and rd in a load) should never be ip, or will be trashed.
729809070a886684cb5b92eb0e00a6581ab1fa6b17aDouglas Gregor      ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
730809070a886684cb5b92eb0e00a6581ab1fa6b17aDouglas Gregor      mov(ip, Operand(x.offset_), LeaveCC,
731809070a886684cb5b92eb0e00a6581ab1fa6b17aDouglas Gregor          static_cast<Condition>(instr & CondMask));
732809070a886684cb5b92eb0e00a6581ab1fa6b17aDouglas Gregor      addrmod2(instr, rd, MemOperand(x.rn_, ip, x.am_));
7331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      return;
7344a76b292c9c3f60a257636e21d76b6ce1c12f8c4Chris Lattner    }
7354a76b292c9c3f60a257636e21d76b6ce1c12f8c4Chris Lattner    ASSERT(offset_12 >= 0);  // no masking needed
7364a76b292c9c3f60a257636e21d76b6ce1c12f8c4Chris Lattner    instr |= offset_12;
737e8904e992ca5e821b199c4577e8b5e5b17a33b1dChris Lattner  } else {
7381ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    // Register offset (shift_imm_ and shift_op_ are 0) or scaled
7394a76b292c9c3f60a257636e21d76b6ce1c12f8c4Chris Lattner    // register offset the constructors make sure than both shift_imm_
7404a76b292c9c3f60a257636e21d76b6ce1c12f8c4Chris Lattner    // and shift_op_ are initialized.
7414a76b292c9c3f60a257636e21d76b6ce1c12f8c4Chris Lattner    ASSERT(!x.rm_.is(pc));
7424a76b292c9c3f60a257636e21d76b6ce1c12f8c4Chris Lattner    instr |= B25 | x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
7434a76b292c9c3f60a257636e21d76b6ce1c12f8c4Chris Lattner  }
744294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  ASSERT((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
745f28b264437053fb0deacc9ba02b18a0966f7290aSteve Naroff  emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
746294494e1cce92043562b4680c613df7fd028c02eSteve Naroff}
747294494e1cce92043562b4680c613df7fd028c02eSteve Naroff
748294494e1cce92043562b4680c613df7fd028c02eSteve Naroff
749294494e1cce92043562b4680c613df7fd028c02eSteve Naroffvoid Assembler::addrmod3(Instr instr, Register rd, const MemOperand& x) {
7504985aceceb9b9261b876b515d32726175c13a775Steve Naroff  ASSERT((instr & ~(CondMask | L | S6 | H)) == (B4 | B7));
751294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  ASSERT(x.rn_.is_valid());
7524985aceceb9b9261b876b515d32726175c13a775Steve Naroff  int am = x.am_;
753294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  if (!x.rm_.is_valid()) {
754294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    // Immediate offset.
7551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    int offset_8 = x.offset_;
756294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    if (offset_8 < 0) {
757294494e1cce92043562b4680c613df7fd028c02eSteve Naroff      offset_8 = -offset_8;
758294494e1cce92043562b4680c613df7fd028c02eSteve Naroff      am ^= U;
7597ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff    }
7607ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff    if (!is_uint8(offset_8)) {
7617ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff      // Immediate offset cannot be encoded, load it first to register ip
7627ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff      // rn (and rd in a load) should never be ip, or will be trashed.
763294494e1cce92043562b4680c613df7fd028c02eSteve Naroff      ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
7644985aceceb9b9261b876b515d32726175c13a775Steve Naroff      mov(ip, Operand(x.offset_), LeaveCC,
7654985aceceb9b9261b876b515d32726175c13a775Steve Naroff          static_cast<Condition>(instr & CondMask));
766294494e1cce92043562b4680c613df7fd028c02eSteve Naroff      addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
7674985aceceb9b9261b876b515d32726175c13a775Steve Naroff      return;
7684985aceceb9b9261b876b515d32726175c13a775Steve Naroff    }
769294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    ASSERT(offset_8 >= 0);  // no masking needed
7704985aceceb9b9261b876b515d32726175c13a775Steve Naroff    instr |= B | (offset_8 >> 4)*B8 | (offset_8 & 0xf);
771294494e1cce92043562b4680c613df7fd028c02eSteve Naroff  } else if (x.shift_imm_ != 0) {
772294494e1cce92043562b4680c613df7fd028c02eSteve Naroff    // Scaled register offset not supported, load index first
7737ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff    // rn (and rd in a load) should never be ip, or will be trashed.
7747ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff    ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
7757ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff    mov(ip, Operand(x.rm_, x.shift_op_, x.shift_imm_), LeaveCC,
776d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall        static_cast<Condition>(instr & CondMask));
7772ccccb3ff40c64927817a7e1ddf1da8c188ed224Douglas Gregor    addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
7782ccccb3ff40c64927817a7e1ddf1da8c188ed224Douglas Gregor    return;
7792ccccb3ff40c64927817a7e1ddf1da8c188ed224Douglas Gregor  } else {
78054abf7d4fa3123b8324c09d2a4dfb789fd818403John McCall    // Register offset.
78154abf7d4fa3123b8324c09d2a4dfb789fd818403John McCall    ASSERT((am & (P|W)) == P || !x.rm_.is(pc));  // no pc index with writeback
782e8f5a1710a7738deff40e10efcd05b1bd6af184fDouglas Gregor    instr |= x.rm_.code();
78323c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor  }
784e8f5a1710a7738deff40e10efcd05b1bd6af184fDouglas Gregor  ASSERT((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
785dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor  emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
786e8f5a1710a7738deff40e10efcd05b1bd6af184fDouglas Gregor}
787e8f5a1710a7738deff40e10efcd05b1bd6af184fDouglas Gregor
788e8904e992ca5e821b199c4577e8b5e5b17a33b1dChris Lattner
789ff38491c18b060526d754765b952f4a497a89416Chris Lattnervoid Assembler::addrmod4(Instr instr, Register rn, RegList rl) {
790a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek  ASSERT((instr & ~(CondMask | P | U | W | L)) == B27);
791df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  ASSERT(rl != 0);
792f1de0ca05e2df6f23bd559028693a12d1ebdaaf6Fariborz Jahanian  ASSERT(!rn.is(pc));
7931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  emit(instr | rn.code()*B16 | rl);
7949e0493576af77dba1c48858c03e31a2897d0681eTed Kremenek}
7959e0493576af77dba1c48858c03e31a2897d0681eTed Kremenek
7969e0493576af77dba1c48858c03e31a2897d0681eTed Kremenek
7979e0493576af77dba1c48858c03e31a2897d0681eTed Kremenekvoid Assembler::addrmod5(Instr instr, CRegister crd, const MemOperand& x) {
7989e0493576af77dba1c48858c03e31a2897d0681eTed Kremenek  // Unindexed addressing is not encoded by this function.
799e8f5a1710a7738deff40e10efcd05b1bd6af184fDouglas Gregor  ASSERT_EQ((B27 | B26),
80023c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor            (instr & ~(CondMask | CoprocessorMask | P | U | N | W | L)));
801e8f5a1710a7738deff40e10efcd05b1bd6af184fDouglas Gregor  ASSERT(x.rn_.is_valid() && !x.rm_.is_valid());
802dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor  int am = x.am_;
803e8f5a1710a7738deff40e10efcd05b1bd6af184fDouglas Gregor  int offset_8 = x.offset_;
804e8f5a1710a7738deff40e10efcd05b1bd6af184fDouglas Gregor  ASSERT((offset_8 & 3) == 0);  // offset must be an aligned word offset
8059e0493576af77dba1c48858c03e31a2897d0681eTed Kremenek  offset_8 >>= 2;
806bef1185418705e16012b3dd50cd7c260c8d6b79cSteve Naroff  if (offset_8 < 0) {
8072fc5c2428ecb450a3256c8316b93b8655cb76a0fChris Lattner    offset_8 = -offset_8;
808e8904e992ca5e821b199c4577e8b5e5b17a33b1dChris Lattner    am ^= U;
80984c431088693e216193094d1dbf327a01173f57fSteve Naroff  }
81084c431088693e216193094d1dbf327a01173f57fSteve Naroff  ASSERT(is_uint8(offset_8));  // unsigned word offset must fit in a byte
8111ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner  ASSERT((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
8121ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner
813e8904e992ca5e821b199c4577e8b5e5b17a33b1dChris Lattner  // Post-indexed addressing requires W == 1; different than in addrmod2/3.
814e8904e992ca5e821b199c4577e8b5e5b17a33b1dChris Lattner  if ((am & P) == 0)
815d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall    am |= W;
816e8904e992ca5e821b199c4577e8b5e5b17a33b1dChris Lattner
8171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ASSERT(offset_8 >= 0);  // no masking needed
8184f4fd92c6c64ecbc65507f63ddd09211f732622cFariborz Jahanian  emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8);
819df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner}
820ff38491c18b060526d754765b952f4a497a89416Chris Lattner
8211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8229e0493576af77dba1c48858c03e31a2897d0681eTed Kremenekint Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
8239e0493576af77dba1c48858c03e31a2897d0681eTed Kremenek  int target_pos;
8241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (L->is_bound()) {
825ff38491c18b060526d754765b952f4a497a89416Chris Lattner    target_pos = L->pos();
826d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  } else {
82754abf7d4fa3123b8324c09d2a4dfb789fd818403John McCall    if (L->is_linked()) {
8281f7b6f88f18d7f6b10265acec5d41c4ed1897487Fariborz Jahanian      target_pos = L->pos();  // L's link
8294f4fd92c6c64ecbc65507f63ddd09211f732622cFariborz Jahanian    } else {
8304f4fd92c6c64ecbc65507f63ddd09211f732622cFariborz Jahanian      target_pos = kEndOfChain;
8314f4fd92c6c64ecbc65507f63ddd09211f732622cFariborz Jahanian    }
8321c6a3cc88177c67498fccdf14cfdf09959214e41Ted Kremenek    L->link_to(pc_offset());
83354abf7d4fa3123b8324c09d2a4dfb789fd818403John McCall  }
83454abf7d4fa3123b8324c09d2a4dfb789fd818403John McCall
835ff38491c18b060526d754765b952f4a497a89416Chris Lattner  // Block the emission of the constant pool, since the branch instruction must
836f28b264437053fb0deacc9ba02b18a0966f7290aSteve Naroff  // be emitted at the pc offset recorded by the label.
83768d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroff  BlockConstPoolBefore(pc_offset() + kInstrSize);
838e294d3fbaffcbc0cf5f16067ab31d2b2763d25e9Chris Lattner  return target_pos - (pc_offset() + kPcLoadDelta);
8391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}
840ff38491c18b060526d754765b952f4a497a89416Chris Lattner
841e294d3fbaffcbc0cf5f16067ab31d2b2763d25e9Chris Lattner
8421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid Assembler::label_at_put(Label* L, int at_offset) {
843ff38491c18b060526d754765b952f4a497a89416Chris Lattner  int target_pos;
844df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  if (L->is_bound()) {
845ff38491c18b060526d754765b952f4a497a89416Chris Lattner    target_pos = L->pos();
846ff38491c18b060526d754765b952f4a497a89416Chris Lattner  } else {
847ff38491c18b060526d754765b952f4a497a89416Chris Lattner    if (L->is_linked()) {
848ff38491c18b060526d754765b952f4a497a89416Chris Lattner      target_pos = L->pos();  // L's link
8491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    } else {
850e294d3fbaffcbc0cf5f16067ab31d2b2763d25e9Chris Lattner      target_pos = kEndOfChain;
851e294d3fbaffcbc0cf5f16067ab31d2b2763d25e9Chris Lattner    }
852e294d3fbaffcbc0cf5f16067ab31d2b2763d25e9Chris Lattner    L->link_to(at_offset);
853e294d3fbaffcbc0cf5f16067ab31d2b2763d25e9Chris Lattner    instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
854ff38491c18b060526d754765b952f4a497a89416Chris Lattner  }
855e294d3fbaffcbc0cf5f16067ab31d2b2763d25e9Chris Lattner}
856df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner
857bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt
8587ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff// Branch instructions.
85940ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregorvoid Assembler::b(int branch_offset, Condition cond) {
86040ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregor  ASSERT((branch_offset & 3) == 0);
86140ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregor  int imm24 = branch_offset >> 2;
86240ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregor  ASSERT(is_int24(imm24));
86340ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregor  emit(cond | B27 | B25 | (imm24 & Imm24Mask));
86440ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregor
86540ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregor  if (cond == al) {
86640ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregor    // Dead code is a good location to emit the constant pool.
86740ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregor    CheckConstPool(false, false);
86840ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregor  }
86940ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregor}
87040ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregor
87140ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregor
87240ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregorvoid Assembler::bl(int branch_offset, Condition cond) {
873df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  ASSERT((branch_offset & 3) == 0);
874ff38491c18b060526d754765b952f4a497a89416Chris Lattner  int imm24 = branch_offset >> 2;
875ff38491c18b060526d754765b952f4a497a89416Chris Lattner  ASSERT(is_int24(imm24));
8764985aceceb9b9261b876b515d32726175c13a775Steve Naroff  emit(cond | B27 | B25 | B24 | (imm24 & Imm24Mask));
8771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}
878e294d3fbaffcbc0cf5f16067ab31d2b2763d25e9Chris Lattner
879e294d3fbaffcbc0cf5f16067ab31d2b2763d25e9Chris Lattner
880ff38491c18b060526d754765b952f4a497a89416Chris Lattnervoid Assembler::blx(int branch_offset) {  // v5 and above
8811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  WriteRecordedPositions();
882e294d3fbaffcbc0cf5f16067ab31d2b2763d25e9Chris Lattner  ASSERT((branch_offset & 1) == 0);
883e294d3fbaffcbc0cf5f16067ab31d2b2763d25e9Chris Lattner  int h = ((branch_offset & 2) >> 1)*B24;
884e294d3fbaffcbc0cf5f16067ab31d2b2763d25e9Chris Lattner  int imm24 = branch_offset >> 2;
8851f5537aaac1e775aff1d523f2cc59a9a3bd6c946Douglas Gregor  ASSERT(is_int24(imm24));
8861f5537aaac1e775aff1d523f2cc59a9a3bd6c946Douglas Gregor  emit(15 << 28 | B27 | B25 | h | (imm24 & Imm24Mask));
8871f5537aaac1e775aff1d523f2cc59a9a3bd6c946Douglas Gregor}
8881f5537aaac1e775aff1d523f2cc59a9a3bd6c946Douglas Gregor
8891f5537aaac1e775aff1d523f2cc59a9a3bd6c946Douglas Gregor
89040ed9a13f5b67b2941f5a9521616e57e9e31ba97Douglas Gregorvoid Assembler::blx(Register target, Condition cond) {  // v5 and above
8911f5537aaac1e775aff1d523f2cc59a9a3bd6c946Douglas Gregor  WriteRecordedPositions();
8921f5537aaac1e775aff1d523f2cc59a9a3bd6c946Douglas Gregor  ASSERT(!target.is(pc));
8931f5537aaac1e775aff1d523f2cc59a9a3bd6c946Douglas Gregor  emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | 3*B4 | target.code());
8941f5537aaac1e775aff1d523f2cc59a9a3bd6c946Douglas Gregor}
8951f5537aaac1e775aff1d523f2cc59a9a3bd6c946Douglas Gregor
8961f5537aaac1e775aff1d523f2cc59a9a3bd6c946Douglas Gregor
897ff38491c18b060526d754765b952f4a497a89416Chris Lattnervoid Assembler::bx(Register target, Condition cond) {  // v5 and above, plus v4t
8984b6c9051c6522894978c9ba6a819a659d102db36Fariborz Jahanian  WriteRecordedPositions();
8992fc5c2428ecb450a3256c8316b93b8655cb76a0fChris Lattner  ASSERT(!target.is(pc));  // use of pc is actually allowed, but discouraged
900df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | B4 | target.code());
901ff38491c18b060526d754765b952f4a497a89416Chris Lattner}
902ff38491c18b060526d754765b952f4a497a89416Chris Lattner
903ff38491c18b060526d754765b952f4a497a89416Chris Lattner
9041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// Data-processing instructions.
905335eafa5be51f6440672a74c73d588af72e96732Steve Naroff
9061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// UBFX <Rd>,<Rn>,#<lsb>,#<width - 1>
907ff38491c18b060526d754765b952f4a497a89416Chris Lattner// Instruction details available in ARM DDI 0406A, A8-464.
908df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner// cond(31-28) | 01111(27-23)| 1(22) | 1(21) | widthm1(20-16) |
909ff38491c18b060526d754765b952f4a497a89416Chris Lattner//  Rd(15-12) | lsb(11-7) | 101(6-4) | Rn(3-0)
910df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattnervoid Assembler::ubfx(Register dst, Register src1, const Operand& src2,
911335eafa5be51f6440672a74c73d588af72e96732Steve Naroff                     const Operand& src3, Condition cond) {
9124985aceceb9b9261b876b515d32726175c13a775Steve Naroff  ASSERT(!src2.rm_.is_valid() && !src3.rm_.is_valid());
913ff38491c18b060526d754765b952f4a497a89416Chris Lattner  ASSERT(static_cast<uint32_t>(src2.imm32_) <= 0x1f);
9144985aceceb9b9261b876b515d32726175c13a775Steve Naroff  ASSERT(static_cast<uint32_t>(src3.imm32_) <= 0x1f);
915ff38491c18b060526d754765b952f4a497a89416Chris Lattner  emit(cond | 0x3F*B21 | src3.imm32_*B16 |
916ff38491c18b060526d754765b952f4a497a89416Chris Lattner       dst.code()*B12 | src2.imm32_*B7 | 0x5*B4 | src1.code());
9171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}
918ff38491c18b060526d754765b952f4a497a89416Chris Lattner
919ff38491c18b060526d754765b952f4a497a89416Chris Lattner
9204f4fd92c6c64ecbc65507f63ddd09211f732622cFariborz Jahanianvoid Assembler::and_(Register dst, Register src1, const Operand& src2,
921d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall                     SBit s, Condition cond) {
9224f4fd92c6c64ecbc65507f63ddd09211f732622cFariborz Jahanian  addrmod1(cond | 0*B21 | s, src1, dst, src2);
9234f4fd92c6c64ecbc65507f63ddd09211f732622cFariborz Jahanian}
9244f4fd92c6c64ecbc65507f63ddd09211f732622cFariborz Jahanian
9254f4fd92c6c64ecbc65507f63ddd09211f732622cFariborz Jahanian
9264f4fd92c6c64ecbc65507f63ddd09211f732622cFariborz Jahanianvoid Assembler::eor(Register dst, Register src1, const Operand& src2,
9274985aceceb9b9261b876b515d32726175c13a775Steve Naroff                    SBit s, Condition cond) {
9281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  addrmod1(cond | 1*B21 | s, src1, dst, src2);
929ff38491c18b060526d754765b952f4a497a89416Chris Lattner}
930e3a2ca7e30601cdd31c77a830f4cc487851e8096Fariborz Jahanian
9311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9329e0493576af77dba1c48858c03e31a2897d0681eTed Kremenekvoid Assembler::sub(Register dst, Register src1, const Operand& src2,
9339e0493576af77dba1c48858c03e31a2897d0681eTed Kremenek                    SBit s, Condition cond) {
9341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  addrmod1(cond | 2*B21 | s, src1, dst, src2);
9353688fc679389d67b6755e62406998f9ea84d886aFariborz Jahanian}
936d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall
937ff38491c18b060526d754765b952f4a497a89416Chris Lattner
938ff38491c18b060526d754765b952f4a497a89416Chris Lattnervoid Assembler::rsb(Register dst, Register src1, const Operand& src2,
939d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall                    SBit s, Condition cond) {
94054abf7d4fa3123b8324c09d2a4dfb789fd818403John McCall  addrmod1(cond | 3*B21 | s, src1, dst, src2);
9413688fc679389d67b6755e62406998f9ea84d886aFariborz Jahanian}
9424f4fd92c6c64ecbc65507f63ddd09211f732622cFariborz Jahanian
9434f4fd92c6c64ecbc65507f63ddd09211f732622cFariborz Jahanian
9441e37765c9257ef1d051f54a674eaa964bdba9693Ted Kremenekvoid Assembler::add(Register dst, Register src1, const Operand& src2,
945335eafa5be51f6440672a74c73d588af72e96732Steve Naroff                    SBit s, Condition cond) {
94654abf7d4fa3123b8324c09d2a4dfb789fd818403John McCall  addrmod1(cond | 4*B21 | s, src1, dst, src2);
9471e37765c9257ef1d051f54a674eaa964bdba9693Ted Kremenek
9481e37765c9257ef1d051f54a674eaa964bdba9693Ted Kremenek  // Eliminate pattern: push(r), pop()
9491e37765c9257ef1d051f54a674eaa964bdba9693Ted Kremenek  //   str(src, MemOperand(sp, 4, NegPreIndex), al);
9501e37765c9257ef1d051f54a674eaa964bdba9693Ted Kremenek  //   add(sp, sp, Operand(kPointerSize));
9511e37765c9257ef1d051f54a674eaa964bdba9693Ted Kremenek  // Both instructions can be eliminated.
9521e37765c9257ef1d051f54a674eaa964bdba9693Ted Kremenek  if (can_peephole_optimize(2) &&
95354abf7d4fa3123b8324c09d2a4dfb789fd818403John McCall      // Pattern.
954294494e1cce92043562b4680c613df7fd028c02eSteve Naroff      instr_at(pc_ - 1 * kInstrSize) == kPopInstruction &&
955294494e1cce92043562b4680c613df7fd028c02eSteve Naroff      (instr_at(pc_ - 2 * kInstrSize) & ~RdMask) == kPushRegPattern) {
956dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    pc_ -= 2 * kInstrSize;
957dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    if (FLAG_print_peephole_optimization) {
958dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff      PrintF("%x push(reg)/pop() eliminated\n", pc_offset());
9597caeabd868d46cf4e68478c6e9136dae4e735d21Chris Lattner    }
960d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  }
96171b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis}
96271b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis
96371b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis
964e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattnervoid Assembler::adc(Register dst, Register src1, const Operand& src2,
9651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                    SBit s, Condition cond) {
96671b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis  addrmod1(cond | 5*B21 | s, src1, dst, src2);
9671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}
968e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner
9691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
970e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattnervoid Assembler::sbc(Register dst, Register src1, const Operand& src2,
97155385fe3e723cd675001e45f42d61adde6b7f075Douglas Gregor                    SBit s, Condition cond) {
97255385fe3e723cd675001e45f42d61adde6b7f075Douglas Gregor  addrmod1(cond | 6*B21 | s, src1, dst, src2);
97355385fe3e723cd675001e45f42d61adde6b7f075Douglas Gregor}
974dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor
97555385fe3e723cd675001e45f42d61adde6b7f075Douglas Gregor
97655385fe3e723cd675001e45f42d61adde6b7f075Douglas Gregorvoid Assembler::rsc(Register dst, Register src1, const Operand& src2,
977e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner                    SBit s, Condition cond) {
978e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner  addrmod1(cond | 7*B21 | s, src1, dst, src2);
979e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner}
980e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner
981e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner
982e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattnervoid Assembler::tst(Register src1, const Operand& src2, Condition cond) {
983e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner  addrmod1(cond | 8*B21 | S, src1, r0, src2);
98471b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis}
985e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner
9861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
987e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattnervoid Assembler::teq(Register src1, const Operand& src2, Condition cond) {
988e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner  addrmod1(cond | 9*B21 | S, src1, r0, src2);
989e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner}
990e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner
9911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
992e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattnervoid Assembler::cmp(Register src1, const Operand& src2, Condition cond) {
993e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner  addrmod1(cond | 10*B21 | S, src1, r0, src2);
994e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner}
995e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner
996e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner
9971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid Assembler::cmn(Register src1, const Operand& src2, Condition cond) {
998e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner  addrmod1(cond | 11*B21 | S, src1, r0, src2);
9991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}
1000e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner
1001e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner
1002e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattnervoid Assembler::orr(Register dst, Register src1, const Operand& src2,
1003e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner                    SBit s, Condition cond) {
1004e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner  addrmod1(cond | 12*B21 | s, src1, dst, src2);
1005e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner}
1006e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner
1007dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
1008dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroffvoid Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) {
1009dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  if (dst.is(pc)) {
1010dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    WriteRecordedPositions();
1011dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  }
1012dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  // Don't allow nop instructions in the form mov rn, rn to be generated using
1013dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  // the mov instruction. They must be generated using nop(int)
1014dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  // pseudo instructions.
1015dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  ASSERT(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al));
1016dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  addrmod1(cond | 13*B21 | s, r0, dst, src);
1017dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff}
1018dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
1019dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
1020dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroffvoid Assembler::bic(Register dst, Register src1, const Operand& src2,
1021dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff                    SBit s, Condition cond) {
1022ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff  addrmod1(cond | 14*B21 | s, src1, dst, src2);
1023dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff}
1024dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
10251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1026dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroffvoid Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) {
1027d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  addrmod1(cond | 15*B21 | s, r0, dst, src);
102883c481ade785a919ba21a33f9a8b1b21c1212fb3Fariborz Jahanian}
102960fcceeedbfc8b4a99cb942e2bc5aeb9e2f92a1fSteve Naroff
1030df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner
1031d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall// Multiply instructions.
1032e13594279a952537ac903325efff57e3edca79d9Chris Lattnervoid Assembler::mla(Register dst, Register src1, Register src2, Register srcA,
10331a0d31a3d7f14ddc6370ba912c778aece6c12cf0Douglas Gregor                    SBit s, Condition cond) {
103472de6676bd30f9081ee4166bbe07b4c270258ce6Douglas Gregor  ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
1035ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff  emit(cond | A | s | dst.code()*B16 | srcA.code()*B12 |
10361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump       src2.code()*B8 | B7 | B4 | src1.code());
1037ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff}
1038df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner
1039ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff
10401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid Assembler::mul(Register dst, Register src1, Register src2,
1041ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff                    SBit s, Condition cond) {
1042df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
1043f13ca06e57ac094ed05ea08c26a499af1ba0ce88Douglas Gregor  // dst goes in bits 16-19 for this instruction!
1044849b243d4065f56742a4677d6dc8277609a151f8Douglas Gregor  emit(cond | s | dst.code()*B16 | src2.code()*B8 | B7 | B4 | src1.code());
1045ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff}
1046ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff
1047ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff
10481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid Assembler::smlal(Register dstL,
1049ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff                      Register dstH,
1050df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner                      Register src1,
1051ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff                      Register src2,
1052c38c3e1e726630458154534227d74eda833d26a0Douglas Gregor                      SBit s,
1053c38c3e1e726630458154534227d74eda833d26a0Douglas Gregor                      Condition cond) {
105423c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1055dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor  ASSERT(!dstL.is(dstH));
1056c38c3e1e726630458154534227d74eda833d26a0Douglas Gregor  emit(cond | B23 | B22 | A | s | dstH.code()*B16 | dstL.code()*B12 |
1057c38c3e1e726630458154534227d74eda833d26a0Douglas Gregor       src2.code()*B8 | B7 | B4 | src1.code());
1058861cf3effdc0fbc97d401539bc3050da76b2476fSteve Naroff}
1059ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff
1060ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff
1061ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroffvoid Assembler::smull(Register dstL,
1062ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff                      Register dstH,
1063861cf3effdc0fbc97d401539bc3050da76b2476fSteve Naroff                      Register src1,
1064ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff                      Register src2,
10651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                      SBit s,
1066ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff                      Condition cond) {
1067ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1068ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff  ASSERT(!dstL.is(dstH));
1069ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff  emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 |
1070ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff       src2.code()*B8 | B7 | B4 | src1.code());
10711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}
1072c38c3e1e726630458154534227d74eda833d26a0Douglas Gregor
107323c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor
1074e6b1bb6e7fe906d164637ca33503b8fafdbc99e5Douglas Gregorvoid Assembler::umlal(Register dstL,
1075dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor                      Register dstH,
1076c38c3e1e726630458154534227d74eda833d26a0Douglas Gregor                      Register src1,
1077c38c3e1e726630458154534227d74eda833d26a0Douglas Gregor                      Register src2,
1078bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall                      SBit s,
1079bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall                      Condition cond) {
1080d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1081bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall  ASSERT(!dstL.is(dstH));
1082d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  emit(cond | B23 | A | s | dstH.code()*B16 | dstL.code()*B12 |
1083bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall       src2.code()*B8 | B7 | B4 | src1.code());
1084d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall}
1085d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall
1086bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall
1087bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCallvoid Assembler::umull(Register dstL,
1088bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall                      Register dstH,
1089d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall                      Register src1,
1090bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall                      Register src2,
1091d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall                      SBit s,
109223c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor                      Condition cond) {
1093bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1094bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall  ASSERT(!dstL.is(dstH));
10950bd04596e4645ff145a046dfb3475f39674060d9Fariborz Jahanian  emit(cond | B23 | s | dstH.code()*B16 | dstL.code()*B12 |
10960bd04596e4645ff145a046dfb3475f39674060d9Fariborz Jahanian       src2.code()*B8 | B7 | B4 | src1.code());
1097bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall}
1098bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall
1099bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall
1100bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall// Miscellaneous arithmetic instructions.
1101e13594279a952537ac903325efff57e3edca79d9Chris Lattnervoid Assembler::clz(Register dst, Register src, Condition cond) {
1102e13594279a952537ac903325efff57e3edca79d9Chris Lattner  // v5 and above.
1103bdd563ec391b0a83fc6d04b8a8ea3022aa702f74John McCall  ASSERT(!dst.is(pc) && !src.is(pc));
11041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  emit(cond | B24 | B22 | B21 | 15*B16 | dst.code()*B12 |
1105df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner       15*B8 | B4 | src.code());
1106ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff}
1107ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff
1108ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff
1109ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff// Status register access instructions.
1110ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroffvoid Assembler::mrs(Register dst, SRegister s, Condition cond) {
1111ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff  ASSERT(!dst.is(pc));
1112ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff  emit(cond | B24 | s | 15*B16 | dst.code()*B12);
111360fcceeedbfc8b4a99cb942e2bc5aeb9e2f92a1fSteve Naroff}
11148749be53f53384e7846502791ceda6c657228d07Steve Naroff
11158749be53f53384e7846502791ceda6c657228d07Steve Naroff
111623c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregorvoid Assembler::msr(SRegisterFieldMask fields, const Operand& src,
1117beaaccd8e2a8748f77b66e2b330fb9136937e14cJay Foad                    Condition cond) {
11181bfe1c2129771c06fb58ae5e8c079ae30e138309Daniel Dunbar  ASSERT(fields >= B16 && fields < B20);  // at least one field set
1119ddbff78fb719a645b04bd27099fa6ec8c4693b3cSteve Naroff  Instr instr;
11205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  if (!src.rm_.is_valid()) {
1121dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    // Immediate.
1122dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    uint32_t rotate_imm;
1123dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    uint32_t immed_8;
1124dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    if (MustUseIp(src.rmode_) ||
1125dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff        !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) {
1126dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff      // Immediate operand cannot be encoded, load it first to register ip.
11271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      RecordRelocInfo(src.rmode_, src.imm32_);
11281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      ldr(ip, MemOperand(pc, 0), cond);
11291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      msr(fields, Operand(ip), cond);
1130dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff      return;
1131dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    }
1132dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    instr = I | rotate_imm*B8 | immed_8;
1133dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  } else {
1134dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    ASSERT(!src.rs_.is_valid() && src.shift_imm_ == 0);  // only rm allowed
1135dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff    instr = src.rm_.code();
11363536b443bc50d58a79f14fca9b6842541a434854Steve Naroff  }
1137dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff  emit(cond | instr | B24 | B21 | fields | 15*B12);
1138d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall}
1139b28317a8e5e0e2953d1e5406d753d6c3c7f1e7d2Chris Lattner
1140861cf3effdc0fbc97d401539bc3050da76b2476fSteve Naroff
11417ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff// Load/Store instructions.
11427ef58fdbefddf693910e6403a71b3d367444c897Steve Naroffvoid Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
11431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (dst.is(pc)) {
1144083128f6b13dfa4fc615a838c49b516d901b1ac0Douglas Gregor    WriteRecordedPositions();
114523c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor  }
1146dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor  addrmod2(cond | B26 | L, dst, src);
1147083128f6b13dfa4fc615a838c49b516d901b1ac0Douglas Gregor
1148083128f6b13dfa4fc615a838c49b516d901b1ac0Douglas Gregor  // Eliminate pattern: push(ry), pop(rx)
1149df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  //   str(ry, MemOperand(sp, 4, NegPreIndex), al)
11507ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff  //   ldr(rx, MemOperand(sp, 4, PostIndex), al)
1151d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  // Both instructions can be eliminated if ry = rx.
11527ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff  // If ry != rx, a register copy from ry to rx is inserted
11537ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff  // after eliminating the push and the pop instructions.
11547ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff  Instr push_instr = instr_at(pc_ - 2 * kInstrSize);
11557ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff  Instr pop_instr = instr_at(pc_ - 1 * kInstrSize);
11561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1157df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  if (can_peephole_optimize(2) &&
11587caeabd868d46cf4e68478c6e9136dae4e735d21Chris Lattner      IsPush(push_instr) &&
11597ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff      IsPop(pop_instr)) {
11601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    if ((pop_instr & kRdMask) != (push_instr & kRdMask)) {
1161bc1c877fe28fb6a825f0b226a0a2da99e713ea03Fariborz Jahanian      // For consecutive push and pop on different registers,
11627ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff      // we delete both the push & pop and insert a register move.
11631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      // push ry, pop rx --> mov rx, ry
1164df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner      Register reg_pushed, reg_popped;
11657caeabd868d46cf4e68478c6e9136dae4e735d21Chris Lattner      reg_pushed = GetRd(push_instr);
11667caeabd868d46cf4e68478c6e9136dae4e735d21Chris Lattner      reg_popped = GetRd(pop_instr);
11677caeabd868d46cf4e68478c6e9136dae4e735d21Chris Lattner      pc_ -= 2 * kInstrSize;
11687ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff      // Insert a mov instruction, which is better than a pair of push & pop
11697ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff      mov(reg_popped, reg_pushed);
11707ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff      if (FLAG_print_peephole_optimization) {
1171df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner        PrintF("%x push/pop (diff reg) replaced by a reg move\n", pc_offset());
11727ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff      }
11737ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff    } else {
1174d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall      // For consecutive push and pop on the same register,
11757ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff      // both the push and the pop can be deleted.
11767caeabd868d46cf4e68478c6e9136dae4e735d21Chris Lattner      pc_ -= 2 * kInstrSize;
11777caeabd868d46cf4e68478c6e9136dae4e735d21Chris Lattner      if (FLAG_print_peephole_optimization) {
11787ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff        PrintF("%x push/pop (same reg) eliminated\n", pc_offset());
11791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      }
1180df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner    }
11817ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff  }
11827ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff
11837ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff  if (can_peephole_optimize(2)) {
11847ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff    Instr str_instr = instr_at(pc_ - 2 * kInstrSize);
1185d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall    Instr ldr_instr = instr_at(pc_ - 1 * kInstrSize);
11861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1187e440eb8158e71deb1e4ab11618ae3d680aac6da1Steve Naroff    if ((IsStrRegFpOffset(str_instr) &&
11881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump         IsLdrRegFpOffset(ldr_instr)) ||
1189bc1c877fe28fb6a825f0b226a0a2da99e713ea03Fariborz Jahanian       (IsStrRegFpNegOffset(str_instr) &&
1190bc1c877fe28fb6a825f0b226a0a2da99e713ea03Fariborz Jahanian         IsLdrRegFpNegOffset(ldr_instr))) {
11917caeabd868d46cf4e68478c6e9136dae4e735d21Chris Lattner      if ((ldr_instr & kLdrStrInstrArgumentMask) ==
11921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump            (str_instr & kLdrStrInstrArgumentMask)) {
11937ef58fdbefddf693910e6403a71b3d367444c897Steve Naroff        // Pattern: Ldr/str same fp+offset, same register.
119471b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis        //
11957caeabd868d46cf4e68478c6e9136dae4e735d21Chris Lattner        // The following:
1196d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall        // str rx, [fp, #-12]
119771b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis        // ldr rx, [fp, #-12]
11987caeabd868d46cf4e68478c6e9136dae4e735d21Chris Lattner        //
119971b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis        // Becomes:
120071b0addffbdeed29cc062c962e236c34107755d6Argyrios Kyrtzidis        // str rx, [fp, #-12]
1201d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall
12021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        pc_ -= 1 * kInstrSize;
1203d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall        if (FLAG_print_peephole_optimization) {
1204e13b9595dc1e2f4288bec34f3412359f648e84a5Chris Lattner          PrintF("%x str/ldr (fp + same offset), same reg\n", pc_offset());
1205beaaccd8e2a8748f77b66e2b330fb9136937e14cJay Foad        }
1206beaaccd8e2a8748f77b66e2b330fb9136937e14cJay Foad      } else if ((ldr_instr & kLdrStrOffsetMask) ==
120718df52bbb5d28ca082064d31ae7558dbdae52377Douglas Gregor                 (str_instr & kLdrStrOffsetMask)) {
1208246e70f69cb8aeb67225c54690f1c6b25abd5a86Daniel Dunbar        // Pattern: Ldr/str same fp+offset, different register.
120925e077d59a8e8e43b65882b69610a3d5e2aaf53cFariborz Jahanian        //
1210bc662afa1cb9b61cb1e7808bb1463dd6291b8095Chris Lattner        // The following:
1211dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff        // str rx, [fp, #-12]
1212dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff        // ldr ry, [fp, #-12]
1213dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff        //
1214dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff        // Becomes:
1215dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff        // str rx, [fp, #-12]
1216dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff        // mov ry, rx
1217dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff
1218dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff        Register reg_stored, reg_loaded;
1219dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff        reg_stored = GetRd(str_instr);
1220dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff        reg_loaded = GetRd(ldr_instr);
1221dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff        pc_ -= 1 * kInstrSize;
1222dac269b65eed82182fc3e96566dedd6562dfe11eSteve Naroff        // Insert a mov instruction, which is better than ldr.
1223d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall        mov(reg_loaded, reg_stored);
1224ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian        if (FLAG_print_peephole_optimization) {
1225ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian          PrintF("%x str/ldr (fp + same offset), diff reg \n", pc_offset());
1226ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian        }
1227ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian      }
12281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    }
12293b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor  }
12303b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor
123123c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor  if (can_peephole_optimize(3)) {
1232dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor    Instr mem_write_instr = instr_at(pc_ - 3 * kInstrSize);
12333b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor    Instr ldr_instr = instr_at(pc_ - 2 * kInstrSize);
12343b49aca913dc0c1838321b9bb2dc9a4cb4681922Douglas Gregor    Instr mem_read_instr = instr_at(pc_ - 1 * kInstrSize);
1235df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner    if (IsPush(mem_write_instr) &&
1236ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian        IsPop(mem_read_instr)) {
1237d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall      if ((IsLdrRegFpOffset(ldr_instr) ||
1238ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian        IsLdrRegFpNegOffset(ldr_instr))) {
1239ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian        if ((mem_write_instr & kRdMask) ==
1240ccb4f314248fb2202637d3290f2b17af5646da08Fariborz Jahanian              (mem_read_instr & kRdMask)) {
1241ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian          // Pattern: push & pop from/to same register,
12421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          // with a fp+offset ldr in between
12431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          //
1244ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian          // The following:
1245ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian          // str rx, [sp, #-4]!
1246ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian          // ldr rz, [fp, #-24]
1247ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian          // ldr rx, [sp], #+4
12481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          //
124933ced0b8550f3e7169f326944731ee02e9338659Douglas Gregor          // Becomes:
125023c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor          // if(rx == rz)
1251dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor          //   delete all
125233ced0b8550f3e7169f326944731ee02e9338659Douglas Gregor          // else
125333ced0b8550f3e7169f326944731ee02e9338659Douglas Gregor          //   ldr rz, [fp, #-24]
1254df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner
1255ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian          if ((mem_write_instr & kRdMask) == (ldr_instr & kRdMask)) {
1256ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian            pc_ -= 3 * kInstrSize;
1257ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian          } else {
1258ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian            pc_ -= 3 * kInstrSize;
1259d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall            // Reinsert back the ldr rz.
12601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump            emit(ldr_instr);
1261df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner          }
1262ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian          if (FLAG_print_peephole_optimization) {
1263ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian            PrintF("%x push/pop -dead ldr fp+offset in middle\n", pc_offset());
1264d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall          }
1265ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian        } else {
1266ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian          // Pattern: push & pop from/to different registers
1267d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall          // with a fp+offset ldr in between
12681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          //
12698f3fde00ad4d4f943321e338b914ae4740711c84Fariborz Jahanian          // The following:
1270a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek          // str rx, [sp, #-4]!
127163e963cdffca9530f920dbab58b9b4eecb2a582cFariborz Jahanian          // ldr rz, [fp, #-24]
1272d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall          // ldr ry, [sp], #+4
1273ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian          //
1274ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian          // Becomes:
1275ccb4f314248fb2202637d3290f2b17af5646da08Fariborz Jahanian          // if(ry == rz)
1276ccb4f314248fb2202637d3290f2b17af5646da08Fariborz Jahanian          //   mov ry, rx;
1277df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner          // else if(rx != rz)
1278ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian          //   ldr rz, [fp, #-24]
1279ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian          //   mov ry, rx
1280df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner          // else if((ry != rz) || (rx == rz)) becomes:
1281ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian          //   mov ry, rx
1282d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall          //   ldr rz, [fp, #-24]
1283ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian
1284ccb4f314248fb2202637d3290f2b17af5646da08Fariborz Jahanian          Register reg_pushed, reg_popped;
1285ccb4f314248fb2202637d3290f2b17af5646da08Fariborz Jahanian          if ((mem_read_instr & kRdMask) == (ldr_instr & kRdMask)) {
1286ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian            reg_pushed = GetRd(mem_write_instr);
1287d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall            reg_popped = GetRd(mem_read_instr);
1288cb53b361bce341c8591333c6997f62e480acc0b4Chris Lattner            pc_ -= 3 * kInstrSize;
1289ccb4f314248fb2202637d3290f2b17af5646da08Fariborz Jahanian            mov(reg_popped, reg_pushed);
12901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          } else if ((mem_write_instr & kRdMask)
129160fcceeedbfc8b4a99cb942e2bc5aeb9e2f92a1fSteve Naroff                                != (ldr_instr & kRdMask)) {
129283c481ade785a919ba21a33f9a8b1b21c1212fb3Fariborz Jahanian            reg_pushed = GetRd(mem_write_instr);
129301f1bfc3284d5817517d35217885ea9ecb252817Fariborz Jahanian            reg_popped = GetRd(mem_read_instr);
1294a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek            pc_ -= 3 * kInstrSize;
129563e963cdffca9530f920dbab58b9b4eecb2a582cFariborz Jahanian            emit(ldr_instr);
129663e963cdffca9530f920dbab58b9b4eecb2a582cFariborz Jahanian            mov(reg_popped, reg_pushed);
1297d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall          } else if (((mem_read_instr & kRdMask)
12985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                                     != (ldr_instr & kRdMask)) ||
129960fcceeedbfc8b4a99cb942e2bc5aeb9e2f92a1fSteve Naroff                    ((mem_write_instr & kRdMask)
1300d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall                                     == (ldr_instr & kRdMask)) ) {
1301ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian            reg_pushed = GetRd(mem_write_instr);
1302ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian            reg_popped = GetRd(mem_read_instr);
1303d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall            pc_ -= 3 * kInstrSize;
1304ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian            mov(reg_popped, reg_pushed);
1305a6e3ac514c924879699c6b0b1201028f0091044fFariborz Jahanian            emit(ldr_instr);
130623c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor          }
1307d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall          if (FLAG_print_peephole_optimization) {
130863e963cdffca9530f920dbab58b9b4eecb2a582cFariborz Jahanian            PrintF("%x push/pop (ldr fp+off in middle)\n", pc_offset());
1309a6e3ac514c924879699c6b0b1201028f0091044fFariborz Jahanian          }
1310782f2f52b78d8ca785110398a7f7b56b830b9ac7Ted Kremenek        }
1311782f2f52b78d8ca785110398a7f7b56b830b9ac7Ted Kremenek      }
1312782f2f52b78d8ca785110398a7f7b56b830b9ac7Ted Kremenek    }
1313782f2f52b78d8ca785110398a7f7b56b830b9ac7Ted Kremenek  }
1314a6e3ac514c924879699c6b0b1201028f0091044fFariborz Jahanian}
13155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1316e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanian
13173fe104154dd2e8ffb351142d74f308938b5c99bfFariborz Jahanianvoid Assembler::str(Register src, const MemOperand& dst, Condition cond) {
13183fe104154dd2e8ffb351142d74f308938b5c99bfFariborz Jahanian  addrmod2(cond | B26, src, dst);
131963e963cdffca9530f920dbab58b9b4eecb2a582cFariborz Jahanian
1320d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  // Eliminate pattern: pop(), push(r)
1321d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  //     add sp, sp, #4 LeaveCC, al; str r, [sp, #-4], al
132223c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor  // ->  str r, [sp, 0], al
132363e963cdffca9530f920dbab58b9b4eecb2a582cFariborz Jahanian  if (can_peephole_optimize(2) &&
132463e963cdffca9530f920dbab58b9b4eecb2a582cFariborz Jahanian     // Pattern.
132563e963cdffca9530f920dbab58b9b4eecb2a582cFariborz Jahanian     instr_at(pc_ - 1 * kInstrSize) == (kPushRegPattern | src.code() * B12) &&
1326e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanian     instr_at(pc_ - 2 * kInstrSize) == kPopInstruction) {
1327e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanian    pc_ -= 2 * kInstrSize;
1328e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanian    emit(al | B26 | 0 | Offset | sp.code() * B16 | src.code() * B12);
1329d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall    if (FLAG_print_peephole_optimization) {
1330e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanian      PrintF("%x pop()/push(reg) eliminated\n", pc_offset());
1331e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanian    }
1332e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanian  }
1333df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner}
1334e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanian
1335d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall
1336e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanianvoid Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) {
1337243b64b0001172405ff803c61bdcaa8e98ec1552Fariborz Jahanian  addrmod2(cond | B26 | B | L, dst, src);
1338243b64b0001172405ff803c61bdcaa8e98ec1552Fariborz Jahanian}
1339df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner
1340e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanian
1341d226f65006733ed7f709c3174f22ce33391cb58fJohn McCallvoid Assembler::strb(Register src, const MemOperand& dst, Condition cond) {
1342e992af01d14e2e31037562c123af0a71ae1ed374Fariborz Jahanian  addrmod2(cond | B26 | B, src, dst);
1343243b64b0001172405ff803c61bdcaa8e98ec1552Fariborz Jahanian}
1344243b64b0001172405ff803c61bdcaa8e98ec1552Fariborz Jahanian
1345243b64b0001172405ff803c61bdcaa8e98ec1552Fariborz Jahanian
13461ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattnervoid Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) {
1347d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  addrmod3(cond | L | B7 | H | B4, dst, src);
1348243b64b0001172405ff803c61bdcaa8e98ec1552Fariborz Jahanian}
1349b28317a8e5e0e2953d1e5406d753d6c3c7f1e7d2Chris Lattner
1350b28317a8e5e0e2953d1e5406d753d6c3c7f1e7d2Chris Lattner
13515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid Assembler::strh(Register src, const MemOperand& dst, Condition cond) {
13525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  addrmod3(cond | B7 | H | B4, src, dst);
1353ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian}
1354ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian
1355ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian
1356ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanianvoid Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) {
1357ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian  addrmod3(cond | L | B7 | S6 | B4, dst, src);
1358ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian}
1359ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian
1360ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian
1361ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanianvoid Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) {
1362ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian  addrmod3(cond | L | B7 | S6 | H | B4, dst, src);
1363ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian}
1364d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall
1365ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian
1366ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanianvoid Assembler::ldrd(Register dst1, Register dst2,
1367f624f8186d8fe474350051c6d3f00b2c204fbeaeFariborz Jahanian                     const MemOperand& src, Condition cond) {
13681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ASSERT(CpuFeatures::IsEnabled(ARMv7));
1369b328c4251a9d2db704b3bd46ec04884dc8e56332Douglas Gregor  ASSERT(src.rm().is(no_reg));
1370322328b8a65ad2e45829eb06d245addb64037f6fDouglas Gregor  ASSERT(!dst1.is(lr));  // r14.
137123c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor  ASSERT_EQ(0, dst1.code() % 2);
1372dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor  ASSERT_EQ(dst1.code() + 1, dst2.code());
1373322328b8a65ad2e45829eb06d245addb64037f6fDouglas Gregor  addrmod3(cond | B7 | B6 | B4, dst1, src);
1374322328b8a65ad2e45829eb06d245addb64037f6fDouglas Gregor}
1375b328c4251a9d2db704b3bd46ec04884dc8e56332Douglas Gregor
1376b328c4251a9d2db704b3bd46ec04884dc8e56332Douglas Gregor
1377b328c4251a9d2db704b3bd46ec04884dc8e56332Douglas Gregorvoid Assembler::strd(Register src1, Register src2,
1378d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall                     const MemOperand& dst, Condition cond) {
1379b328c4251a9d2db704b3bd46ec04884dc8e56332Douglas Gregor  ASSERT(dst.rm().is(no_reg));
1380b328c4251a9d2db704b3bd46ec04884dc8e56332Douglas Gregor  ASSERT(!src1.is(lr));  // r14.
1381f624f8186d8fe474350051c6d3f00b2c204fbeaeFariborz Jahanian  ASSERT_EQ(0, src1.code() % 2);
1382f624f8186d8fe474350051c6d3f00b2c204fbeaeFariborz Jahanian  ASSERT_EQ(src1.code() + 1, src2.code());
1383f624f8186d8fe474350051c6d3f00b2c204fbeaeFariborz Jahanian  ASSERT(CpuFeatures::IsEnabled(ARMv7));
1384df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  addrmod3(cond | B7 | B6 | B5 | B4, src1, dst);
1385ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian}
1386ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian
1387322328b8a65ad2e45829eb06d245addb64037f6fDouglas Gregor// Load/Store multiple instructions.
1388322328b8a65ad2e45829eb06d245addb64037f6fDouglas Gregorvoid Assembler::ldm(BlockAddrMode am,
138923c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor                    Register base,
1390322328b8a65ad2e45829eb06d245addb64037f6fDouglas Gregor                    RegList dst,
1391dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor                    Condition cond) {
1392322328b8a65ad2e45829eb06d245addb64037f6fDouglas Gregor  // ABI stack constraint: ldmxx base, {..sp..}  base != sp  is not restartable.
1393322328b8a65ad2e45829eb06d245addb64037f6fDouglas Gregor  ASSERT(base.is(sp) || (dst & sp.bit()) == 0);
1394df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner
1395ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian  addrmod4(cond | B27 | am | L, base, dst);
1396ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian
1397ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian  // Emit the constant pool after a function return implemented by ldm ..{..pc}.
1398f624f8186d8fe474350051c6d3f00b2c204fbeaeFariborz Jahanian  if (cond == al && (dst & pc.bit()) != 0) {
1399ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian    // There is a slight chance that the ldm instruction was actually a call,
1400ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian    // in which case it would be wrong to return into the constant pool; we
140123c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor    // recognize this case by checking if the emission of the pool was blocked
1402f624f8186d8fe474350051c6d3f00b2c204fbeaeFariborz Jahanian    // at the pc of the ldm instruction by a mov lr, pc instruction; if this is
1403df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner    // the case, we emit a jump over the pool.
1404ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian    CheckConstPool(true, no_const_pool_before_ == pc_offset() - kInstrSize);
1405ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian  }
1406ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian}
1407b328c4251a9d2db704b3bd46ec04884dc8e56332Douglas Gregor
14081ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner
1409b328c4251a9d2db704b3bd46ec04884dc8e56332Douglas Gregorvoid Assembler::stm(BlockAddrMode am,
1410b328c4251a9d2db704b3bd46ec04884dc8e56332Douglas Gregor                    Register base,
1411d3fdcb5a1bf6bd5e54e18579c054ea3c292a0e28Fariborz Jahanian                    RegList src,
1412d3fdcb5a1bf6bd5e54e18579c054ea3c292a0e28Fariborz Jahanian                    Condition cond) {
1413d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  addrmod4(cond | B27 | am, base, src);
1414ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian}
1415ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian
1416ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian
1417ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian// Exception-generating instructions and debugging support.
1418ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanianvoid Assembler::stop(const char* msg) {
1419ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian#ifndef __arm__
1420ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian  // The simulator handles these special instructions and stops execution.
1421ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian  emit(15 << 28 | ((intptr_t) msg));
1422ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian#else  // def __arm__
1423d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall#ifdef CAN_USE_ARMV5_INSTRUCTIONS
1424ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian  bkpt(0);
1425ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian#else  // ndef CAN_USE_ARMV5_INSTRUCTIONS
1426ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian  swi(0x9f0001);
1427424b2a546dbd09cf70d43087771c7fff851ca158Douglas Gregor#endif  // ndef CAN_USE_ARMV5_INSTRUCTIONS
1428424b2a546dbd09cf70d43087771c7fff851ca158Douglas Gregor#endif  // def __arm__
142923c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor}
1430dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor
1431424b2a546dbd09cf70d43087771c7fff851ca158Douglas Gregor
1432424b2a546dbd09cf70d43087771c7fff851ca158Douglas Gregorvoid Assembler::bkpt(uint32_t imm16) {  // v5 and above
1433424b2a546dbd09cf70d43087771c7fff851ca158Douglas Gregor  ASSERT(is_uint16(imm16));
1434424b2a546dbd09cf70d43087771c7fff851ca158Douglas Gregor  emit(al | B24 | B21 | (imm16 >> 4)*B8 | 7*B4 | (imm16 & 0xf));
1435424b2a546dbd09cf70d43087771c7fff851ca158Douglas Gregor}
1436d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall
1437424b2a546dbd09cf70d43087771c7fff851ca158Douglas Gregor
1438424b2a546dbd09cf70d43087771c7fff851ca158Douglas Gregorvoid Assembler::swi(uint32_t imm24, Condition cond) {
1439c35b9e4e2efad727538c848cf30d4b0eb1031dc9Fariborz Jahanian  ASSERT(is_uint24(imm24));
1440c35b9e4e2efad727538c848cf30d4b0eb1031dc9Fariborz Jahanian  emit(cond | 15*B24 | imm24);
144123c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor}
1442c35b9e4e2efad727538c848cf30d4b0eb1031dc9Fariborz Jahanian
1443c35b9e4e2efad727538c848cf30d4b0eb1031dc9Fariborz Jahanian
1444df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner// Coprocessor instructions.
1445ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanianvoid Assembler::cdp(Coprocessor coproc,
1446ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian                    int opcode_1,
1447ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian                    CRegister crd,
144894b24db37e80a75c4088e592d4150fb12b00bfb3Fariborz Jahanian                    CRegister crn,
14491ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner                    CRegister crm,
145094b24db37e80a75c4088e592d4150fb12b00bfb3Fariborz Jahanian                    int opcode_2,
145194b24db37e80a75c4088e592d4150fb12b00bfb3Fariborz Jahanian                    Condition cond) {
145294b24db37e80a75c4088e592d4150fb12b00bfb3Fariborz Jahanian  ASSERT(is_uint4(opcode_1) && is_uint3(opcode_2));
145394b24db37e80a75c4088e592d4150fb12b00bfb3Fariborz Jahanian  emit(cond | B27 | B26 | B25 | (opcode_1 & 15)*B20 | crn.code()*B16 |
1454d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall       crd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | crm.code());
1455ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian}
14561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1457397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian
1458397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanianvoid Assembler::cdp2(Coprocessor coproc,
1459397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian                     int opcode_1,
146043bc2a0973ffe404fabba6f8280cd6bad2c69fcbSebastian Redl                     CRegister crd,
1461ca0408fb49c1370430672acf2d770b7151cf71deJohn McCall                     CRegister crn,
1462397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian                     CRegister crm,
1463df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner                     int opcode_2) {  // v5 and above
146439f8f159c488a900e5958d5aab3e467af9ec8a2bFariborz Jahanian  cdp(coproc, opcode_1, crd, crn, crm, opcode_2, static_cast<Condition>(nv));
14650e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl}
1466397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian
146743bc2a0973ffe404fabba6f8280cd6bad2c69fcbSebastian Redl
1468397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanianvoid Assembler::mcr(Coprocessor coproc,
1469397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian                    int opcode_1,
147002418c7f0cb8bb83f1a1a1fad9bf6104efa83e0eTed Kremenek                    Register rd,
147102418c7f0cb8bb83f1a1a1fad9bf6104efa83e0eTed Kremenek                    CRegister crn,
147223c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor                    CRegister crm,
1473397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian                    int opcode_2,
1474397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian                    Condition cond) {
1475c385c90c68dfa376650e2facfbb444b2ec9bd110Fariborz Jahanian  ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2));
147678a677bbb5fa115fa0995b5783adeeefad67167eFariborz Jahanian  emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | crn.code()*B16 |
1477c385c90c68dfa376650e2facfbb444b2ec9bd110Fariborz Jahanian       rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
147843bc2a0973ffe404fabba6f8280cd6bad2c69fcbSebastian Redl}
147943bc2a0973ffe404fabba6f8280cd6bad2c69fcbSebastian Redl
1480fa3ee8e6776634caf064ba5928ca7699d317a280Fariborz Jahanian
1481fa3ee8e6776634caf064ba5928ca7699d317a280Fariborz Jahanianvoid Assembler::mcr2(Coprocessor coproc,
14821ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner                     int opcode_1,
148343bc2a0973ffe404fabba6f8280cd6bad2c69fcbSebastian Redl                     Register rd,
1484fa3ee8e6776634caf064ba5928ca7699d317a280Fariborz Jahanian                     CRegister crn,
1485fa3ee8e6776634caf064ba5928ca7699d317a280Fariborz Jahanian                     CRegister crm,
14862f7ece7c77eb17e24e8f0f4e1b7fb01aa5111f96Sebastian Redl                     int opcode_2) {  // v5 and above
14870e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  mcr(coproc, opcode_1, rd, crn, crm, opcode_2, static_cast<Condition>(nv));
1488fa3ee8e6776634caf064ba5928ca7699d317a280Fariborz Jahanian}
148943bc2a0973ffe404fabba6f8280cd6bad2c69fcbSebastian Redl
1490fa3ee8e6776634caf064ba5928ca7699d317a280Fariborz Jahanian
1491fa3ee8e6776634caf064ba5928ca7699d317a280Fariborz Jahanianvoid Assembler::mrc(Coprocessor coproc,
14921ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner                    int opcode_1,
149343bc2a0973ffe404fabba6f8280cd6bad2c69fcbSebastian Redl                    Register rd,
1494fa3ee8e6776634caf064ba5928ca7699d317a280Fariborz Jahanian                    CRegister crn,
1495fa3ee8e6776634caf064ba5928ca7699d317a280Fariborz Jahanian                    CRegister crm,
149678a677bbb5fa115fa0995b5783adeeefad67167eFariborz Jahanian                    int opcode_2,
14971ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner                    Condition cond) {
149843bc2a0973ffe404fabba6f8280cd6bad2c69fcbSebastian Redl  ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2));
149978a677bbb5fa115fa0995b5783adeeefad67167eFariborz Jahanian  emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | L | crn.code()*B16 |
15003ac438c383a4a9a73c76a05c76ec5d02f10a3c52Steve Naroff       rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
15013ac438c383a4a9a73c76a05c76ec5d02f10a3c52Steve Naroff}
15028935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor
15033ac438c383a4a9a73c76a05c76ec5d02f10a3c52Steve Naroff
150461364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redlvoid Assembler::mrc2(Coprocessor coproc,
15050e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl                     int opcode_1,
15068935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor                     Register rd,
15070e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl                     CRegister crn,
1508fa3ee8e6776634caf064ba5928ca7699d317a280Fariborz Jahanian                     CRegister crm,
150976ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl                     int opcode_2) {  // v5 and above
1510c385c90c68dfa376650e2facfbb444b2ec9bd110Fariborz Jahanian  mrc(coproc, opcode_1, rd, crn, crm, opcode_2, static_cast<Condition>(nv));
1511c385c90c68dfa376650e2facfbb444b2ec9bd110Fariborz Jahanian}
1512397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian
1513397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian
1514397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanianvoid Assembler::ldc(Coprocessor coproc,
1515397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian                    CRegister crd,
1516397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian                    const MemOperand& src,
1517397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian                    LFlag l,
1518397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian                    Condition cond) {
1519397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian  addrmod5(cond | B27 | B26 | l | L | coproc*B8, crd, src);
1520397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian}
1521397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian
1522397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian
152343bc2a0973ffe404fabba6f8280cd6bad2c69fcbSebastian Redlvoid Assembler::ldc(Coprocessor coproc,
1524397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian                    CRegister crd,
152543bc2a0973ffe404fabba6f8280cd6bad2c69fcbSebastian Redl                    Register rn,
1526397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian                    int option,
1527df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner                    LFlag l,
15281ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner                    Condition cond) {
152943bc2a0973ffe404fabba6f8280cd6bad2c69fcbSebastian Redl  // Unindexed addressing.
1530397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian  ASSERT(is_uint8(option));
15318f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor  emit(cond | B27 | B26 | U | l | L | rn.code()*B16 | crd.code()*B12 |
1532ca0408fb49c1370430672acf2d770b7151cf71deJohn McCall       coproc*B8 | (option & 255));
15338935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor}
153461364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
15358935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor
15360e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redlvoid Assembler::ldc2(Coprocessor coproc,
1537bd49a647afd9cc534fef13cadf652d4e9c396e2bFariborz Jahanian                     CRegister crd,
1538a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl                     const MemOperand& src,
1539df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner                     LFlag l) {  // v5 and above
15406b884508c3bc97cc9df9516adb92fbf88dd0a2e4Chris Lattner  ldc(coproc, crd, src, l, static_cast<Condition>(nv));
15416b884508c3bc97cc9df9516adb92fbf88dd0a2e4Chris Lattner}
15426b884508c3bc97cc9df9516adb92fbf88dd0a2e4Chris Lattner
15436b884508c3bc97cc9df9516adb92fbf88dd0a2e4Chris Lattner
15446b884508c3bc97cc9df9516adb92fbf88dd0a2e4Chris Lattnervoid Assembler::ldc2(Coprocessor coproc,
15456b884508c3bc97cc9df9516adb92fbf88dd0a2e4Chris Lattner                     CRegister crd,
15466b884508c3bc97cc9df9516adb92fbf88dd0a2e4Chris Lattner                     Register rn,
15470e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl                     int option,
1548161a9c5afaafb4d527b7efba9675a8b2cbbe32e0Fariborz Jahanian                     LFlag l) {  // v5 and above
1549cb53b361bce341c8591333c6997f62e480acc0b4Chris Lattner  ldc(coproc, crd, rn, option, l, static_cast<Condition>(nv));
1550d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall}
15513b1191d7eaf2f4984564e01ab84b6713a9d80e70Fariborz Jahanian
1552df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner
1553397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanianvoid Assembler::stc(Coprocessor coproc,
1554e21dd6ffef4585fa43cd3586ed971217d65bf56cSteve Naroff                    CRegister crd,
1555df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner                    const MemOperand& dst,
1556397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian                    LFlag l,
1557397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian                    Condition cond) {
155843bc2a0973ffe404fabba6f8280cd6bad2c69fcbSebastian Redl  addrmod5(cond | B27 | B26 | l | coproc*B8, crd, dst);
15591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}
15607ba138abd329e591a8f6d5001f60dd7082f71b3bSteve Naroff
15617ba138abd329e591a8f6d5001f60dd7082f71b3bSteve Naroff
15627ba138abd329e591a8f6d5001f60dd7082f71b3bSteve Naroffvoid Assembler::stc(Coprocessor coproc,
15637ba138abd329e591a8f6d5001f60dd7082f71b3bSteve Naroff                    CRegister crd,
15644e6c0d19b7c072758922cf80525a81aeefc6e64bDouglas Gregor                    Register rn,
15657ba138abd329e591a8f6d5001f60dd7082f71b3bSteve Naroff                    int option,
156623c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor                    LFlag l,
156764515f31850024a263e8f55f81e9ea4b39925cfaSteve Naroff                    Condition cond) {
1568397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian  // Unindexed addressing.
15691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ASSERT(is_uint8(option));
157093a259500186fa7270f66cb460c5f5728e5680aeSteve Naroff  emit(cond | B27 | B26 | U | l | rn.code()*B16 | crd.code()*B12 |
15711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump       coproc*B8 | (option & 255));
157293a259500186fa7270f66cb460c5f5728e5680aeSteve Naroff}
157393a259500186fa7270f66cb460c5f5728e5680aeSteve Naroff
157493a259500186fa7270f66cb460c5f5728e5680aeSteve Naroff
157593a259500186fa7270f66cb460c5f5728e5680aeSteve Naroffvoid Assembler::stc2(Coprocessor
157693a259500186fa7270f66cb460c5f5728e5680aeSteve Naroff                     coproc, CRegister crd,
1577ca0408fb49c1370430672acf2d770b7151cf71deJohn McCall                     const MemOperand& dst,
1578c1b3ba5ae08316fe43e541c4fb02921fc3e80b21Chris Lattner                     LFlag l) {  // v5 and above
1579c1b3ba5ae08316fe43e541c4fb02921fc3e80b21Chris Lattner  stc(coproc, crd, dst, l, static_cast<Condition>(nv));
1580c1b3ba5ae08316fe43e541c4fb02921fc3e80b21Chris Lattner}
1581c1b3ba5ae08316fe43e541c4fb02921fc3e80b21Chris Lattner
15820e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
15833b1191d7eaf2f4984564e01ab84b6713a9d80e70Fariborz Jahanianvoid Assembler::stc2(Coprocessor coproc,
15848f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor                     CRegister crd,
15858f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor                     Register rn,
15868f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor                     int option,
15878f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor                     LFlag l) {  // v5 and above
15888f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor  stc(coproc, crd, rn, option, l, static_cast<Condition>(nv));
15898f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor}
15908f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor
15918f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor
159264515f31850024a263e8f55f81e9ea4b39925cfaSteve Naroff// Support for VFP.
15931ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattnervoid Assembler::vldr(const DwVfpRegister dst,
15941ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner                     const Register base,
159543bc2a0973ffe404fabba6f8280cd6bad2c69fcbSebastian Redl                     int offset,
1596397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian                     const Condition cond) {
1597397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian  // Ddst = MEM(Rbase + offset).
15986b884508c3bc97cc9df9516adb92fbf88dd0a2e4Chris Lattner  // Instruction details available in ARM DDI 0406A, A8-628.
15996b884508c3bc97cc9df9516adb92fbf88dd0a2e4Chris Lattner  // cond(31-28) | 1101(27-24)| 1001(23-20) | Rbase(19-16) |
160064515f31850024a263e8f55f81e9ea4b39925cfaSteve Naroff  // Vdst(15-12) | 1011(11-8) | offset
16018935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  ASSERT(CpuFeatures::IsEnabled(VFP3));
16020e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  ASSERT(offset % 4 == 0);
1603ca0408fb49c1370430672acf2d770b7151cf71deJohn McCall  ASSERT((offset / 4) < 256);
1604c1b3ba5ae08316fe43e541c4fb02921fc3e80b21Chris Lattner  emit(cond | 0xD9*B20 | base.code()*B16 | dst.code()*B12 |
1605c1b3ba5ae08316fe43e541c4fb02921fc3e80b21Chris Lattner       0xB*B8 | ((offset / 4) & 255));
1606c1b3ba5ae08316fe43e541c4fb02921fc3e80b21Chris Lattner}
1607c1b3ba5ae08316fe43e541c4fb02921fc3e80b21Chris Lattner
16080e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
1609161a9c5afaafb4d527b7efba9675a8b2cbbe32e0Fariborz Jahanianvoid Assembler::vldr(const SwVfpRegister dst,
16100e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl                     const Register base,
161176ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl                     int offset,
1612397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian                     const Condition cond) {
1613397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian  // Sdst = MEM(Rbase + offset).
1614397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian  // Instruction details available in ARM DDI 0406A, A8-628.
1615397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian  // cond(31-28) | 1101(27-24)| 1001(23-20) | Rbase(19-16) |
1616bd49a647afd9cc534fef13cadf652d4e9c396e2bFariborz Jahanian  // Vdst(15-12) | 1010(11-8) | offset
1617397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian  ASSERT(CpuFeatures::IsEnabled(VFP3));
161843bc2a0973ffe404fabba6f8280cd6bad2c69fcbSebastian Redl  ASSERT(offset % 4 == 0);
1619bd49a647afd9cc534fef13cadf652d4e9c396e2bFariborz Jahanian  ASSERT((offset / 4) < 256);
16208f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor  emit(cond | 0xD9*B20 | base.code()*B16 | dst.code()*B12 |
16218f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor       0xA*B8 | ((offset / 4) & 255));
16228f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor}
162376ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl
1624397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian
1625ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanianvoid Assembler::vstr(const DwVfpRegister src,
16263536b443bc50d58a79f14fca9b6842541a434854Steve Naroff                     const Register base,
1627ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian                     int offset,
1628d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall                     const Condition cond) {
1629d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall  // MEM(Rbase + offset) = Dsrc.
16301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Instruction details available in ARM DDI 0406A, A8-786.
163149f28ca787d8db7cac3c8898334f70ea55374c98Chris Lattner  // cond(31-28) | 1101(27-24)| 1000(23-20) | | Rbase(19-16) |
163249f28ca787d8db7cac3c8898334f70ea55374c98Chris Lattner  // Vsrc(15-12) | 1011(11-8) | (offset/4)
163349f28ca787d8db7cac3c8898334f70ea55374c98Chris Lattner  ASSERT(CpuFeatures::IsEnabled(VFP3));
16341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ASSERT(offset % 4 == 0);
1635ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian  ASSERT((offset / 4) < 256);
1636209a8c2fa23636f6d065d618e7078e164903f5cdFariborz Jahanian  emit(cond | 0xD8*B20 | base.code()*B16 | src.code()*B12 |
1637496e45ef3350fabc312c5a807d308c65c50af4dbTed Kremenek       0xB*B8 | ((offset / 4) & 255));
1638496e45ef3350fabc312c5a807d308c65c50af4dbTed Kremenek}
1639849b243d4065f56742a4677d6dc8277609a151f8Douglas Gregor
1640496e45ef3350fabc312c5a807d308c65c50af4dbTed Kremenek
1641ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanianvoid Assembler::vmov(const DwVfpRegister dst,
1642209a8c2fa23636f6d065d618e7078e164903f5cdFariborz Jahanian                     const Register src1,
1643ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian                     const Register src2,
1644409be835b68344e0de56f99ef9a1e12760bc69eeSteve Naroff                     const Condition cond) {
1645df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  // Dm = <Rt,Rt2>.
1646da323adbb99cee19a203ead852d5d9bfebb23fb7Steve Naroff  // Instruction details available in ARM DDI 0406A, A8-646.
16471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) |
1648409be835b68344e0de56f99ef9a1e12760bc69eeSteve Naroff  // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
1649409be835b68344e0de56f99ef9a1e12760bc69eeSteve Naroff  ASSERT(CpuFeatures::IsEnabled(VFP3));
16501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ASSERT(!src1.is(pc) && !src2.is(pc));
1651409be835b68344e0de56f99ef9a1e12760bc69eeSteve Naroff  emit(cond | 0xC*B24 | B22 | src2.code()*B16 |
1652409be835b68344e0de56f99ef9a1e12760bc69eeSteve Naroff       src1.code()*B12 | 0xB*B8 | B4 | dst.code());
1653d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall}
1654ac00b7f4a933e60e2f0afd83092339160adc140cFariborz Jahanian
1655409be835b68344e0de56f99ef9a1e12760bc69eeSteve Naroff
16561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid Assembler::vmov(const Register dst1,
1657409be835b68344e0de56f99ef9a1e12760bc69eeSteve Naroff                     const Register dst2,
165815faee19fdb9017dd6d08a690427b18c3b062c2dChris Lattner                     const DwVfpRegister src,
165915faee19fdb9017dd6d08a690427b18c3b062c2dChris Lattner                     const Condition cond) {
16601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // <Rt,Rt2> = Dm.
1661409be835b68344e0de56f99ef9a1e12760bc69eeSteve Naroff  // Instruction details available in ARM DDI 0406A, A8-646.
1662394f3f483fa4e7b472630cfcd03f7840520958c5Steve Naroff  // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) |
166323c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor  // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
166461364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  ASSERT(CpuFeatures::IsEnabled(VFP3));
166561364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  ASSERT(!dst1.is(pc) && !dst2.is(pc));
166661364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 |
1667409be835b68344e0de56f99ef9a1e12760bc69eeSteve Naroff       dst1.code()*B12 | 0xB*B8 | B4 | src.code());
16680e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl}
1669a60528cdac7deee3991c2b48af4df4f315e49e9dSebastian Redl
1670a60528cdac7deee3991c2b48af4df4f315e49e9dSebastian Redl
1671798d119415323ebcd029ffe1e0fb442a4ca8adbbSebastian Redlvoid Assembler::vmov(const SwVfpRegister dst,
167232ce8376efb7e0d70e5f7e8fcf685130293f412bSteve Naroff                     const Register src,
167332ce8376efb7e0d70e5f7e8fcf685130293f412bSteve Naroff                     const Condition cond) {
16741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Sn = Rt.
1675409be835b68344e0de56f99ef9a1e12760bc69eeSteve Naroff  // Instruction details available in ARM DDI 0406A, A8-642.
16768935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) |
1677798d119415323ebcd029ffe1e0fb442a4ca8adbbSebastian Redl  // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
167871c0a951d08dc7a2a057df8c15f22b36f6aa47c7Steve Naroff  ASSERT(CpuFeatures::IsEnabled(VFP3));
16795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ASSERT(!src.is(pc));
16805508518a2702b00be3b15a26d772bde968972f54Anders Carlsson  emit(cond | 0xE*B24 | (dst.code() >> 1)*B16 |
168143bc2a0973ffe404fabba6f8280cd6bad2c69fcbSebastian Redl       src.code()*B12 | 0xA*B8 | (0x1 & dst.code())*B7 | B4);
16829a0c85e640a08174569a303db22981612f05d385Douglas Gregor}
168323c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor
1684dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor
16859a0c85e640a08174569a303db22981612f05d385Douglas Gregorvoid Assembler::vmov(const Register dst,
16865d8031687d086701b4dadaab3e0de1def448da9dChris Lattner                     const SwVfpRegister src,
16875d8031687d086701b4dadaab3e0de1def448da9dChris Lattner                     const Condition cond) {
16885d8031687d086701b4dadaab3e0de1def448da9dChris Lattner  // Rt = Sn.
16896b884508c3bc97cc9df9516adb92fbf88dd0a2e4Chris Lattner  // Instruction details available in ARM DDI 0406A, A8-642.
16905d8031687d086701b4dadaab3e0de1def448da9dChris Lattner  // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) |
16915d8031687d086701b4dadaab3e0de1def448da9dChris Lattner  // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
169264515f31850024a263e8f55f81e9ea4b39925cfaSteve Naroff  ASSERT(CpuFeatures::IsEnabled(VFP3));
16935d8031687d086701b4dadaab3e0de1def448da9dChris Lattner  ASSERT(!dst.is(pc));
16945d8031687d086701b4dadaab3e0de1def448da9dChris Lattner  emit(cond | 0xE*B24 | B20 | (src.code() >> 1)*B16 |
169564515f31850024a263e8f55f81e9ea4b39925cfaSteve Naroff       dst.code()*B12 | 0xA*B8 | (0x1 & src.code())*B7 | B4);
16965d8031687d086701b4dadaab3e0de1def448da9dChris Lattner}
1697d8c4e15138e69a51754cc259c8a592cc47950c8eSebastian Redl
16980e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
169964515f31850024a263e8f55f81e9ea4b39925cfaSteve Naroff// Type of data to read from or write to VFP register.
170064515f31850024a263e8f55f81e9ea4b39925cfaSteve Naroff// Used as specifier in generic vcvt instruction.
170164515f31850024a263e8f55f81e9ea4b39925cfaSteve Naroffenum VFPType { S32, U32, F32, F64 };
170264515f31850024a263e8f55f81e9ea4b39925cfaSteve Naroff
170343bc2a0973ffe404fabba6f8280cd6bad2c69fcbSebastian Redl
170464515f31850024a263e8f55f81e9ea4b39925cfaSteve Naroffstatic bool IsSignedVFPType(VFPType type) {
17055d8031687d086701b4dadaab3e0de1def448da9dChris Lattner  switch (type) {
170664515f31850024a263e8f55f81e9ea4b39925cfaSteve Naroff    case S32:
170764515f31850024a263e8f55f81e9ea4b39925cfaSteve Naroff      return true;
17085ee56e95c3905d2e7bc403631b03865cdbdd8a42Anders Carlsson    case U32:
170964515f31850024a263e8f55f81e9ea4b39925cfaSteve Naroff      return false;
171064515f31850024a263e8f55f81e9ea4b39925cfaSteve Naroff    default:
17111d922960e083906a586609ac6978678147250177Sebastian Redl      UNREACHABLE();
17125508518a2702b00be3b15a26d772bde968972f54Anders Carlsson      return false;
17139a0c85e640a08174569a303db22981612f05d385Douglas Gregor  }
171423c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor}
1715dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor
17169a0c85e640a08174569a303db22981612f05d385Douglas Gregor
17179a0c85e640a08174569a303db22981612f05d385Douglas Gregorstatic bool IsIntegerVFPType(VFPType type) {
1718b3a99cd5bcaeff0c5ff6a60788b5eb68e52a3953Chris Lattner  switch (type) {
1719b3a99cd5bcaeff0c5ff6a60788b5eb68e52a3953Chris Lattner    case S32:
17201d922960e083906a586609ac6978678147250177Sebastian Redl    case U32:
1721b3a99cd5bcaeff0c5ff6a60788b5eb68e52a3953Chris Lattner      return true;
17224fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner    case F32:
17231d922960e083906a586609ac6978678147250177Sebastian Redl    case F64:
17242f7ece7c77eb17e24e8f0f4e1b7fb01aa5111f96Sebastian Redl      return false;
17254fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner    default:
17264fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner      UNREACHABLE();
17271d922960e083906a586609ac6978678147250177Sebastian Redl      return false;
17284fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner  }
17291d922960e083906a586609ac6978678147250177Sebastian Redl}
17304fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner
17311d922960e083906a586609ac6978678147250177Sebastian Redl
17324fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattnerstatic bool IsDoubleVFPType(VFPType type) {
17331d922960e083906a586609ac6978678147250177Sebastian Redl  switch (type) {
17344fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner    case F32:
17355508518a2702b00be3b15a26d772bde968972f54Anders Carlsson      return false;
17365508518a2702b00be3b15a26d772bde968972f54Anders Carlsson    case F64:
17375508518a2702b00be3b15a26d772bde968972f54Anders Carlsson      return true;
17386aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    default:
17396aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor      UNREACHABLE();
17406aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor      return false;
17416aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor  }
17426aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor}
17436aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor
17446aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor
17456aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor// Depending on split_last_bit split binary representation of reg_code into Vm:M
17466aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor// or M:Vm form (where M is single bit).
17476aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregorstatic void SplitRegCode(bool split_last_bit,
17486aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor                         int reg_code,
17496aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor                         int* vm,
17506aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor                         int* m) {
17516aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor  if (split_last_bit) {
17526aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    *m  = reg_code & 0x1;
17536aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    *vm = reg_code >> 1;
17546aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor  } else {
17556aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    *m  = (reg_code & 0x10) >> 4;
17566aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    *vm = reg_code & 0x0F;
17576aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor  }
17586aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor}
17596aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor
17606aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor
17616aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor// Encode vcvt.src_type.dst_type instruction.
17626aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregorstatic Instr EncodeVCVT(const VFPType dst_type,
17636aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor                        const int dst_code,
17646aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor                        const VFPType src_type,
17656aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor                        const int src_code,
17666aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor                        const Condition cond) {
17676aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor  if (IsIntegerVFPType(dst_type) || IsIntegerVFPType(src_type)) {
17686aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    // Conversion between IEEE floating point and 32-bit integer.
17696aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    // Instruction details available in ARM DDI 0406B, A8.6.295.
17706aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 1(19) | opc2(18-16) |
17716aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    // Vd(15-12) | 101(11-9) | sz(8) | op(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
17726aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    ASSERT(!IsIntegerVFPType(dst_type) || !IsIntegerVFPType(src_type));
17736aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor
17746aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    int sz, opc2, D, Vd, M, Vm, op;
17756aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor
17766aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    if (IsIntegerVFPType(dst_type)) {
17776aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor      opc2 = IsSignedVFPType(dst_type) ? 0x5 : 0x4;
17786aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor      sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
17796aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor      op = 1;  // round towards zero
17806aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor      SplitRegCode(!IsDoubleVFPType(src_type), src_code, &Vm, &M);
17816aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor      SplitRegCode(true, dst_code, &Vd, &D);
17826aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    } else {
17836aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor      ASSERT(IsIntegerVFPType(src_type));
17846aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor
17856aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor      opc2 = 0x0;
17866aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor      sz = IsDoubleVFPType(dst_type) ? 0x1 : 0x0;
17876aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor      op = IsSignedVFPType(src_type) ? 0x1 : 0x0;
17886aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor      SplitRegCode(true, src_code, &Vm, &M);
17896aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor      SplitRegCode(!IsDoubleVFPType(dst_type), dst_code, &Vd, &D);
17906aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    }
17916aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor
17926aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | B19 | opc2*B16 |
17936aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor            Vd*B12 | 0x5*B9 | sz*B8 | op*B7 | B6 | M*B5 | Vm);
17946aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor  } else {
17956aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    // Conversion between IEEE double and single precision.
17966aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    // Instruction details available in ARM DDI 0406B, A8.6.298.
17976aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0111(19-16) |
17986aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    // Vd(15-12) | 101(11-9) | sz(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
17996aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    int sz, D, Vd, M, Vm;
18006aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor
18016aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    ASSERT(IsDoubleVFPType(dst_type) != IsDoubleVFPType(src_type));
18026aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
18036aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    SplitRegCode(IsDoubleVFPType(src_type), dst_code, &Vd, &D);
18046aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    SplitRegCode(!IsDoubleVFPType(src_type), src_code, &Vm, &M);
18056aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor
18066aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor    return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | 0x7*B16 |
18076aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor            Vd*B12 | 0x5*B9 | sz*B8 | B7 | B6 | M*B5 | Vm);
18086aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor  }
18096aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor}
18106aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor
18116aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor
18126aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregorvoid Assembler::vcvt_f64_s32(const DwVfpRegister dst,
18136aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor                             const SwVfpRegister src,
181423c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor                             const Condition cond) {
18156aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor  ASSERT(CpuFeatures::IsEnabled(VFP3));
18166aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor  emit(EncodeVCVT(F64, dst.code(), S32, src.code(), cond));
18176aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor}
18186aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor
18196aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor
18206aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregorvoid Assembler::vcvt_f32_s32(const SwVfpRegister dst,
18216aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor                             const SwVfpRegister src,
18226aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor                             const Condition cond) {
18231b730e847ded503f2e615154035c083c4f94a067Douglas Gregor  ASSERT(CpuFeatures::IsEnabled(VFP3));
18241b730e847ded503f2e615154035c083c4f94a067Douglas Gregor  emit(EncodeVCVT(F32, dst.code(), S32, src.code(), cond));
18251b730e847ded503f2e615154035c083c4f94a067Douglas Gregor}
18261b730e847ded503f2e615154035c083c4f94a067Douglas Gregor
18271b730e847ded503f2e615154035c083c4f94a067Douglas Gregor
18281b730e847ded503f2e615154035c083c4f94a067Douglas Gregorvoid Assembler::vcvt_f64_u32(const DwVfpRegister dst,
1829c59cb38810c63a806270385f79ea84e0203754eaChris Lattner                             const SwVfpRegister src,
18301b730e847ded503f2e615154035c083c4f94a067Douglas Gregor                             const Condition cond) {
18311b730e847ded503f2e615154035c083c4f94a067Douglas Gregor  ASSERT(CpuFeatures::IsEnabled(VFP3));
18321b730e847ded503f2e615154035c083c4f94a067Douglas Gregor  emit(EncodeVCVT(F64, dst.code(), U32, src.code(), cond));
18331b730e847ded503f2e615154035c083c4f94a067Douglas Gregor}
18341b730e847ded503f2e615154035c083c4f94a067Douglas Gregor
18351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
18360ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanianvoid Assembler::vcvt_s32_f64(const SwVfpRegister dst,
18370ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanian                             const DwVfpRegister src,
18382725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor                             const Condition cond) {
1839eb483eb3ee80300f15d6d13573d82493c2194461Chris Lattner  ASSERT(CpuFeatures::IsEnabled(VFP3));
18400ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanian  emit(EncodeVCVT(S32, dst.code(), F64, src.code(), cond));
18410ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanian}
18420ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanian
18436aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor
18441d922960e083906a586609ac6978678147250177Sebastian Redlvoid Assembler::vcvt_u32_f64(const SwVfpRegister dst,
1845699b66138ac307a32e238463e0eff513ff17d337Chris Lattner                             const DwVfpRegister src,
1846699b66138ac307a32e238463e0eff513ff17d337Chris Lattner                             const Condition cond) {
1847699b66138ac307a32e238463e0eff513ff17d337Chris Lattner  ASSERT(CpuFeatures::IsEnabled(VFP3));
18488e254cfe5a6ab4202c7fcc4b64bdd1ca0fe071acDouglas Gregor  emit(EncodeVCVT(U32, dst.code(), F64, src.code(), cond));
184923c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor}
18508e254cfe5a6ab4202c7fcc4b64bdd1ca0fe071acDouglas Gregor
18518e254cfe5a6ab4202c7fcc4b64bdd1ca0fe071acDouglas Gregor
18528e254cfe5a6ab4202c7fcc4b64bdd1ca0fe071acDouglas Gregorvoid Assembler::vcvt_f64_f32(const DwVfpRegister dst,
18538e254cfe5a6ab4202c7fcc4b64bdd1ca0fe071acDouglas Gregor                             const SwVfpRegister src,
18548e254cfe5a6ab4202c7fcc4b64bdd1ca0fe071acDouglas Gregor                             const Condition cond) {
18556aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor  ASSERT(CpuFeatures::IsEnabled(VFP3));
18566aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor  emit(EncodeVCVT(F64, dst.code(), F32, src.code(), cond));
18576aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor}
18586aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor
18596aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor
18606aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregorvoid Assembler::vcvt_f32_f64(const SwVfpRegister dst,
18616aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor                             const DwVfpRegister src,
18626aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor                             const Condition cond) {
186323c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor  ASSERT(CpuFeatures::IsEnabled(VFP3));
18646aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor  emit(EncodeVCVT(F32, dst.code(), F64, src.code(), cond));
18656aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor}
18666aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor
18676aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor
18686aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregorvoid Assembler::vadd(const DwVfpRegister dst,
18696aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor                     const DwVfpRegister src1,
18706aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor                     const DwVfpRegister src2,
18716aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor                     const Condition cond) {
18726aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor  // Dd = vadd(Dn, Dm) double precision floating point addition.
18736aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
18746aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor  // Instruction details available in ARM DDI 0406A, A8-536.
18756aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor  // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) |
18766aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor  // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0)
1877ca0408fb49c1370430672acf2d770b7151cf71deJohn McCall  ASSERT(CpuFeatures::IsEnabled(VFP3));
18786aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor  emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 |
18796aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor       dst.code()*B12 | 0x5*B9 | B8 | src2.code());
18806aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor}
1881c59cb38810c63a806270385f79ea84e0203754eaChris Lattner
1882c59cb38810c63a806270385f79ea84e0203754eaChris Lattner
1883c59cb38810c63a806270385f79ea84e0203754eaChris Lattnervoid Assembler::vsub(const DwVfpRegister dst,
18841dbca6ea983231b4cab1a8f1edda8f6e13c21f12Douglas Gregor                     const DwVfpRegister src1,
18851dbca6ea983231b4cab1a8f1edda8f6e13c21f12Douglas Gregor                     const DwVfpRegister src2,
18861569f95831a8c99e9f664137bf8f40e47ee3d90fDouglas Gregor                     const Condition cond) {
188723c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor  // Dd = vsub(Dn, Dm) double precision floating point subtraction.
18881dbca6ea983231b4cab1a8f1edda8f6e13c21f12Douglas Gregor  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
18891569f95831a8c99e9f664137bf8f40e47ee3d90fDouglas Gregor  // Instruction details available in ARM DDI 0406A, A8-784.
18901569f95831a8c99e9f664137bf8f40e47ee3d90fDouglas Gregor  // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) |
18911dbca6ea983231b4cab1a8f1edda8f6e13c21f12Douglas Gregor  // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 1(6) | M=?(5) | 0(4) | Vm(3-0)
18922725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor  ASSERT(CpuFeatures::IsEnabled(VFP3));
1893d2869925b5f10e00b13fbf3f41bbb17e4c9adbe0Fariborz Jahanian  emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 |
18942725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor       dst.code()*B12 | 0x5*B9 | B8 | B6 | src2.code());
18951569f95831a8c99e9f664137bf8f40e47ee3d90fDouglas Gregor}
18961569f95831a8c99e9f664137bf8f40e47ee3d90fDouglas Gregor
18972725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor
18982725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregorvoid Assembler::vmul(const DwVfpRegister dst,
18992725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor                     const DwVfpRegister src1,
19002725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor                     const DwVfpRegister src2,
19011569f95831a8c99e9f664137bf8f40e47ee3d90fDouglas Gregor                     const Condition cond) {
19021569f95831a8c99e9f664137bf8f40e47ee3d90fDouglas Gregor  // Dd = vmul(Dn, Dm) double precision floating point multiplication.
19031569f95831a8c99e9f664137bf8f40e47ee3d90fDouglas Gregor  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
19041569f95831a8c99e9f664137bf8f40e47ee3d90fDouglas Gregor  // Instruction details available in ARM DDI 0406A, A8-784.
19052725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor  // cond(31-28) | 11100(27-23)| D=?(22) | 10(21-20) | Vn(19-16) |
19061dbca6ea983231b4cab1a8f1edda8f6e13c21f12Douglas Gregor  // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0)
19071dbca6ea983231b4cab1a8f1edda8f6e13c21f12Douglas Gregor  ASSERT(CpuFeatures::IsEnabled(VFP3));
19082725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor  emit(cond | 0xE*B24 | 0x2*B20 | src1.code()*B16 |
19091dbca6ea983231b4cab1a8f1edda8f6e13c21f12Douglas Gregor       dst.code()*B12 | 0x5*B9 | B8 | src2.code());
1910d2869925b5f10e00b13fbf3f41bbb17e4c9adbe0Fariborz Jahanian}
1911699b66138ac307a32e238463e0eff513ff17d337Chris Lattner
1912eb483eb3ee80300f15d6d13573d82493c2194461Chris Lattner
1913eb483eb3ee80300f15d6d13573d82493c2194461Chris Lattnervoid Assembler::vdiv(const DwVfpRegister dst,
19142f7ece7c77eb17e24e8f0f4e1b7fb01aa5111f96Sebastian Redl                     const DwVfpRegister src1,
19150e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl                     const DwVfpRegister src2,
19165c749428a9938d5e2e9564b1c9b7a9252c30ee27Chris Lattner                     const Condition cond) {
19171d922960e083906a586609ac6978678147250177Sebastian Redl  // Dd = vdiv(Dn, Dm) double precision floating point division.
1918699b66138ac307a32e238463e0eff513ff17d337Chris Lattner  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
19191d922960e083906a586609ac6978678147250177Sebastian Redl  // Instruction details available in ARM DDI 0406A, A8-584.
19202725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor  // cond(31-28) | 11101(27-23)| D=?(22) | 00(21-20) | Vn(19-16) |
19212725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor  // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=? | 0(6) | M=?(5) | 0(4) | Vm(3-0)
1922699b66138ac307a32e238463e0eff513ff17d337Chris Lattner  ASSERT(CpuFeatures::IsEnabled(VFP3));
19231d922960e083906a586609ac6978678147250177Sebastian Redl  emit(cond | 0xE*B24 | B23 | src1.code()*B16 |
19242725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor       dst.code()*B12 | 0x5*B9 | B8 | src2.code());
19252725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor}
19262725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor
19272725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor
19282725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregorvoid Assembler::vcmp(const DwVfpRegister src1,
19292725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor                     const DwVfpRegister src2,
19302725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor                     const SBit s,
19312725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor                     const Condition cond) {
19322725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor  // vcmp(Dd, Dm) double precision floating point comparison.
19332725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor  // Instruction details available in ARM DDI 0406A, A8-570.
19342725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor  // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0100 (19-16) |
19352725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor  // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=? | 1(6) | M(5)=? | 0(4) | Vm(3-0)
19362725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor  ASSERT(CpuFeatures::IsEnabled(VFP3));
19372725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor  emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 |
19382725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor       src1.code()*B12 | 0x5*B9 | B8 | B6 | src2.code());
19392725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor}
19402725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor
19412725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor
19422725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregorvoid Assembler::vmrs(Register dst, Condition cond) {
19431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Instruction details available in ARM DDI 0406A, A8-652.
19440ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanian  // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) |
19450ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanian  // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
19460ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanian  ASSERT(CpuFeatures::IsEnabled(VFP3));
19470ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanian  emit(cond | 0xE*B24 | 0xF*B20 |  B16 |
19480ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanian       dst.code()*B12 | 0xA*B8 | B4);
19490ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanian}
19500ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanian
19510ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanian
19521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// Pseudo instructions.
19530ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanianvoid Assembler::nop(int type) {
19540ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanian  // This is mov rx, rx.
19550ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanian  ASSERT(0 <= type && type <= 14);  // mov pc, pc is not a nop.
19560ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanian  emit(al | 13*B21 | type*B12 | type);
19570ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanian}
19580ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanian
19590ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanian
19600ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanianbool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) {
19611d922960e083906a586609ac6978678147250177Sebastian Redl  uint32_t dummy1;
19621d922960e083906a586609ac6978678147250177Sebastian Redl  uint32_t dummy2;
1963699b66138ac307a32e238463e0eff513ff17d337Chris Lattner  return fits_shifter(imm32, &dummy1, &dummy2, NULL);
19642725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor}
19652725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor
19661d922960e083906a586609ac6978678147250177Sebastian Redl
1967c4df6d2c05c647a6a5770ba0c749782b6c023a3aSteve Naroffvoid Assembler::BlockConstPoolFor(int instructions) {
19682725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor  BlockConstPoolBefore(pc_offset() + instructions * kInstrSize);
196923c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor}
19702725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor
197123c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor
1972c4df6d2c05c647a6a5770ba0c749782b6c023a3aSteve Naroff// Debugging.
197323c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregorvoid Assembler::RecordJSReturn() {
1974d3c6854153fd6bc6a412a29e4491dbd0a47bdb14Douglas Gregor  WriteRecordedPositions();
1975dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor  CheckBuffer();
1976c4df6d2c05c647a6a5770ba0c749782b6c023a3aSteve Naroff  RecordRelocInfo(RelocInfo::JS_RETURN);
1977d3c6854153fd6bc6a412a29e4491dbd0a47bdb14Douglas Gregor}
1978a65ff6c81f5b278000839988bb532114fd8c6797Fariborz Jahanian
19794b6c9051c6522894978c9ba6a819a659d102db36Fariborz Jahanian
19802fc5c2428ecb450a3256c8316b93b8655cb76a0fChris Lattnervoid Assembler::RecordComment(const char* msg) {
198168d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroff  if (FLAG_debug_code) {
1982ff975cfab9ada27df86038286d1678084aeb3428Anders Carlsson    CheckBuffer();
19831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
198468d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroff  }
1985a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl}
198668d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroff
1987df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner
1988a65ff6c81f5b278000839988bb532114fd8c6797Fariborz Jahanianvoid Assembler::RecordPosition(int pos) {
1989a65ff6c81f5b278000839988bb532114fd8c6797Fariborz Jahanian  if (pos == RelocInfo::kNoPosition) return;
199068d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroff  ASSERT(pos >= 0);
199137387c932855c6d58d70bdd705cd3a9fdcd2a931Steve Naroff  current_position_ = pos;
1992df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner}
1993a65ff6c81f5b278000839988bb532114fd8c6797Fariborz Jahanian
19944fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner
19954fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattnervoid Assembler::RecordStatementPosition(int pos) {
19964fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner  if (pos == RelocInfo::kNoPosition) return;
19974fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner  ASSERT(pos >= 0);
19981d922960e083906a586609ac6978678147250177Sebastian Redl  current_statement_position_ = pos;
1999a65ff6c81f5b278000839988bb532114fd8c6797Fariborz Jahanian}
20001d922960e083906a586609ac6978678147250177Sebastian Redl
200168d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroff
20021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid Assembler::WriteRecordedPositions() {
20032f7ece7c77eb17e24e8f0f4e1b7fb01aa5111f96Sebastian Redl  // Write the statement position if it is different from what was written last
20040e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  // time.
20054fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner  if (current_statement_position_ != written_statement_position_) {
20064fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner    CheckBuffer();
20074fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner    RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_);
20084fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner    written_statement_position_ = current_statement_position_;
20091d922960e083906a586609ac6978678147250177Sebastian Redl  }
201037387c932855c6d58d70bdd705cd3a9fdcd2a931Steve Naroff
20111d922960e083906a586609ac6978678147250177Sebastian Redl  // Write the position if it is different from what was written last time and
201237387c932855c6d58d70bdd705cd3a9fdcd2a931Steve Naroff  // also different from the written statement position.
2013effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl  if (current_position_ != written_position_ &&
20141d922960e083906a586609ac6978678147250177Sebastian Redl      current_position_ != written_statement_position_) {
2015d3c6854153fd6bc6a412a29e4491dbd0a47bdb14Douglas Gregor    CheckBuffer();
2016d3c6854153fd6bc6a412a29e4491dbd0a47bdb14Douglas Gregor    RecordRelocInfo(RelocInfo::POSITION, current_position_);
20172725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor    written_position_ = current_position_;
201823c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor  }
20192725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor}
20202725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor
20212725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor
202223c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregorvoid Assembler::GrowBuffer() {
2023d3c6854153fd6bc6a412a29e4491dbd0a47bdb14Douglas Gregor  if (!own_buffer_) FATAL("external code buffer is too small");
2024d3c6854153fd6bc6a412a29e4491dbd0a47bdb14Douglas Gregor
2025d3c6854153fd6bc6a412a29e4491dbd0a47bdb14Douglas Gregor  // Compute new buffer size.
202623c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor  CodeDesc desc;  // the new buffer
2027d3c6854153fd6bc6a412a29e4491dbd0a47bdb14Douglas Gregor  if (buffer_size_ < 4*KB) {
2028d3c6854153fd6bc6a412a29e4491dbd0a47bdb14Douglas Gregor    desc.buffer_size = 4*KB;
2029dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor  } else if (buffer_size_ < 1*MB) {
2030d3c6854153fd6bc6a412a29e4491dbd0a47bdb14Douglas Gregor    desc.buffer_size = 2*buffer_size_;
2031d3c6854153fd6bc6a412a29e4491dbd0a47bdb14Douglas Gregor  } else {
203237387c932855c6d58d70bdd705cd3a9fdcd2a931Steve Naroff    desc.buffer_size = buffer_size_ + 1*MB;
20332fc5c2428ecb450a3256c8316b93b8655cb76a0fChris Lattner  }
2034df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  CHECK_GT(desc.buffer_size, 0);  // no overflow
2035a65ff6c81f5b278000839988bb532114fd8c6797Fariborz Jahanian
2036a65ff6c81f5b278000839988bb532114fd8c6797Fariborz Jahanian  // Setup new buffer.
2037a65ff6c81f5b278000839988bb532114fd8c6797Fariborz Jahanian  desc.buffer = NewArray<byte>(desc.buffer_size);
2038a65ff6c81f5b278000839988bb532114fd8c6797Fariborz Jahanian
2039df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner  desc.instr_size = pc_offset();
204049f109c786f99eb7468dac3976db083a65493444Steve Naroff  desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
20411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
20422f7ece7c77eb17e24e8f0f4e1b7fb01aa5111f96Sebastian Redl  // Copy the data.
20430e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  int pc_delta = desc.buffer - buffer_;
20444fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner  int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
20454fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner  memmove(desc.buffer, buffer_, desc.instr_size);
20464fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner  memmove(reloc_info_writer.pos() + rc_delta,
20474fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner          reloc_info_writer.pos(), desc.reloc_size);
20481d922960e083906a586609ac6978678147250177Sebastian Redl
204949f109c786f99eb7468dac3976db083a65493444Steve Naroff  // Switch buffers.
20500e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  DeleteArray(buffer_);
205149f109c786f99eb7468dac3976db083a65493444Steve Naroff  buffer_ = desc.buffer;
2052effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl  buffer_size_ = desc.buffer_size;
2053a65ff6c81f5b278000839988bb532114fd8c6797Fariborz Jahanian  pc_ += pc_delta;
2054a65ff6c81f5b278000839988bb532114fd8c6797Fariborz Jahanian  reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2055a65ff6c81f5b278000839988bb532114fd8c6797Fariborz Jahanian                               reloc_info_writer.last_pc() + pc_delta);
20561d922960e083906a586609ac6978678147250177Sebastian Redl
20574fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner  // None of our relocation types are pc relative pointing outside the code
20584fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner  // buffer nor pc absolute pointing inside the code buffer, so there is no need
20594fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner  // to relocate any emitted relocation entries.
20604fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner
20611d922960e083906a586609ac6978678147250177Sebastian Redl  // Relocate pending relocation entries.
2062a65ff6c81f5b278000839988bb532114fd8c6797Fariborz Jahanian  for (int i = 0; i < num_prinfo_; i++) {
2063809872eca7f6c024e2ab41ddffbbeeae807bf5dcFariborz Jahanian    RelocInfo& rinfo = prinfo_[i];
2064df19526177bc6d0a3ea4d1ae97497869f60563dbChris Lattner    ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
2065809872eca7f6c024e2ab41ddffbbeeae807bf5dcFariborz Jahanian           rinfo.rmode() != RelocInfo::POSITION);
2066809872eca7f6c024e2ab41ddffbbeeae807bf5dcFariborz Jahanian    if (rinfo.rmode() != RelocInfo::JS_RETURN) {
2067809872eca7f6c024e2ab41ddffbbeeae807bf5dcFariborz Jahanian      rinfo.set_pc(rinfo.pc() + pc_delta);
2068809872eca7f6c024e2ab41ddffbbeeae807bf5dcFariborz Jahanian    }
20694fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner  }
20704fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner}
20714fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner
20724fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner
20731d922960e083906a586609ac6978678147250177Sebastian Redlvoid Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2074a65ff6c81f5b278000839988bb532114fd8c6797Fariborz Jahanian  RelocInfo rinfo(pc_, rmode, data);  // we do not try to reuse pool constants
20751d922960e083906a586609ac6978678147250177Sebastian Redl  if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::STATEMENT_POSITION) {
2076699b66138ac307a32e238463e0eff513ff17d337Chris Lattner    // Adjust code for new modes.
20771d922960e083906a586609ac6978678147250177Sebastian Redl    ASSERT(RelocInfo::IsJSReturn(rmode)
207829238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff           || RelocInfo::IsComment(rmode)
2079ff38491c18b060526d754765b952f4a497a89416Chris Lattner           || RelocInfo::IsPosition(rmode));
2080ff38491c18b060526d754765b952f4a497a89416Chris Lattner    // These modes do not need an entry in the constant pool.
2081ff38491c18b060526d754765b952f4a497a89416Chris Lattner  } else {
20821d922960e083906a586609ac6978678147250177Sebastian Redl    ASSERT(num_prinfo_ < kMaxNumPRInfo);
20832725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor    prinfo_[num_prinfo_++] = rinfo;
208423c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor    // Make sure the constant pool is not emitted in place of the next
20852725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor    // instruction for which we just recorded relocation info.
20862725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor    BlockConstPoolBefore(pc_offset() + kInstrSize);
20872725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor  }
20882725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor  if (rinfo.rmode() != RelocInfo::NONE) {
20892725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor    // Don't record external references unless the heap will be serialized.
209023c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor    if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
20912725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor#ifdef DEBUG
20922725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor      if (!Serializer::enabled()) {
20932725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor        Serializer::TooLateToEnableNow();
20942725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor      }
209523c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor#endif
20962725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor      if (!Serializer::enabled() && !FLAG_debug_code) {
20972725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor        return;
20982725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor      }
20992725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor    }
21000ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanian    ASSERT(buffer_space() >= kMaxRelocSize);  // too late to grow buffer here
21010ccb27ded12fd03eb6818a880f50901bb70254feFariborz Jahanian    reloc_info_writer.Write(&rinfo);
21021d922960e083906a586609ac6978678147250177Sebastian Redl  }
210320df9b7ab9388b2a488c5b1293cd196b1e073b4eSebastian Redl}
21041d922960e083906a586609ac6978678147250177Sebastian Redl
21051d922960e083906a586609ac6978678147250177Sebastian Redl
2106b3a99cd5bcaeff0c5ff6a60788b5eb68e52a3953Chris Lattnervoid Assembler::CheckConstPool(bool force_emit, bool require_jump) {
2107b3a99cd5bcaeff0c5ff6a60788b5eb68e52a3953Chris Lattner  // Calculate the offset of the next check. It will be overwritten
2108b3a99cd5bcaeff0c5ff6a60788b5eb68e52a3953Chris Lattner  // when a const pool is generated or when const pools are being
2109b3a99cd5bcaeff0c5ff6a60788b5eb68e52a3953Chris Lattner  // blocked for a specific range.
2110a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl  next_buffer_check_ = pc_offset() + kCheckConstInterval;
2111b3a99cd5bcaeff0c5ff6a60788b5eb68e52a3953Chris Lattner
2112effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl  // There is nothing to do if there are no pending relocation info entries.
21130e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (num_prinfo_ == 0) return;
2114b3a99cd5bcaeff0c5ff6a60788b5eb68e52a3953Chris Lattner
2115b3a99cd5bcaeff0c5ff6a60788b5eb68e52a3953Chris Lattner  // We emit a constant pool at regular intervals of about kDistBetweenPools
2116b3a99cd5bcaeff0c5ff6a60788b5eb68e52a3953Chris Lattner  // or when requested by parameter force_emit (e.g. after each function).
211715faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  // We prefer not to emit a jump unless the max distance is reached or if we
211897cf6eb380016db868866faf27a086cd55a316d4Chris Lattner  // are running low on slots, which can happen if a lot of constants are being
211997cf6eb380016db868866faf27a086cd55a316d4Chris Lattner  // emitted (e.g. --debug-code and many static references).
2120b3a99cd5bcaeff0c5ff6a60788b5eb68e52a3953Chris Lattner  int dist = pc_offset() - last_const_pool_end_;
212197cf6eb380016db868866faf27a086cd55a316d4Chris Lattner  if (!force_emit && dist < kMaxDistBetweenPools &&
21220e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      (require_jump || dist < kDistBetweenPools) &&
21231d922960e083906a586609ac6978678147250177Sebastian Redl      // TODO(1236125): Cleanup the "magic" number below. We know that
21240e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      // the code generation will test every kCheckConstIntervalInst.
2125effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl      // Thus we are safe as long as we generate less than 7 constant
2126b3a99cd5bcaeff0c5ff6a60788b5eb68e52a3953Chris Lattner      // entries per instruction.
21271d922960e083906a586609ac6978678147250177Sebastian Redl      (num_prinfo_ < (kMaxNumPRInfo - (7 * kCheckConstIntervalInst)))) {
21281d922960e083906a586609ac6978678147250177Sebastian Redl    return;
21291d922960e083906a586609ac6978678147250177Sebastian Redl  }
21305508518a2702b00be3b15a26d772bde968972f54Anders Carlsson
2131f9bcf01f82dfd2688f81e57bcc6300c9b13c51a6Anders Carlsson  // If we did not return by now, we need to emit the constant pool soon.
2132f9bcf01f82dfd2688f81e57bcc6300c9b13c51a6Anders Carlsson
2133f9bcf01f82dfd2688f81e57bcc6300c9b13c51a6Anders Carlsson  // However, some small sequences of instructions must not be broken up by the
21341d922960e083906a586609ac6978678147250177Sebastian Redl  // insertion of a constant pool; such sequences are protected by setting
21351d922960e083906a586609ac6978678147250177Sebastian Redl  // either const_pool_blocked_nesting_ or no_const_pool_before_, which are
2136861cf3effdc0fbc97d401539bc3050da76b2476fSteve Naroff  // both checked here. Also, recursive calls to CheckConstPool are blocked by
21371d922960e083906a586609ac6978678147250177Sebastian Redl  // no_const_pool_before_.
2138f9bcf01f82dfd2688f81e57bcc6300c9b13c51a6Anders Carlsson  if (const_pool_blocked_nesting_ > 0 || pc_offset() < no_const_pool_before_) {
21391d922960e083906a586609ac6978678147250177Sebastian Redl    // Emission is currently blocked; make sure we try again as soon as
21404fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner    // possible.
21411d922960e083906a586609ac6978678147250177Sebastian Redl    if (const_pool_blocked_nesting_ > 0) {
21421d922960e083906a586609ac6978678147250177Sebastian Redl      next_buffer_check_ = pc_offset() + kInstrSize;
2143f9bcf01f82dfd2688f81e57bcc6300c9b13c51a6Anders Carlsson    } else {
21441d922960e083906a586609ac6978678147250177Sebastian Redl      next_buffer_check_ = no_const_pool_before_;
2145809070a886684cb5b92eb0e00a6581ab1fa6b17aDouglas Gregor    }
21461d922960e083906a586609ac6978678147250177Sebastian Redl
21474988ae3fda10743c8ed8a98cdcb5a783362587b4Anders Carlsson    // Something is wrong if emission is forced and blocked at the same time.
21481d922960e083906a586609ac6978678147250177Sebastian Redl    ASSERT(!force_emit);
2149809070a886684cb5b92eb0e00a6581ab1fa6b17aDouglas Gregor    return;
2150809070a886684cb5b92eb0e00a6581ab1fa6b17aDouglas Gregor  }
2151809070a886684cb5b92eb0e00a6581ab1fa6b17aDouglas Gregor
21521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  int jump_instr = require_jump ? kInstrSize : 0;
2153809070a886684cb5b92eb0e00a6581ab1fa6b17aDouglas Gregor
2154f9bcf01f82dfd2688f81e57bcc6300c9b13c51a6Anders Carlsson  // Check that the code buffer is large enough before emitting the constant
215529b2cb1ff1a3dd78edd38e2f43ee7041d3e4ec3cAnders Carlsson  // pool and relocation information (include the jump over the pool and the
215629b2cb1ff1a3dd78edd38e2f43ee7041d3e4ec3cAnders Carlsson  // constant pool marker).
215729b2cb1ff1a3dd78edd38e2f43ee7041d3e4ec3cAnders Carlsson  int max_needed_space =
21581d922960e083906a586609ac6978678147250177Sebastian Redl      jump_instr + kInstrSize + num_prinfo_*(kInstrSize + kMaxRelocSize);
21591d922960e083906a586609ac6978678147250177Sebastian Redl  while (buffer_space() <= (max_needed_space + kGap)) GrowBuffer();
216029b2cb1ff1a3dd78edd38e2f43ee7041d3e4ec3cAnders Carlsson
21611d922960e083906a586609ac6978678147250177Sebastian Redl  // Block recursive calls to CheckConstPool.
21624fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner  BlockConstPoolBefore(pc_offset() + jump_instr + kInstrSize +
21631d922960e083906a586609ac6978678147250177Sebastian Redl                       num_prinfo_*kInstrSize);
21641d922960e083906a586609ac6978678147250177Sebastian Redl  // Don't bother to check for the emit calls below.
216529b2cb1ff1a3dd78edd38e2f43ee7041d3e4ec3cAnders Carlsson  next_buffer_check_ = no_const_pool_before_;
21661d922960e083906a586609ac6978678147250177Sebastian Redl
21674fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner  // Emit jump over constant pool if necessary.
21681d922960e083906a586609ac6978678147250177Sebastian Redl  Label after_pool;
21691d922960e083906a586609ac6978678147250177Sebastian Redl  if (require_jump) b(&after_pool);
2170390d50a725497e99247dc104a7d2c2a255d3af14Fariborz Jahanian
217129b2cb1ff1a3dd78edd38e2f43ee7041d3e4ec3cAnders Carlsson  RecordComment("[ Constant Pool");
21721d922960e083906a586609ac6978678147250177Sebastian Redl
21734988ae3fda10743c8ed8a98cdcb5a783362587b4Anders Carlsson  // Put down constant pool marker "Undefined instruction" as specified by
217429b2cb1ff1a3dd78edd38e2f43ee7041d3e4ec3cAnders Carlsson  // A3.1 Instruction set encoding.
21751d922960e083906a586609ac6978678147250177Sebastian Redl  emit(0x03000000 | num_prinfo_);
21761d922960e083906a586609ac6978678147250177Sebastian Redl
217729b2cb1ff1a3dd78edd38e2f43ee7041d3e4ec3cAnders Carlsson  // Emit constant pool entries.
2178a0818e3cd7d59d05e6da41015033b5574c3d7893Fariborz Jahanian  for (int i = 0; i < num_prinfo_; i++) {
2179a0818e3cd7d59d05e6da41015033b5574c3d7893Fariborz Jahanian    RelocInfo& rinfo = prinfo_[i];
2180a0818e3cd7d59d05e6da41015033b5574c3d7893Fariborz Jahanian    ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
21811d922960e083906a586609ac6978678147250177Sebastian Redl           rinfo.rmode() != RelocInfo::POSITION &&
21821d922960e083906a586609ac6978678147250177Sebastian Redl           rinfo.rmode() != RelocInfo::STATEMENT_POSITION);
2183a0818e3cd7d59d05e6da41015033b5574c3d7893Fariborz Jahanian    Instr instr = instr_at(rinfo.pc());
21841d922960e083906a586609ac6978678147250177Sebastian Redl
21854fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner    // Instruction to patch must be a ldr/str [pc, #offset].
21861d922960e083906a586609ac6978678147250177Sebastian Redl    // P and U set, B and W clear, Rn == pc, offset12 still 0.
21871d922960e083906a586609ac6978678147250177Sebastian Redl    ASSERT((instr & (7*B25 | P | U | B | W | 15*B16 | Off12Mask)) ==
2188b62f6813406a03bf8a371c4e46c9fad51d102121Fariborz Jahanian           (2*B25 | P | U | pc.code()*B16));
2189a0818e3cd7d59d05e6da41015033b5574c3d7893Fariborz Jahanian    int delta = pc_ - rinfo.pc() - 8;
2190a0818e3cd7d59d05e6da41015033b5574c3d7893Fariborz Jahanian    ASSERT(delta >= -4);  // instr could be ldr pc, [pc, #-4] followed by targ32
21912fc5c2428ecb450a3256c8316b93b8655cb76a0fChris Lattner    if (delta < 0) {
21921d922960e083906a586609ac6978678147250177Sebastian Redl      instr &= ~U;
21931d922960e083906a586609ac6978678147250177Sebastian Redl      delta = -delta;
21941d922960e083906a586609ac6978678147250177Sebastian Redl    }
2195b62f6813406a03bf8a371c4e46c9fad51d102121Fariborz Jahanian    ASSERT(is_uint12(delta));
2196887407e71fd58de452361b77d72970e32b20ebe0Steve Naroff    instr_at_put(rinfo.pc(), instr + delta);
2197887407e71fd58de452361b77d72970e32b20ebe0Steve Naroff    emit(rinfo.data());
2198a0818e3cd7d59d05e6da41015033b5574c3d7893Fariborz Jahanian  }
21994fef81d718ca1b91ce2adef52db91a35f86e9bbdChris Lattner  num_prinfo_ = 0;
22001d922960e083906a586609ac6978678147250177Sebastian Redl  last_const_pool_end_ = pc_offset();
22011d922960e083906a586609ac6978678147250177Sebastian Redl
2202cb53b361bce341c8591333c6997f62e480acc0b4Chris Lattner  RecordComment("]");
2203a0818e3cd7d59d05e6da41015033b5574c3d7893Fariborz Jahanian
2204a0818e3cd7d59d05e6da41015033b5574c3d7893Fariborz Jahanian  if (after_pool.is_linked()) {
2205a0818e3cd7d59d05e6da41015033b5574c3d7893Fariborz Jahanian    bind(&after_pool);
2206a0818e3cd7d59d05e6da41015033b5574c3d7893Fariborz Jahanian  }
2207a0818e3cd7d59d05e6da41015033b5574c3d7893Fariborz Jahanian
22082fc5c2428ecb450a3256c8316b93b8655cb76a0fChris Lattner  // Since a constant pool was just emitted, move the check offset forward by
2209b62f6813406a03bf8a371c4e46c9fad51d102121Fariborz Jahanian  // the standard interval.
2210a0818e3cd7d59d05e6da41015033b5574c3d7893Fariborz Jahanian  next_buffer_check_ = pc_offset() + kCheckConstInterval;
2211a0818e3cd7d59d05e6da41015033b5574c3d7893Fariborz Jahanian}
2212a0818e3cd7d59d05e6da41015033b5574c3d7893Fariborz Jahanian
2213887407e71fd58de452361b77d72970e32b20ebe0Steve Naroff
2214a0818e3cd7d59d05e6da41015033b5574c3d7893Fariborz Jahanian} }  // namespace v8::internal
2215887407e71fd58de452361b77d72970e32b20ebe0Steve Naroff
22161d922960e083906a586609ac6978678147250177Sebastian Redl#endif  // V8_TARGET_ARCH_ARM
22171d922960e083906a586609ac6978678147250177Sebastian Redl