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