1b78f13911bfe6eda303e91ef215c87a165aae8aeAlexandre Rames// Copyright 2015, VIXL authors 288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// All rights reserved. 388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// 488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// Redistribution and use in source and binary forms, with or without 588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// modification, are permitted provided that the following conditions are met: 688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// 788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// * Redistributions of source code must retain the above copyright notice, 888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// this list of conditions and the following disclaimer. 988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// * Redistributions in binary form must reproduce the above copyright 1088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// notice, this list of conditions and the following disclaimer in the 1188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// documentation and/or other materials provided with the distribution. 1288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// * Neither the name of ARM Limited nor the names of its contributors may 1388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// be used to endorse or promote products derived from this software 1488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// without specific prior written permission. 1588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// 1688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 1788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// POSSIBILITY OF SUCH DAMAGE. 2788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 28d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames#include "aarch32/macro-assembler-aarch32.h" 2988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 3021d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell#define STRINGIFY(x) #x 3121d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell#define TOSTRING(x) STRINGIFY(x) 3221d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell 3321d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell#define CONTEXT_SCOPE \ 3421d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell ContextScope context(this, __FILE__ ":" TOSTRING(__LINE__)) 3521d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell 3688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisnamespace vixl { 3788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisnamespace aarch32 { 3888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 39a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard// We use a subclass to access the protected `ExactAssemblyScope` constructor 40a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard// giving us control over the pools, and make the constructor private to limit 41a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard// usage to code paths emitting pools. 42a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliardclass ExactAssemblyScopeWithoutPoolsCheck : public ExactAssemblyScope { 43a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard private: 44a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard ExactAssemblyScopeWithoutPoolsCheck(MacroAssembler* masm, 45a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard size_t size, 46a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard SizePolicy size_policy = kExactSize) 47a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard : ExactAssemblyScope(masm, 48a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard size, 49a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard size_policy, 50a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard ExactAssemblyScope::kIgnorePools) {} 51a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard 52a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard friend class MacroAssembler; 53a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard friend class VeneerPoolManager; 54a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard}; 55a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard 56a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard 5788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid UseScratchRegisterScope::Open(MacroAssembler* masm) { 58e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_ASSERT(masm_ == NULL); 59e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_ASSERT(masm != NULL); 60e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley masm_ = masm; 61e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley 62e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley old_available_ = masm_->GetScratchRegisterList()->GetList(); 63e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley old_available_vfp_ = masm_->GetScratchVRegisterList()->GetList(); 64e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley 65e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley parent_ = masm->GetCurrentScratchRegisterScope(); 66e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley masm->SetCurrentScratchRegisterScope(this); 6788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 6888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 6988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 7088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid UseScratchRegisterScope::Close() { 71e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley if (masm_ != NULL) { 72e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley // Ensure that scopes nest perfectly, and do not outlive their parents. 73e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley // This is a run-time check because the order of destruction of objects in 74e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley // the _same_ scope is implementation-defined, and is likely to change in 75e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley // optimised builds. 76e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_CHECK(masm_->GetCurrentScratchRegisterScope() == this); 77e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley masm_->SetCurrentScratchRegisterScope(parent_); 78e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley 79e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley masm_->GetScratchRegisterList()->SetList(old_available_); 80e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley masm_->GetScratchVRegisterList()->SetList(old_available_vfp_); 81e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley 82e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley masm_ = NULL; 8388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 8488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 8588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 8688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 8788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisbool UseScratchRegisterScope::IsAvailable(const Register& reg) const { 88e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_ASSERT(masm_ != NULL); 8988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_ASSERT(reg.IsValid()); 90e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley return masm_->GetScratchRegisterList()->Includes(reg); 9188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 9288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 9388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 9488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisbool UseScratchRegisterScope::IsAvailable(const VRegister& reg) const { 95e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_ASSERT(masm_ != NULL); 9688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_ASSERT(reg.IsValid()); 97e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley return masm_->GetScratchVRegisterList()->IncludesAllOf(reg); 9888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 9988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 10088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 10188c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisRegister UseScratchRegisterScope::Acquire() { 102e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_ASSERT(masm_ != NULL); 103e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley Register reg = masm_->GetScratchRegisterList()->GetFirstAvailableRegister(); 104e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_CHECK(reg.IsValid()); 105e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley masm_->GetScratchRegisterList()->Remove(reg); 10688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return reg; 10788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 10888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 10988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 11088c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisVRegister UseScratchRegisterScope::AcquireV(unsigned size_in_bits) { 11188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois switch (size_in_bits) { 11288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case kSRegSizeInBits: 11388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return AcquireS(); 11488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case kDRegSizeInBits: 11588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return AcquireD(); 11688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case kQRegSizeInBits: 11788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return AcquireQ(); 11888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois default: 11988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_UNREACHABLE(); 12088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return NoVReg; 12188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 12288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 12388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 12488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 12588c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisQRegister UseScratchRegisterScope::AcquireQ() { 126e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_ASSERT(masm_ != NULL); 127e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley QRegister reg = 128e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley masm_->GetScratchVRegisterList()->GetFirstAvailableQRegister(); 129e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_CHECK(reg.IsValid()); 130e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley masm_->GetScratchVRegisterList()->Remove(reg); 13188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return reg; 13288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 13388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 13488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 13588c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisDRegister UseScratchRegisterScope::AcquireD() { 136e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_ASSERT(masm_ != NULL); 137e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley DRegister reg = 138e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley masm_->GetScratchVRegisterList()->GetFirstAvailableDRegister(); 139e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_CHECK(reg.IsValid()); 140e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley masm_->GetScratchVRegisterList()->Remove(reg); 14188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return reg; 14288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 14388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 14488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 14588c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisSRegister UseScratchRegisterScope::AcquireS() { 146e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_ASSERT(masm_ != NULL); 147e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley SRegister reg = 148e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley masm_->GetScratchVRegisterList()->GetFirstAvailableSRegister(); 149e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_CHECK(reg.IsValid()); 150e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley masm_->GetScratchVRegisterList()->Remove(reg); 15188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return reg; 15288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 15388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 15488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 15588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid UseScratchRegisterScope::Release(const Register& reg) { 156e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_ASSERT(masm_ != NULL); 15788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_ASSERT(reg.IsValid()); 158e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_ASSERT(!masm_->GetScratchRegisterList()->Includes(reg)); 159e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley masm_->GetScratchRegisterList()->Combine(reg); 16088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 16188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 16288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 16388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid UseScratchRegisterScope::Release(const VRegister& reg) { 164e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_ASSERT(masm_ != NULL); 16588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_ASSERT(reg.IsValid()); 166e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_ASSERT(!masm_->GetScratchVRegisterList()->IncludesAliasOf(reg)); 167e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley masm_->GetScratchVRegisterList()->Combine(reg); 16888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 16988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 17088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 17188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid UseScratchRegisterScope::Include(const RegisterList& list) { 172e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_ASSERT(masm_ != NULL); 17388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois RegisterList excluded_registers(sp, lr, pc); 17488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois uint32_t mask = list.GetList() & ~excluded_registers.GetList(); 175e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley RegisterList* available = masm_->GetScratchRegisterList(); 176e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley available->SetList(available->GetList() | mask); 17788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 17888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 17988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 18088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid UseScratchRegisterScope::Include(const VRegisterList& list) { 181e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_ASSERT(masm_ != NULL); 182e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VRegisterList* available = masm_->GetScratchVRegisterList(); 183e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley available->SetList(available->GetList() | list.GetList()); 18488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 18588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 18688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 18788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid UseScratchRegisterScope::Exclude(const RegisterList& list) { 188e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_ASSERT(masm_ != NULL); 189e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley RegisterList* available = masm_->GetScratchRegisterList(); 190e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley available->SetList(available->GetList() & ~list.GetList()); 19188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 19288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 19388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 19488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid UseScratchRegisterScope::Exclude(const VRegisterList& list) { 195e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_ASSERT(masm_ != NULL); 196e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VRegisterList* available = masm_->GetScratchVRegisterList(); 197e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley available->SetList(available->GetList() & ~list.GetList()); 19888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 19988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 20088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 2019ee25b5df54608e45947a7f99f2c23ce61802474Jacob Bramleyvoid UseScratchRegisterScope::Exclude(const Operand& operand) { 2029ee25b5df54608e45947a7f99f2c23ce61802474Jacob Bramley if (operand.IsImmediateShiftedRegister()) { 2039ee25b5df54608e45947a7f99f2c23ce61802474Jacob Bramley Exclude(operand.GetBaseRegister()); 2049ee25b5df54608e45947a7f99f2c23ce61802474Jacob Bramley } else if (operand.IsRegisterShiftedRegister()) { 2059ee25b5df54608e45947a7f99f2c23ce61802474Jacob Bramley Exclude(operand.GetBaseRegister(), operand.GetShiftRegister()); 2069ee25b5df54608e45947a7f99f2c23ce61802474Jacob Bramley } else { 2079ee25b5df54608e45947a7f99f2c23ce61802474Jacob Bramley VIXL_ASSERT(operand.IsImmediate()); 2089ee25b5df54608e45947a7f99f2c23ce61802474Jacob Bramley } 2099ee25b5df54608e45947a7f99f2c23ce61802474Jacob Bramley} 2109ee25b5df54608e45947a7f99f2c23ce61802474Jacob Bramley 2119ee25b5df54608e45947a7f99f2c23ce61802474Jacob Bramley 21288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid UseScratchRegisterScope::ExcludeAll() { 213e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley VIXL_ASSERT(masm_ != NULL); 214e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley masm_->GetScratchRegisterList()->SetList(0); 215e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley masm_->GetScratchVRegisterList()->SetList(0); 21688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 21788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 21888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 2197827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliardvoid VeneerPoolManager::AddLabel(Label* label) { 22015985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard if (last_label_reference_offset_ != 0) { 22115985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // If the pool grows faster than the instruction stream, we must adjust 22215985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // the checkpoint to compensate. The veneer pool entries take 32 bits, so 22315985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // this can only occur when two consecutive 16-bit instructions add veneer 22415985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // pool entries. 22515985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // This is typically the case for cbz and cbnz (other forward branches 22615985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // have a 32 bit variant which is always used). 22715985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard if (last_label_reference_offset_ + 2 * k16BitT32InstructionSizeInBytes == 22815985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard static_cast<uint32_t>(masm_->GetCursorOffset())) { 22915985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // We found two 16 bit forward branches generated one after the other. 23015985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // That means that the pool will grow by one 32-bit branch when 23115985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // the cursor offset will move forward by only one 16-bit branch. 2322272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard // Update the near checkpoint margin to manage the difference. 2332272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard near_checkpoint_margin_ += 23415985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard k32BitT32InstructionSizeInBytes - k16BitT32InstructionSizeInBytes; 23515985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard } 2367827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard } 2377827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard Label::ForwardReference& back = label->GetBackForwardRef(); 23815985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard VIXL_ASSERT(back.GetMaxForwardDistance() >= kCbzCbnzRange); 23915985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard if (!label->IsInVeneerPool()) { 2404a30c5d68ebbc271d6d876d828ffa96db53d8d7cVincent Belliard if (back.GetMaxForwardDistance() <= kNearLabelRange) { 24115985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard near_labels_.push_back(label); 24215985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard label->SetVeneerPoolManager(this, true); 24315985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard } else { 24415985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard far_labels_.push_back(label); 24515985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard label->SetVeneerPoolManager(this, false); 24615985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard } 2474a30c5d68ebbc271d6d876d828ffa96db53d8d7cVincent Belliard } else if (back.GetMaxForwardDistance() <= kNearLabelRange) { 24815985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard if (!label->IsNear()) { 24915985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard far_labels_.remove(label); 25015985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard near_labels_.push_back(label); 25115985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard label->SetVeneerPoolManager(this, true); 25215985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard } 25315985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard } 25415985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard 2557827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard back.SetIsBranch(); 25615985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard last_label_reference_offset_ = back.GetLocation(); 2577827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard label->UpdateCheckpoint(); 2587827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard Label::Offset tmp = label->GetCheckpoint(); 25915985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard if (label->IsNear()) { 26015985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard if (near_checkpoint_ > tmp) near_checkpoint_ = tmp; 2612272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard if (max_near_checkpoint_ >= tmp) { 2622272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard // This checkpoint is before some already in the near list. That means 2632272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard // that the veneer (if needed) will be emitted before some of the veneers 2642272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard // already in the list. We adjust the margin with the size of a veneer 2652272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard // branch. 2662272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard near_checkpoint_margin_ += k32BitT32InstructionSizeInBytes; 2672272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard } else { 2682272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard max_near_checkpoint_ = tmp; 2692272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard } 27015985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard } else { 27115985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard if (far_checkpoint_ > tmp) far_checkpoint_ = tmp; 2727827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard } 27315985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // Always compute the global checkpoint as, adding veneers shorten the 27415985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // literals' checkpoint. 27515985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard masm_->ComputeCheckpoint(); 2767827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard} 2777827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard 2787827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard 2797827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliardvoid VeneerPoolManager::RemoveLabel(Label* label) { 2807827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard label->ClearVeneerPoolManager(); 28115985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard std::list<Label*>& list = label->IsNear() ? near_labels_ : far_labels_; 28215985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard Label::Offset* checkpoint_reference = 28315985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard label->IsNear() ? &near_checkpoint_ : &far_checkpoint_; 28415985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard if (label->GetCheckpoint() == *checkpoint_reference) { 28588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // We have to compute checkpoint again. 28615985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard *checkpoint_reference = Label::kMaxOffset; 28715985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard for (std::list<Label*>::iterator it = list.begin(); it != list.end();) { 28888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (*it == label) { 28915985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard it = list.erase(it); 29088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } else { 29115985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard *checkpoint_reference = 29215985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard std::min(*checkpoint_reference, (*it)->GetCheckpoint()); 29388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois ++it; 29488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 29588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 29688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois masm_->ComputeCheckpoint(); 29788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } else { 29888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // We only have to remove the label from the list. 29915985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard list.remove(label); 30015985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard } 30115985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard} 30215985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard 30315985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard 30415985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliardvoid VeneerPoolManager::EmitLabel(Label* label, Label::Offset emitted_target) { 305d56f609907e454dd41bb8b2d98e078e69c4feafaPierre Langlois VIXL_ASSERT(!IsBlocked()); 30615985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // Define the veneer. 30715985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard Label veneer; 30815985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard masm_->Bind(&veneer); 30915985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard Label::Offset label_checkpoint = Label::kMaxOffset; 31015985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // Check all uses of this label. 31115985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard for (Label::ForwardRefList::iterator ref = label->GetFirstForwardRef(); 31215985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard ref != label->GetEndForwardRef();) { 31315985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard if (ref->IsBranch()) { 31415985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard if (ref->GetCheckpoint() <= emitted_target) { 31515985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // Use the veneer. 31615985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard masm_->EncodeLabelFor(*ref, &veneer); 31715985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard ref = label->Erase(ref); 31815985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard } else { 31915985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // Don't use the veneer => update checkpoint. 32015985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard label_checkpoint = std::min(label_checkpoint, ref->GetCheckpoint()); 32115985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard ++ref; 32288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 32315985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard } else { 32415985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard ++ref; 32588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 32688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 32715985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard label->SetCheckpoint(label_checkpoint); 32815985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard if (label->IsNear()) { 32915985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard near_checkpoint_ = std::min(near_checkpoint_, label_checkpoint); 33015985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard } else { 33115985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard far_checkpoint_ = std::min(far_checkpoint_, label_checkpoint); 33215985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard } 33315985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // Generate the veneer. 334a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard ExactAssemblyScopeWithoutPoolsCheck guard(masm_, 335a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard kMaxInstructionSizeInBytes, 336a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard ExactAssemblyScope::kMaximumSize); 337a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard masm_->b(label); 338a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard masm_->AddBranchLabel(label); 33988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 34088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 34188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 3427827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliardvoid VeneerPoolManager::Emit(Label::Offset target) { 3438d191abf32edf41421f68f35585e4fce8da4d50cAlexandre Rames VIXL_ASSERT(!IsBlocked()); 34488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // Sort labels (regarding their checkpoint) to avoid that a veneer 3452272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard // becomes out of range. 3462272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard near_labels_.sort(Label::CompareLabels); 34715985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard far_labels_.sort(Label::CompareLabels); 34888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // To avoid too many veneers, generate veneers which will be necessary soon. 349a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard target += static_cast<int>(GetMaxSize()) + near_checkpoint_margin_; 35088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois static const size_t kVeneerEmissionMargin = 1 * KBytes; 35188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // To avoid too many veneers, use generated veneers for other not too far 35288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // uses. 35388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois static const size_t kVeneerEmittedMargin = 2 * KBytes; 35488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Label::Offset emitted_target = target + kVeneerEmittedMargin; 35588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois target += kVeneerEmissionMargin; 35615985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // Reset the checkpoints. They will be computed again in the loop. 35715985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard near_checkpoint_ = Label::kMaxOffset; 35815985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard far_checkpoint_ = Label::kMaxOffset; 3592272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard max_near_checkpoint_ = 0; 3602272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard near_checkpoint_margin_ = 0; 36115985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard for (std::list<Label*>::iterator it = near_labels_.begin(); 36215985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard it != near_labels_.end();) { 36315985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard Label* label = *it; 36415985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // Move the label from the near list to the far list as it will be needed in 36515985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // the far list (as the veneer will generate a far branch). 36615985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // The label is pushed at the end of the list. The list remains sorted as 36715985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // we use an unconditional jump which has the biggest range. However, it 36815985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // wouldn't be a problem if the items at the end of the list were not 36915985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // sorted as they won't be used by this generation (their range will be 37015985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard // greater than kVeneerEmittedMargin). 37115985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard it = near_labels_.erase(it); 37215985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard far_labels_.push_back(label); 37315985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard label->SetVeneerPoolManager(this, false); 37415985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard EmitLabel(label, emitted_target); 37515985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard } 37615985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard for (std::list<Label*>::iterator it = far_labels_.begin(); 37715985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard it != far_labels_.end();) { 37888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // The labels are sorted. As soon as a veneer is not needed, we can stop. 37988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if ((*it)->GetCheckpoint() > target) { 38015985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard far_checkpoint_ = std::min(far_checkpoint_, (*it)->GetCheckpoint()); 38188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 38288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 38388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // Even if we no longer have use of this label, we can keep it in the list 38488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // as the next "B" would add it back. 38515985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard EmitLabel(*it, emitted_target); 38688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois ++it; 38788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 38888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#ifdef VIXL_DEBUG 38915985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard for (std::list<Label*>::iterator it = near_labels_.begin(); 39015985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard it != near_labels_.end(); 39115985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard ++it) { 39215985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard VIXL_ASSERT((*it)->GetCheckpoint() >= near_checkpoint_); 39315985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard } 39415985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard for (std::list<Label*>::iterator it = far_labels_.begin(); 39515985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard it != far_labels_.end(); 39688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois ++it) { 39715985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard VIXL_ASSERT((*it)->GetCheckpoint() >= far_checkpoint_); 39888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 39988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#endif 40088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois masm_->ComputeCheckpoint(); 40188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 40288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 40388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 40488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid MacroAssembler::PerformEnsureEmit(Label::Offset target, uint32_t size) { 405a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard EmitOption option = kBranchRequired; 406a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard Label after_pools; 407a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard Label::Offset literal_target = GetTargetForLiteralEmission(); 408a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard VIXL_ASSERT(literal_target >= 0); 409a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard bool generate_veneers = target > veneer_pool_manager_.GetCheckpoint(); 410a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard if (target > literal_target) { 411a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard // We will generate the literal pool. Generate all the veneers which 412a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard // would become out of range. 413a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard size_t literal_pool_size = 414a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard literal_pool_manager_.GetLiteralPoolSize() + kMaxInstructionSizeInBytes; 415a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard VIXL_ASSERT(IsInt32(literal_pool_size)); 416a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard Label::Offset veneers_target = 417a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard AlignUp(target + static_cast<Label::Offset>(literal_pool_size), 4); 418a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard VIXL_ASSERT(veneers_target >= 0); 419a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard if (veneers_target > veneer_pool_manager_.GetCheckpoint()) { 420a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard generate_veneers = true; 42188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 422a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard } 423fb37b5d8438252728469290fa35a779817faea00Pierre Langlois if (!IsVeneerPoolBlocked() && generate_veneers) { 424a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard { 425a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard ExactAssemblyScopeWithoutPoolsCheck 426a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard guard(this, 427a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard kMaxInstructionSizeInBytes, 428a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard ExactAssemblyScope::kMaximumSize); 429a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard b(&after_pools); 430bd087d8fe70f7db770f37569073b8b9f77a9c372Vincent Belliard } 431a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard veneer_pool_manager_.Emit(target); 432a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard option = kNoBranchRequired; 433a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard } 434a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard // Check if the macro-assembler's internal literal pool should be emitted 435a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard // to avoid any overflow. If we already generated the veneers, we can 436a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard // emit the pool (the branch is already done). 437fb37b5d8438252728469290fa35a779817faea00Pierre Langlois if (!IsLiteralPoolBlocked() && 438d56f609907e454dd41bb8b2d98e078e69c4feafaPierre Langlois ((target > literal_target) || (option == kNoBranchRequired))) { 439a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard EmitLiteralPool(option); 44088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 441a4cbc576a003da934ab58b293d9023d9b6f3077bVincent Belliard BindHelper(&after_pools); 442919e3fe28a5024c53ede42922092bbc32e89dcb8Alexandre Rames if (GetBuffer()->IsManaged()) { 44388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois bool grow_requested; 444919e3fe28a5024c53ede42922092bbc32e89dcb8Alexandre Rames GetBuffer()->EnsureSpaceFor(size, &grow_requested); 44588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (grow_requested) ComputeCheckpoint(); 44688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 44788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 44888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 44988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 45088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid MacroAssembler::ComputeCheckpoint() { 451bd087d8fe70f7db770f37569073b8b9f77a9c372Vincent Belliard checkpoint_ = AlignDown(std::min(veneer_pool_manager_.GetCheckpoint(), 452bd087d8fe70f7db770f37569073b8b9f77a9c372Vincent Belliard GetTargetForLiteralEmission()), 453bd087d8fe70f7db770f37569073b8b9f77a9c372Vincent Belliard 4); 454919e3fe28a5024c53ede42922092bbc32e89dcb8Alexandre Rames size_t buffer_size = GetBuffer()->GetCapacity(); 455f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois VIXL_ASSERT(IsInt32(buffer_size)); 456f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois Label::Offset buffer_checkpoint = static_cast<Label::Offset>(buffer_size); 45788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois checkpoint_ = std::min(checkpoint_, buffer_checkpoint); 45888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 45988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 46088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 4611661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Ramesvoid MacroAssembler::EmitLiteralPool(LiteralPool* const literal_pool, 4621661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames EmitOption option) { 463fb37b5d8438252728469290fa35a779817faea00Pierre Langlois VIXL_ASSERT(!IsLiteralPoolBlocked()); 4641661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames if (literal_pool->GetSize() > 0) { 4651661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames#ifdef VIXL_DEBUG 4661661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames for (LiteralPool::RawLiteralListIterator literal_it = 4671661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames literal_pool->GetFirst(); 4681661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames literal_it != literal_pool->GetEnd(); 4691661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames literal_it++) { 4701661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames RawLiteral* literal = *literal_it; 4711661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames VIXL_ASSERT(GetCursorOffset() < literal->GetCheckpoint()); 4721661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames } 4731661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames#endif 4741661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames Label after_literal; 4751661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames if (option == kBranchRequired) { 4761661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames GetBuffer()->EnsureSpaceFor(kMaxInstructionSizeInBytes); 4771661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames VIXL_ASSERT(!AllowAssembler()); 4781661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames { 4791661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames ExactAssemblyScopeWithoutPoolsCheck 4801661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames guard(this, 4811661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames kMaxInstructionSizeInBytes, 4821661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames ExactAssemblyScope::kMaximumSize); 4831661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames b(&after_literal); 4841661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames } 4851661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames } 4861661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames GetBuffer()->Align(); 4871661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames GetBuffer()->EnsureSpaceFor(literal_pool->GetSize()); 4881661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames for (LiteralPool::RawLiteralListIterator it = literal_pool->GetFirst(); 4891661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames it != literal_pool->GetEnd(); 4901661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames it++) { 4911661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames PlaceHelper(*it); 4921661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames GetBuffer()->Align(); 4931661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames } 4941661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames if (option == kBranchRequired) BindHelper(&after_literal); 4951661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames literal_pool->Clear(); 4961661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames } 4971661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames} 4981661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames 4991661f51a172e7c3dcce6caca55b6fe6d10ebd416Alexandre Rames 50088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid MacroAssembler::HandleOutOfBoundsImmediate(Condition cond, 50188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register tmp, 50288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois uint32_t imm) { 50321376f637832074ecd3e00f2bf9c708e5e0244b4Vincent Belliard if (IsUintN(16, imm)) { 504aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 5058885c17bce593f82cf90c086da242e52943c50efVincent Belliard mov(cond, tmp, imm & 0xffff); 50621376f637832074ecd3e00f2bf9c708e5e0244b4Vincent Belliard return; 50721376f637832074ecd3e00f2bf9c708e5e0244b4Vincent Belliard } 50821376f637832074ecd3e00f2bf9c708e5e0244b4Vincent Belliard if (IsUsingT32()) { 50921376f637832074ecd3e00f2bf9c708e5e0244b4Vincent Belliard if (ImmediateT32::IsImmediateT32(~imm)) { 510aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 5118885c17bce593f82cf90c086da242e52943c50efVincent Belliard mvn(cond, tmp, ~imm); 51221376f637832074ecd3e00f2bf9c708e5e0244b4Vincent Belliard return; 51321376f637832074ecd3e00f2bf9c708e5e0244b4Vincent Belliard } 51421376f637832074ecd3e00f2bf9c708e5e0244b4Vincent Belliard } else { 51521376f637832074ecd3e00f2bf9c708e5e0244b4Vincent Belliard if (ImmediateA32::IsImmediateA32(~imm)) { 516aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 5178885c17bce593f82cf90c086da242e52943c50efVincent Belliard mvn(cond, tmp, ~imm); 51821376f637832074ecd3e00f2bf9c708e5e0244b4Vincent Belliard return; 51921376f637832074ecd3e00f2bf9c708e5e0244b4Vincent Belliard } 52021376f637832074ecd3e00f2bf9c708e5e0244b4Vincent Belliard } 521aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, 2 * kMaxInstructionSizeInBytes); 5228885c17bce593f82cf90c086da242e52943c50efVincent Belliard mov(cond, tmp, imm & 0xffff); 5238885c17bce593f82cf90c086da242e52943c50efVincent Belliard movt(cond, tmp, imm >> 16); 52488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 52588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 52688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 527f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliardvoid MacroAssembler::PadToMinimumBranchRange(Label* label) { 528f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard const Label::ForwardReference* last_reference = label->GetForwardRefBack(); 529f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard if ((last_reference != NULL) && last_reference->IsUsingT32()) { 530f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard uint32_t location = last_reference->GetLocation(); 531f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard if (location + k16BitT32InstructionSizeInBytes == 532f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard static_cast<uint32_t>(GetCursorOffset())) { 533f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard uint16_t* instr_ptr = buffer_.GetOffsetAddress<uint16_t*>(location); 534f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard if ((instr_ptr[0] & kCbzCbnzMask) == kCbzCbnzValue) { 535f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard VIXL_ASSERT(!InITBlock()); 536f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard // A Cbz or a Cbnz can't jump immediately after the instruction. If the 537f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard // target is immediately after the Cbz or Cbnz, we insert a nop to 538f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard // avoid that. 539f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard EmitT32_16(k16BitT32NopOpcode); 540f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard } 541f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard } 542f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard } 543f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard} 544f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard 545f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard 546f8c2284645ce651f99ba410a512279102851076eJacob BramleyMemOperand MacroAssembler::MemOperandComputationHelper( 547f8c2284645ce651f99ba410a512279102851076eJacob Bramley Condition cond, 548f8c2284645ce651f99ba410a512279102851076eJacob Bramley Register scratch, 549f8c2284645ce651f99ba410a512279102851076eJacob Bramley Register base, 550f8c2284645ce651f99ba410a512279102851076eJacob Bramley uint32_t offset, 551f8c2284645ce651f99ba410a512279102851076eJacob Bramley uint32_t extra_offset_mask) { 552f8c2284645ce651f99ba410a512279102851076eJacob Bramley VIXL_ASSERT(!AliasesAvailableScratchRegister(scratch)); 553f8c2284645ce651f99ba410a512279102851076eJacob Bramley VIXL_ASSERT(!AliasesAvailableScratchRegister(base)); 554f8c2284645ce651f99ba410a512279102851076eJacob Bramley VIXL_ASSERT(allow_macro_instructions_); 555f8c2284645ce651f99ba410a512279102851076eJacob Bramley VIXL_ASSERT(OutsideITBlock()); 556f8c2284645ce651f99ba410a512279102851076eJacob Bramley 557f8c2284645ce651f99ba410a512279102851076eJacob Bramley // Check for the simple pass-through case. 558f8c2284645ce651f99ba410a512279102851076eJacob Bramley if ((offset & extra_offset_mask) == offset) return MemOperand(base, offset); 559f8c2284645ce651f99ba410a512279102851076eJacob Bramley 560f8c2284645ce651f99ba410a512279102851076eJacob Bramley MacroEmissionCheckScope guard(this); 561f8c2284645ce651f99ba410a512279102851076eJacob Bramley ITScope it_scope(this, &cond); 562f8c2284645ce651f99ba410a512279102851076eJacob Bramley 563f8c2284645ce651f99ba410a512279102851076eJacob Bramley uint32_t load_store_offset = offset & extra_offset_mask; 56452e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley uint32_t add_offset = offset & ~extra_offset_mask; 565b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard if ((add_offset != 0) && 566b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard (IsModifiedImmediate(offset) || IsModifiedImmediate(-offset))) { 567b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard load_store_offset = 0; 568b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard add_offset = offset; 569b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard } 57052e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley 57152e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley if (base.IsPC()) { 57252e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley // Special handling for PC bases. We must read the PC in the first 57352e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley // instruction (and only in that instruction), and we must also take care to 57452e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley // keep the same address calculation as loads and stores. For T32, that 57552e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley // means using something like ADR, which uses AlignDown(PC, 4). 57652e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley 57752e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley // We don't handle positive offsets from PC because the intention is not 57852e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley // clear; does the user expect the offset from the current 57952e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley // GetCursorOffset(), or to allow a certain amount of space after the 58052e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley // instruction? 58152e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley VIXL_ASSERT((offset & 0x80000000) != 0); 58252e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley if (IsUsingT32()) { 58352e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley // T32: make the first instruction "SUB (immediate, from PC)" -- an alias 58452e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley // of ADR -- to get behaviour like loads and stores. This ADR can handle 58552e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley // at least as much offset as the load_store_offset so it can replace it. 58652e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley 58752e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley uint32_t sub_pc_offset = (-offset) & 0xfff; 58852e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley load_store_offset = (offset + sub_pc_offset) & extra_offset_mask; 58952e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley add_offset = (offset + sub_pc_offset) & ~extra_offset_mask; 59052e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley 59152e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley ExactAssemblyScope scope(this, k32BitT32InstructionSizeInBytes); 59252e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley sub(cond, scratch, base, sub_pc_offset); 59352e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley 59452e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley if (add_offset == 0) return MemOperand(scratch, load_store_offset); 59552e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley 59652e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley // The rest of the offset can be generated in the usual way. 59752e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley base = scratch; 59852e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley } 59952e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley // A32 can use any SUB instruction, so we don't have to do anything special 60052e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley // here except to ensure that we read the PC first. 60152e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley } 602f8c2284645ce651f99ba410a512279102851076eJacob Bramley 60352e987eb677af65859f169b20816fa5d293c6cf0Jacob Bramley add(cond, scratch, base, add_offset); 604f8c2284645ce651f99ba410a512279102851076eJacob Bramley return MemOperand(scratch, load_store_offset); 605f8c2284645ce651f99ba410a512279102851076eJacob Bramley} 606f8c2284645ce651f99ba410a512279102851076eJacob Bramley 607f8c2284645ce651f99ba410a512279102851076eJacob Bramley 608f8c2284645ce651f99ba410a512279102851076eJacob Bramleyuint32_t MacroAssembler::GetOffsetMask(InstructionType type, 609f8c2284645ce651f99ba410a512279102851076eJacob Bramley AddrMode addrmode) { 610f8c2284645ce651f99ba410a512279102851076eJacob Bramley switch (type) { 611f8c2284645ce651f99ba410a512279102851076eJacob Bramley case kLdr: 612f8c2284645ce651f99ba410a512279102851076eJacob Bramley case kLdrb: 613f8c2284645ce651f99ba410a512279102851076eJacob Bramley case kStr: 614f8c2284645ce651f99ba410a512279102851076eJacob Bramley case kStrb: 615f8c2284645ce651f99ba410a512279102851076eJacob Bramley if (IsUsingA32() || (addrmode == Offset)) { 616f8c2284645ce651f99ba410a512279102851076eJacob Bramley return 0xfff; 617f8c2284645ce651f99ba410a512279102851076eJacob Bramley } else { 618f8c2284645ce651f99ba410a512279102851076eJacob Bramley return 0xff; 619f8c2284645ce651f99ba410a512279102851076eJacob Bramley } 620f8c2284645ce651f99ba410a512279102851076eJacob Bramley case kLdrsb: 621f8c2284645ce651f99ba410a512279102851076eJacob Bramley case kLdrh: 622f8c2284645ce651f99ba410a512279102851076eJacob Bramley case kLdrsh: 623f8c2284645ce651f99ba410a512279102851076eJacob Bramley case kStrh: 624f8c2284645ce651f99ba410a512279102851076eJacob Bramley if (IsUsingT32() && (addrmode == Offset)) { 625f8c2284645ce651f99ba410a512279102851076eJacob Bramley return 0xfff; 626f8c2284645ce651f99ba410a512279102851076eJacob Bramley } else { 627f8c2284645ce651f99ba410a512279102851076eJacob Bramley return 0xff; 628f8c2284645ce651f99ba410a512279102851076eJacob Bramley } 629f8c2284645ce651f99ba410a512279102851076eJacob Bramley case kVldr: 630f8c2284645ce651f99ba410a512279102851076eJacob Bramley case kVstr: 631f8c2284645ce651f99ba410a512279102851076eJacob Bramley return 0x3fc; 632f8c2284645ce651f99ba410a512279102851076eJacob Bramley case kLdrd: 633f8c2284645ce651f99ba410a512279102851076eJacob Bramley case kStrd: 634f8c2284645ce651f99ba410a512279102851076eJacob Bramley if (IsUsingA32()) { 635f8c2284645ce651f99ba410a512279102851076eJacob Bramley return 0xff; 636f8c2284645ce651f99ba410a512279102851076eJacob Bramley } else { 637f8c2284645ce651f99ba410a512279102851076eJacob Bramley return 0x3fc; 638f8c2284645ce651f99ba410a512279102851076eJacob Bramley } 639f8c2284645ce651f99ba410a512279102851076eJacob Bramley default: 640f8c2284645ce651f99ba410a512279102851076eJacob Bramley VIXL_UNREACHABLE(); 641f8c2284645ce651f99ba410a512279102851076eJacob Bramley return 0; 642f8c2284645ce651f99ba410a512279102851076eJacob Bramley } 643f8c2284645ce651f99ba410a512279102851076eJacob Bramley} 644f8c2284645ce651f99ba410a512279102851076eJacob Bramley 645f8c2284645ce651f99ba410a512279102851076eJacob Bramley 64688c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisHARDFLOAT void PrintfTrampolineRRRR( 64788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const char* format, uint32_t a, uint32_t b, uint32_t c, uint32_t d) { 64888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois printf(format, a, b, c, d); 64988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 65088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 65188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 65288c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisHARDFLOAT void PrintfTrampolineRRRD( 65388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const char* format, uint32_t a, uint32_t b, uint32_t c, double d) { 65488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois printf(format, a, b, c, d); 65588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 65688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 65788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 65888c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisHARDFLOAT void PrintfTrampolineRRDR( 65988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const char* format, uint32_t a, uint32_t b, double c, uint32_t d) { 66088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois printf(format, a, b, c, d); 66188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 66288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 66388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 66488c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisHARDFLOAT void PrintfTrampolineRRDD( 66588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const char* format, uint32_t a, uint32_t b, double c, double d) { 66688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois printf(format, a, b, c, d); 66788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 66888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 66988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 67088c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisHARDFLOAT void PrintfTrampolineRDRR( 67188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const char* format, uint32_t a, double b, uint32_t c, uint32_t d) { 67288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois printf(format, a, b, c, d); 67388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 67488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 67588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 67688c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisHARDFLOAT void PrintfTrampolineRDRD( 67788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const char* format, uint32_t a, double b, uint32_t c, double d) { 67888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois printf(format, a, b, c, d); 67988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 68088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 68188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 68288c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisHARDFLOAT void PrintfTrampolineRDDR( 68388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const char* format, uint32_t a, double b, double c, uint32_t d) { 68488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois printf(format, a, b, c, d); 68588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 68688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 68788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 68888c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisHARDFLOAT void PrintfTrampolineRDDD( 68988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const char* format, uint32_t a, double b, double c, double d) { 69088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois printf(format, a, b, c, d); 69188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 69288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 69388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 69488c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisHARDFLOAT void PrintfTrampolineDRRR( 69588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const char* format, double a, uint32_t b, uint32_t c, uint32_t d) { 69688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois printf(format, a, b, c, d); 69788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 69888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 69988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 70088c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisHARDFLOAT void PrintfTrampolineDRRD( 70188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const char* format, double a, uint32_t b, uint32_t c, double d) { 70288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois printf(format, a, b, c, d); 70388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 70488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 70588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 70688c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisHARDFLOAT void PrintfTrampolineDRDR( 70788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const char* format, double a, uint32_t b, double c, uint32_t d) { 70888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois printf(format, a, b, c, d); 70988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 71088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 71188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 71288c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisHARDFLOAT void PrintfTrampolineDRDD( 71388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const char* format, double a, uint32_t b, double c, double d) { 71488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois printf(format, a, b, c, d); 71588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 71688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 71788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 71888c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisHARDFLOAT void PrintfTrampolineDDRR( 71988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const char* format, double a, double b, uint32_t c, uint32_t d) { 72088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois printf(format, a, b, c, d); 72188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 72288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 72388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 72488c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisHARDFLOAT void PrintfTrampolineDDRD( 72588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const char* format, double a, double b, uint32_t c, double d) { 72688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois printf(format, a, b, c, d); 72788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 72888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 72988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 73088c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisHARDFLOAT void PrintfTrampolineDDDR( 73188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const char* format, double a, double b, double c, uint32_t d) { 73288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois printf(format, a, b, c, d); 73388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 73488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 73588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 73688c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisHARDFLOAT void PrintfTrampolineDDDD( 73788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const char* format, double a, double b, double c, double d) { 73888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois printf(format, a, b, c, d); 73988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 74088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 74188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 74288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid MacroAssembler::Printf(const char* format, 74388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois CPURegister reg1, 74488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois CPURegister reg2, 74588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois CPURegister reg3, 74688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois CPURegister reg4) { 7474cb13e841305b38acbd8195b1c511d59c91ec8d9Georgia Kouveli // Exclude all registers from the available scratch registers, so 7484cb13e841305b38acbd8195b1c511d59c91ec8d9Georgia Kouveli // that we are able to use ip below. 7494cb13e841305b38acbd8195b1c511d59c91ec8d9Georgia Kouveli // TODO: Refactor this function to use UseScratchRegisterScope 7504cb13e841305b38acbd8195b1c511d59c91ec8d9Georgia Kouveli // for temporary registers below. 7514cb13e841305b38acbd8195b1c511d59c91ec8d9Georgia Kouveli UseScratchRegisterScope scratch(this); 7524cb13e841305b38acbd8195b1c511d59c91ec8d9Georgia Kouveli scratch.ExcludeAll(); 7531e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois if (generate_simulator_code_) { 7541e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois PushRegister(reg4); 7551e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois PushRegister(reg3); 7561e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois PushRegister(reg2); 7571e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois PushRegister(reg1); 7581e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Push(RegisterList(r0, r1)); 75925e3987b3b684df88edc8069d60b483b95587be5Pierre Langlois StringLiteral* format_literal = 76025e3987b3b684df88edc8069d60b483b95587be5Pierre Langlois new StringLiteral(format, RawLiteral::kDeletedOnPlacementByPool); 76125e3987b3b684df88edc8069d60b483b95587be5Pierre Langlois Adr(r0, format_literal); 7621e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois uint32_t args = (reg4.GetType() << 12) | (reg3.GetType() << 8) | 7631e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois (reg2.GetType() << 4) | reg1.GetType(); 7641e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Mov(r1, args); 7651e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Hvc(kPrintfCode); 7661e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Pop(RegisterList(r0, r1)); 7671e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois int size = reg4.GetRegSizeInBytes() + reg3.GetRegSizeInBytes() + 7681e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois reg2.GetRegSizeInBytes() + reg1.GetRegSizeInBytes(); 7691e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Drop(size); 77088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } else { 7711e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois // Generate on a native platform => 32 bit environment. 7721e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois // Preserve core registers r0-r3, r12, r14 7731e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois const uint32_t saved_registers_mask = 7741e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois kCallerSavedRegistersMask | (1 << r5.GetCode()); 7751e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Push(RegisterList(saved_registers_mask)); 7761e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois // Push VFP registers. 77771bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois Vpush(Untyped64, DRegisterList(d0, 8)); 77871bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois if (Has32DRegs()) Vpush(Untyped64, DRegisterList(d16, 16)); 7791e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois // Search one register which has been saved and which doesn't need to be 7801e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois // printed. 7811e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois RegisterList available_registers(kCallerSavedRegistersMask); 7821e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois if (reg1.GetType() == CPURegister::kRRegister) { 7831e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois available_registers.Remove(Register(reg1.GetCode())); 7841e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois } 7851e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois if (reg2.GetType() == CPURegister::kRRegister) { 7861e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois available_registers.Remove(Register(reg2.GetCode())); 7871e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois } 7881e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois if (reg3.GetType() == CPURegister::kRRegister) { 7891e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois available_registers.Remove(Register(reg3.GetCode())); 7901e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois } 7911e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois if (reg4.GetType() == CPURegister::kRRegister) { 7921e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois available_registers.Remove(Register(reg4.GetCode())); 7931e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois } 7941e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Register tmp = available_registers.GetFirstAvailableRegister(); 7951e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois VIXL_ASSERT(tmp.GetType() == CPURegister::kRRegister); 7961e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois // Push the flags. 7971e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Mrs(tmp, APSR); 7981e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Push(tmp); 7991e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Vmrs(RegisterOrAPSR_nzcv(tmp.GetCode()), FPSCR); 8001e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Push(tmp); 8011e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois // Push the registers to print on the stack. 8021e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois PushRegister(reg4); 8031e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois PushRegister(reg3); 8041e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois PushRegister(reg2); 8051e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois PushRegister(reg1); 8061e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois int core_count = 1; 8071e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois int vfp_count = 0; 8081e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois uint32_t printf_type = 0; 8091e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois // Pop the registers to print and store them into r1-r3 and/or d0-d3. 8101e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois // Reg4 may stay into the stack if all the register to print are core 8111e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois // registers. 8121e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois PreparePrintfArgument(reg1, &core_count, &vfp_count, &printf_type); 8131e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois PreparePrintfArgument(reg2, &core_count, &vfp_count, &printf_type); 8141e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois PreparePrintfArgument(reg3, &core_count, &vfp_count, &printf_type); 8151e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois PreparePrintfArgument(reg4, &core_count, &vfp_count, &printf_type); 8161e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois // Ensure that the stack is aligned on 8 bytes. 8171e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois And(r5, sp, 0x7); 8181e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois if (core_count == 5) { 8191e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois // One 32 bit argument (reg4) has been left on the stack => align the 8201e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois // stack 8211e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois // before the argument. 8221e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Pop(r0); 8231e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Sub(sp, sp, r5); 8241e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Push(r0); 8251e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois } else { 8261e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Sub(sp, sp, r5); 8271e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois } 8281e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois // Select the right trampoline depending on the arguments. 8291e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois uintptr_t address; 8301e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois switch (printf_type) { 8311e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois case 0: 8321e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois address = reinterpret_cast<uintptr_t>(PrintfTrampolineRRRR); 8331e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois break; 8341e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois case 1: 8351e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois address = reinterpret_cast<uintptr_t>(PrintfTrampolineDRRR); 8361e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois break; 8371e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois case 2: 8381e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois address = reinterpret_cast<uintptr_t>(PrintfTrampolineRDRR); 8391e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois break; 8401e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois case 3: 8411e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois address = reinterpret_cast<uintptr_t>(PrintfTrampolineDDRR); 8421e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois break; 8431e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois case 4: 8441e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois address = reinterpret_cast<uintptr_t>(PrintfTrampolineRRDR); 8451e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois break; 8461e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois case 5: 8471e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois address = reinterpret_cast<uintptr_t>(PrintfTrampolineDRDR); 8481e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois break; 8491e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois case 6: 8501e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois address = reinterpret_cast<uintptr_t>(PrintfTrampolineRDDR); 8511e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois break; 8521e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois case 7: 8531e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois address = reinterpret_cast<uintptr_t>(PrintfTrampolineDDDR); 8541e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois break; 8551e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois case 8: 8561e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois address = reinterpret_cast<uintptr_t>(PrintfTrampolineRRRD); 8571e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois break; 8581e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois case 9: 8591e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois address = reinterpret_cast<uintptr_t>(PrintfTrampolineDRRD); 8601e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois break; 8611e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois case 10: 8621e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois address = reinterpret_cast<uintptr_t>(PrintfTrampolineRDRD); 8631e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois break; 8641e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois case 11: 8651e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois address = reinterpret_cast<uintptr_t>(PrintfTrampolineDDRD); 8661e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois break; 8671e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois case 12: 8681e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois address = reinterpret_cast<uintptr_t>(PrintfTrampolineRRDD); 8691e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois break; 8701e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois case 13: 8711e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois address = reinterpret_cast<uintptr_t>(PrintfTrampolineDRDD); 8721e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois break; 8731e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois case 14: 8741e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois address = reinterpret_cast<uintptr_t>(PrintfTrampolineRDDD); 8751e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois break; 8761e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois case 15: 8771e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois address = reinterpret_cast<uintptr_t>(PrintfTrampolineDDDD); 8781e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois break; 8791e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois default: 8801e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois VIXL_UNREACHABLE(); 8811e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois address = reinterpret_cast<uintptr_t>(PrintfTrampolineRRRR); 8821e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois break; 8831e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois } 88425e3987b3b684df88edc8069d60b483b95587be5Pierre Langlois StringLiteral* format_literal = 88525e3987b3b684df88edc8069d60b483b95587be5Pierre Langlois new StringLiteral(format, RawLiteral::kDeletedOnPlacementByPool); 88625e3987b3b684df88edc8069d60b483b95587be5Pierre Langlois Adr(r0, format_literal); 887f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois Mov(ip, Operand::From(address)); 8881e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Blx(ip); 8891e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois // If register reg4 was left on the stack => skip it. 8901e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois if (core_count == 5) Drop(kRegSizeInBytes); 8911e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois // Restore the stack as it was before alignment. 8921e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Add(sp, sp, r5); 8931e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois // Restore the flags. 8941e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Pop(tmp); 8951e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Vmsr(FPSCR, tmp); 8961e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Pop(tmp); 8971e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Msr(APSR_nzcvqg, tmp); 8981e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois // Restore the regsisters. 89971bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois if (Has32DRegs()) Vpop(Untyped64, DRegisterList(d16, 16)); 90071bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois Vpop(Untyped64, DRegisterList(d0, 8)); 9011e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois Pop(RegisterList(saved_registers_mask)); 90288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 90388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 90488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 90588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 90688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid MacroAssembler::PushRegister(CPURegister reg) { 90788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois switch (reg.GetType()) { 90888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case CPURegister::kNoRegister: 90988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 91088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case CPURegister::kRRegister: 91188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Push(Register(reg.GetCode())); 91288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 91388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case CPURegister::kSRegister: 91488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Vpush(Untyped32, SRegisterList(SRegister(reg.GetCode()))); 91588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 91688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case CPURegister::kDRegister: 91788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Vpush(Untyped64, DRegisterList(DRegister(reg.GetCode()))); 91888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 91988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case CPURegister::kQRegister: 92088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_UNIMPLEMENTED(); 92188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 92288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 92388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 92488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 92588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 92688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid MacroAssembler::PreparePrintfArgument(CPURegister reg, 92788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois int* core_count, 92888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois int* vfp_count, 92988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois uint32_t* printf_type) { 93088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois switch (reg.GetType()) { 93188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case CPURegister::kNoRegister: 93288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 93388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case CPURegister::kRRegister: 93488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_ASSERT(*core_count <= 4); 93588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (*core_count < 4) Pop(Register(*core_count)); 93688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois *core_count += 1; 93788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 93888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case CPURegister::kSRegister: 93988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_ASSERT(*vfp_count < 4); 94088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois *printf_type |= 1 << (*core_count + *vfp_count - 1); 94188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Vpop(Untyped32, SRegisterList(SRegister(*vfp_count * 2))); 94288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Vcvt(F64, F32, DRegister(*vfp_count), SRegister(*vfp_count * 2)); 94388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois *vfp_count += 1; 94488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 94588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case CPURegister::kDRegister: 94688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_ASSERT(*vfp_count < 4); 94788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois *printf_type |= 1 << (*core_count + *vfp_count - 1); 94888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Vpop(Untyped64, DRegisterList(DRegister(*vfp_count))); 94988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois *vfp_count += 1; 95088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 95188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case CPURegister::kQRegister: 95288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_UNIMPLEMENTED(); 95388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 95488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 95588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 95688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 95788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 95888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid MacroAssembler::Delegate(InstructionType type, 95988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois InstructionCondROp instruction, 96088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Condition cond, 96188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register rn, 96288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const Operand& operand) { 9634634a88b6db240a13adc66f26ff3437806f08aecPierre Langlois VIXL_ASSERT((type == kMovt) || (type == kSxtb16) || (type == kTeq) || 9644634a88b6db240a13adc66f26ff3437806f08aecPierre Langlois (type == kUxtb16)); 96530aaad9e13111af88c55cbbba6dc31b06e1c8d5aPierre Langlois 96630aaad9e13111af88c55cbbba6dc31b06e1c8d5aPierre Langlois if (type == kMovt) { 967028fb0566f6af6d839d34ccfec754ba394510302Jacob Bramley VIXL_ABORT_WITH_MSG("`Movt` expects a 16-bit immediate.\n"); 96830aaad9e13111af88c55cbbba6dc31b06e1c8d5aPierre Langlois } 96930aaad9e13111af88c55cbbba6dc31b06e1c8d5aPierre Langlois 97030aaad9e13111af88c55cbbba6dc31b06e1c8d5aPierre Langlois // This delegate only supports teq with immediates. 97130aaad9e13111af88c55cbbba6dc31b06e1c8d5aPierre Langlois CONTEXT_SCOPE; 97230aaad9e13111af88c55cbbba6dc31b06e1c8d5aPierre Langlois if ((type == kTeq) && operand.IsImmediate()) { 97330aaad9e13111af88c55cbbba6dc31b06e1c8d5aPierre Langlois UseScratchRegisterScope temps(this); 97430aaad9e13111af88c55cbbba6dc31b06e1c8d5aPierre Langlois Register scratch = temps.Acquire(); 97530aaad9e13111af88c55cbbba6dc31b06e1c8d5aPierre Langlois HandleOutOfBoundsImmediate(cond, scratch, operand.GetImmediate()); 97630aaad9e13111af88c55cbbba6dc31b06e1c8d5aPierre Langlois CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 97730aaad9e13111af88c55cbbba6dc31b06e1c8d5aPierre Langlois teq(cond, rn, scratch); 97830aaad9e13111af88c55cbbba6dc31b06e1c8d5aPierre Langlois return; 97988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 98088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Assembler::Delegate(type, instruction, cond, rn, operand); 98188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 98288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 98388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 98488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid MacroAssembler::Delegate(InstructionType type, 98588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois InstructionCondSizeROp instruction, 98688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Condition cond, 98788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois EncodingSize size, 98888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register rn, 98988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const Operand& operand) { 99021d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell CONTEXT_SCOPE; 99188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_ASSERT(size.IsBest()); 99266170ac6e8c11239700e6031dc690cc2594c0675Georgia Kouveli VIXL_ASSERT((type == kCmn) || (type == kCmp) || (type == kMov) || 99366170ac6e8c11239700e6031dc690cc2594c0675Georgia Kouveli (type == kMovs) || (type == kMvn) || (type == kMvns) || 99466170ac6e8c11239700e6031dc690cc2594c0675Georgia Kouveli (type == kSxtb) || (type == kSxth) || (type == kTst) || 99566170ac6e8c11239700e6031dc690cc2594c0675Georgia Kouveli (type == kUxtb) || (type == kUxth)); 99610dae1a549308bddc1931f29754d6a4459f70c9bJacob Bramley if (IsUsingT32() && operand.IsRegisterShiftedRegister()) { 99766170ac6e8c11239700e6031dc690cc2594c0675Georgia Kouveli VIXL_ASSERT((type != kMov) || (type != kMovs)); 99888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois InstructionCondRROp shiftop = NULL; 99988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois switch (operand.GetShift().GetType()) { 100088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case LSL: 100188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois shiftop = &Assembler::lsl; 100288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 100388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case LSR: 100488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois shiftop = &Assembler::lsr; 100588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 100688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case ASR: 100788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois shiftop = &Assembler::asr; 100888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 100988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case RRX: 101066170ac6e8c11239700e6031dc690cc2594c0675Georgia Kouveli // A RegisterShiftedRegister operand cannot have a shift of type RRX. 101166170ac6e8c11239700e6031dc690cc2594c0675Georgia Kouveli VIXL_UNREACHABLE(); 101288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 101388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case ROR: 101488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois shiftop = &Assembler::ror; 101588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 101688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois default: 101788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_UNREACHABLE(); 101888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 101988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (shiftop != NULL) { 102088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois UseScratchRegisterScope temps(this); 102188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register scratch = temps.Acquire(); 1022aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, 2 * kMaxInstructionSizeInBytes); 102388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois (this->*shiftop)(cond, 102488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois scratch, 102588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois operand.GetBaseRegister(), 102688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois operand.GetShiftRegister()); 1027283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois (this->*instruction)(cond, size, rn, scratch); 1028283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 102988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 103088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 103188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (operand.IsImmediate()) { 103288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois uint32_t imm = operand.GetImmediate(); 103388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois switch (type) { 103488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case kMov: 103588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case kMovs: 103688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (!rn.IsPC()) { 103788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // Immediate is too large, but not using PC, so handle with mov{t}. 103888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois HandleOutOfBoundsImmediate(cond, rn, imm); 103988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (type == kMovs) { 1040aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 10418885c17bce593f82cf90c086da242e52943c50efVincent Belliard tst(cond, rn, rn); 104288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 104388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return; 1044c12d772a9c07b86010ec7e929716a95bda2aab25Vincent Belliard } else if (type == kMov) { 1045c12d772a9c07b86010ec7e929716a95bda2aab25Vincent Belliard VIXL_ASSERT(IsUsingA32() || cond.Is(al)); 104688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // Immediate is too large and using PC, so handle using a temporary 104788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // register. 104888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois UseScratchRegisterScope temps(this); 104988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register scratch = temps.Acquire(); 1050c12d772a9c07b86010ec7e929716a95bda2aab25Vincent Belliard HandleOutOfBoundsImmediate(al, scratch, imm); 1051aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley EnsureEmitFor(kMaxInstructionSizeInBytes); 1052283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois bx(cond, scratch); 1053283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 105488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 1055c12d772a9c07b86010ec7e929716a95bda2aab25Vincent Belliard break; 105688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case kCmn: 105788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case kCmp: 10582ec1f7562e90ebd295989c1323d59161a23dadfcMartyn Capewell if (IsUsingA32() || !rn.IsPC()) { 105988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois UseScratchRegisterScope temps(this); 106088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register scratch = temps.Acquire(); 106188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois HandleOutOfBoundsImmediate(cond, scratch, imm); 1062aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 1063283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois (this->*instruction)(cond, size, rn, scratch); 1064283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 106588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 106688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 106788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case kMvn: 106888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case kMvns: 1069c12d772a9c07b86010ec7e929716a95bda2aab25Vincent Belliard if (!rn.IsPC()) { 107088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois UseScratchRegisterScope temps(this); 107188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register scratch = temps.Acquire(); 107288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois HandleOutOfBoundsImmediate(cond, scratch, imm); 1073aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 1074283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois (this->*instruction)(cond, size, rn, scratch); 1075283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 107688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 107788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 10782ec1f7562e90ebd295989c1323d59161a23dadfcMartyn Capewell case kTst: 10792ec1f7562e90ebd295989c1323d59161a23dadfcMartyn Capewell if (IsUsingA32() || !rn.IsPC()) { 10802ec1f7562e90ebd295989c1323d59161a23dadfcMartyn Capewell UseScratchRegisterScope temps(this); 10812ec1f7562e90ebd295989c1323d59161a23dadfcMartyn Capewell Register scratch = temps.Acquire(); 10822ec1f7562e90ebd295989c1323d59161a23dadfcMartyn Capewell HandleOutOfBoundsImmediate(cond, scratch, imm); 10832ec1f7562e90ebd295989c1323d59161a23dadfcMartyn Capewell CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 1084283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois (this->*instruction)(cond, size, rn, scratch); 1085283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 10862ec1f7562e90ebd295989c1323d59161a23dadfcMartyn Capewell } 10872ec1f7562e90ebd295989c1323d59161a23dadfcMartyn Capewell break; 108888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois default: // kSxtb, Sxth, Uxtb, Uxth 108988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 109088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 109188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 109288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Assembler::Delegate(type, instruction, cond, size, rn, operand); 109388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 109488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 109588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 109688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid MacroAssembler::Delegate(InstructionType type, 109788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois InstructionCondRROp instruction, 109888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Condition cond, 109988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register rd, 110088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register rn, 110188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const Operand& operand) { 1102bf9f0ca0d76df354d17c181ef2121016859f299cPierre Langlois if ((type == kSxtab) || (type == kSxtab16) || (type == kSxtah) || 1103bf9f0ca0d76df354d17c181ef2121016859f299cPierre Langlois (type == kUxtab) || (type == kUxtab16) || (type == kUxtah) || 1104bf9f0ca0d76df354d17c181ef2121016859f299cPierre Langlois (type == kPkhbt) || (type == kPkhtb)) { 1105283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois UnimplementedDelegate(type); 1106283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 1107bf9f0ca0d76df354d17c181ef2121016859f299cPierre Langlois } 1108bf9f0ca0d76df354d17c181ef2121016859f299cPierre Langlois 1109bf9f0ca0d76df354d17c181ef2121016859f299cPierre Langlois // This delegate only handles the following instructions. 1110bf9f0ca0d76df354d17c181ef2121016859f299cPierre Langlois VIXL_ASSERT((type == kOrn) || (type == kOrns) || (type == kRsc) || 1111bf9f0ca0d76df354d17c181ef2121016859f299cPierre Langlois (type == kRscs)); 111221d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell CONTEXT_SCOPE; 1113d370ac5a89d8a5ce4f07326f5b04347465be2422Pierre Langlois 1114d370ac5a89d8a5ce4f07326f5b04347465be2422Pierre Langlois // T32 does not support register shifted register operands, emulate it. 111510dae1a549308bddc1931f29754d6a4459f70c9bJacob Bramley if (IsUsingT32() && operand.IsRegisterShiftedRegister()) { 111688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois InstructionCondRROp shiftop = NULL; 111788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois switch (operand.GetShift().GetType()) { 111888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case LSL: 111988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois shiftop = &Assembler::lsl; 112088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 112188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case LSR: 112288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois shiftop = &Assembler::lsr; 112388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 112488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case ASR: 112588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois shiftop = &Assembler::asr; 112688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 112788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case RRX: 1128bf9f0ca0d76df354d17c181ef2121016859f299cPierre Langlois // A RegisterShiftedRegister operand cannot have a shift of type RRX. 1129bf9f0ca0d76df354d17c181ef2121016859f299cPierre Langlois VIXL_UNREACHABLE(); 113088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 113188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case ROR: 113288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois shiftop = &Assembler::ror; 113388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 113488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois default: 113588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_UNREACHABLE(); 113688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 113788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (shiftop != NULL) { 113888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois UseScratchRegisterScope temps(this); 113988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register rm = operand.GetBaseRegister(); 114088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register rs = operand.GetShiftRegister(); 1141fd7f94dd378ec93adcc201d8eb9d71836948de09Vincent Belliard // Try to use rd as a scratch register. We can do this if it aliases rs or 1142fd7f94dd378ec93adcc201d8eb9d71836948de09Vincent Belliard // rm (because we read them in the first instruction), but not rn. 114388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (!rd.Is(rn)) temps.Include(rd); 114488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register scratch = temps.Acquire(); 1145aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley // TODO: The scope length was measured empirically. We should analyse the 1146aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley // worst-case size and add targetted tests. 1147aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, 3 * kMaxInstructionSizeInBytes); 114888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois (this->*shiftop)(cond, scratch, rm, rs); 1149283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois (this->*instruction)(cond, rd, rn, scratch); 1150283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 115188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 115288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 1153d370ac5a89d8a5ce4f07326f5b04347465be2422Pierre Langlois 1154d370ac5a89d8a5ce4f07326f5b04347465be2422Pierre Langlois // T32 does not have a Rsc instruction, negate the lhs input and turn it into 1155d370ac5a89d8a5ce4f07326f5b04347465be2422Pierre Langlois // an Adc. Adc and Rsc are equivalent using a bitwise NOT: 1156d370ac5a89d8a5ce4f07326f5b04347465be2422Pierre Langlois // adc rd, rn, operand <-> rsc rd, NOT(rn), operand 115710dae1a549308bddc1931f29754d6a4459f70c9bJacob Bramley if (IsUsingT32() && ((type == kRsc) || (type == kRscs))) { 115888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // The RegisterShiftRegister case should have been handled above. 115988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_ASSERT(!operand.IsRegisterShiftedRegister()); 116088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois UseScratchRegisterScope temps(this); 1161fd7f94dd378ec93adcc201d8eb9d71836948de09Vincent Belliard // Try to use rd as a scratch register. We can do this if it aliases rn 1162fd7f94dd378ec93adcc201d8eb9d71836948de09Vincent Belliard // (because we read it in the first instruction), but not rm. 1163fd7f94dd378ec93adcc201d8eb9d71836948de09Vincent Belliard temps.Include(rd); 1164fd7f94dd378ec93adcc201d8eb9d71836948de09Vincent Belliard temps.Exclude(operand); 1165fd7f94dd378ec93adcc201d8eb9d71836948de09Vincent Belliard Register negated_rn = temps.Acquire(); 1166aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 1167aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 1168aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley mvn(cond, negated_rn, rn); 1169aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 117088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (type == kRsc) { 1171aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 1172283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois adc(cond, rd, negated_rn, operand); 1173283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 117488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 1175bf9f0ca0d76df354d17c181ef2121016859f299cPierre Langlois // TODO: We shouldn't have to specify how much space the next instruction 1176bf9f0ca0d76df354d17c181ef2121016859f299cPierre Langlois // needs. 1177bf9f0ca0d76df354d17c181ef2121016859f299cPierre Langlois CodeBufferCheckScope scope(this, 3 * kMaxInstructionSizeInBytes); 1178283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois adcs(cond, rd, negated_rn, operand); 1179283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 118088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 1181d370ac5a89d8a5ce4f07326f5b04347465be2422Pierre Langlois 11825ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard if (operand.IsImmediate()) { 11835ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard // If the immediate can be encoded when inverted, turn Orn into Orr. 11845ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard // Otherwise rely on HandleOutOfBoundsImmediate to generate a series of 11855ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard // mov. 11865ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard int32_t imm = operand.GetSignedImmediate(); 11875ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard if (((type == kOrn) || (type == kOrns)) && IsModifiedImmediate(~imm)) { 11885ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 11895ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard switch (type) { 11905ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard case kOrn: 11915ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard orr(cond, rd, rn, ~imm); 11925ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard return; 11935ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard case kOrns: 11945ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard orrs(cond, rd, rn, ~imm); 11955ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard return; 11965ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard default: 11975ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard VIXL_UNREACHABLE(); 11985ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard break; 11995ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard } 12005ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard } 12015ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard } 12025ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard 1203d370ac5a89d8a5ce4f07326f5b04347465be2422Pierre Langlois // A32 does not have a Orn instruction, negate the rhs input and turn it into 1204d370ac5a89d8a5ce4f07326f5b04347465be2422Pierre Langlois // a Orr. 120510dae1a549308bddc1931f29754d6a4459f70c9bJacob Bramley if (IsUsingA32() && ((type == kOrn) || (type == kOrns))) { 120688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // TODO: orn r0, r1, imm -> orr r0, r1, neg(imm) if doable 120788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // mvn r0, r2 120888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // orr r0, r1, r0 120988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register scratch; 121088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois UseScratchRegisterScope temps(this); 1211fd7f94dd378ec93adcc201d8eb9d71836948de09Vincent Belliard // Try to use rd as a scratch register. We can do this if it aliases rs or 1212fd7f94dd378ec93adcc201d8eb9d71836948de09Vincent Belliard // rm (because we read them in the first instruction), but not rn. 121388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (!rd.Is(rn)) temps.Include(rd); 121488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois scratch = temps.Acquire(); 1215aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 1216bf9f0ca0d76df354d17c181ef2121016859f299cPierre Langlois // TODO: We shouldn't have to specify how much space the next instruction 1217bf9f0ca0d76df354d17c181ef2121016859f299cPierre Langlois // needs. 1218bf9f0ca0d76df354d17c181ef2121016859f299cPierre Langlois CodeBufferCheckScope scope(this, 3 * kMaxInstructionSizeInBytes); 1219aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley mvn(cond, scratch, operand); 1220aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 122188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (type == kOrns) { 1222aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 1223283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois orrs(cond, rd, rn, scratch); 1224283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 122588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 1226aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 1227283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois orr(cond, rd, rn, scratch); 1228283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 122988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 12305ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard 123188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (operand.IsImmediate()) { 12325ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard UseScratchRegisterScope temps(this); 12335ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard // Allow using the destination as a scratch register if possible. 12345ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard if (!rd.Is(rn)) temps.Include(rd); 12355ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard Register scratch = temps.Acquire(); 12362ec1f7562e90ebd295989c1323d59161a23dadfcMartyn Capewell int32_t imm = operand.GetSignedImmediate(); 12375ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard HandleOutOfBoundsImmediate(cond, scratch, imm); 12385ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 12395ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard (this->*instruction)(cond, rd, rn, scratch); 12405ddbc800588cde7e4d02f9fb7ca2f9e8c12522efVincent Belliard return; 124188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 124288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Assembler::Delegate(type, instruction, cond, rd, rn, operand); 124388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 124488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 124588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 124688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid MacroAssembler::Delegate(InstructionType type, 1247f8c2284645ce651f99ba410a512279102851076eJacob Bramley InstructionCondSizeRL instruction, 1248f8c2284645ce651f99ba410a512279102851076eJacob Bramley Condition cond, 1249f8c2284645ce651f99ba410a512279102851076eJacob Bramley EncodingSize size, 1250f8c2284645ce651f99ba410a512279102851076eJacob Bramley Register rd, 1251f8c2284645ce651f99ba410a512279102851076eJacob Bramley Label* label) { 1252f8c2284645ce651f99ba410a512279102851076eJacob Bramley VIXL_ASSERT((type == kLdr) || (type == kAdr)); 1253f8c2284645ce651f99ba410a512279102851076eJacob Bramley 1254f8c2284645ce651f99ba410a512279102851076eJacob Bramley CONTEXT_SCOPE; 1255f8c2284645ce651f99ba410a512279102851076eJacob Bramley VIXL_ASSERT(size.IsBest()); 1256f8c2284645ce651f99ba410a512279102851076eJacob Bramley 1257f8c2284645ce651f99ba410a512279102851076eJacob Bramley if ((type == kLdr) && label->IsBound()) { 125889d2f7702f0dc1751574bd5f9d35b5182fc65facJacob Bramley CodeBufferCheckScope scope(this, 5 * kMaxInstructionSizeInBytes); 1259f8c2284645ce651f99ba410a512279102851076eJacob Bramley UseScratchRegisterScope temps(this); 1260f8c2284645ce651f99ba410a512279102851076eJacob Bramley temps.Include(rd); 1261f8c2284645ce651f99ba410a512279102851076eJacob Bramley uint32_t mask = GetOffsetMask(type, Offset); 1262f8c2284645ce651f99ba410a512279102851076eJacob Bramley ldr(rd, MemOperandComputationHelper(cond, temps.Acquire(), label, mask)); 1263f8c2284645ce651f99ba410a512279102851076eJacob Bramley return; 1264f8c2284645ce651f99ba410a512279102851076eJacob Bramley } 1265f8c2284645ce651f99ba410a512279102851076eJacob Bramley 1266f8c2284645ce651f99ba410a512279102851076eJacob Bramley Assembler::Delegate(type, instruction, cond, size, rd, label); 1267f8c2284645ce651f99ba410a512279102851076eJacob Bramley} 1268f8c2284645ce651f99ba410a512279102851076eJacob Bramley 1269f8c2284645ce651f99ba410a512279102851076eJacob Bramley 127080b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliardbool MacroAssembler::GenerateSplitInstruction( 127180b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard InstructionCondSizeRROp instruction, 127280b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard Condition cond, 127380b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard Register rd, 127480b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard Register rn, 127580b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard uint32_t imm, 127680b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard uint32_t mask) { 127780b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard uint32_t high = imm & ~mask; 127880b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard if (!IsModifiedImmediate(high) && !rn.IsPC()) return false; 127980b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard // If high is a modified immediate, we can perform the operation with 128080b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard // only 2 instructions. 128180b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard // Else, if rn is PC, we want to avoid moving PC into a temporary. 128280b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard // Therefore, we also use the pattern even if the second call may 128380b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard // generate 3 instructions. 128480b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard uint32_t low = imm & mask; 128580b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard CodeBufferCheckScope scope(this, 128680b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard (rn.IsPC() ? 4 : 2) * kMaxInstructionSizeInBytes); 128780b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard (this->*instruction)(cond, Best, rd, rn, low); 128880b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard (this->*instruction)(cond, Best, rd, rd, high); 128980b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard return true; 129080b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard} 129180b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard 129280b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard 1293f8c2284645ce651f99ba410a512279102851076eJacob Bramleyvoid MacroAssembler::Delegate(InstructionType type, 129488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois InstructionCondSizeRROp instruction, 129588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Condition cond, 129688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois EncodingSize size, 129788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register rd, 129888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register rn, 129988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const Operand& operand) { 13002aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois VIXL_ASSERT( 13012aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois (type == kAdc) || (type == kAdcs) || (type == kAdd) || (type == kAdds) || 13022aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois (type == kAnd) || (type == kAnds) || (type == kAsr) || (type == kAsrs) || 13032aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois (type == kBic) || (type == kBics) || (type == kEor) || (type == kEors) || 13042aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois (type == kLsl) || (type == kLsls) || (type == kLsr) || (type == kLsrs) || 13052aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois (type == kOrr) || (type == kOrrs) || (type == kRor) || (type == kRors) || 13062aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois (type == kRsb) || (type == kRsbs) || (type == kSbc) || (type == kSbcs) || 13072aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois (type == kSub) || (type == kSubs)); 13082aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois 130921d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell CONTEXT_SCOPE; 131088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_ASSERT(size.IsBest()); 131110dae1a549308bddc1931f29754d6a4459f70c9bJacob Bramley if (IsUsingT32() && operand.IsRegisterShiftedRegister()) { 131288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois InstructionCondRROp shiftop = NULL; 131388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois switch (operand.GetShift().GetType()) { 131488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case LSL: 131588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois shiftop = &Assembler::lsl; 131688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 131788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case LSR: 131888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois shiftop = &Assembler::lsr; 131988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 132088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case ASR: 132188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois shiftop = &Assembler::asr; 132288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 132388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case RRX: 13242aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois // A RegisterShiftedRegister operand cannot have a shift of type RRX. 13252aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois VIXL_UNREACHABLE(); 132688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 132788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case ROR: 132888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois shiftop = &Assembler::ror; 132988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 133088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois default: 133188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_UNREACHABLE(); 133288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 133388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (shiftop != NULL) { 133488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois UseScratchRegisterScope temps(this); 133588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register rm = operand.GetBaseRegister(); 133688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register rs = operand.GetShiftRegister(); 1337fd7f94dd378ec93adcc201d8eb9d71836948de09Vincent Belliard // Try to use rd as a scratch register. We can do this if it aliases rs or 1338fd7f94dd378ec93adcc201d8eb9d71836948de09Vincent Belliard // rm (because we read them in the first instruction), but not rn. 133988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (!rd.Is(rn)) temps.Include(rd); 134088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register scratch = temps.Acquire(); 1341aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, 2 * kMaxInstructionSizeInBytes); 134288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois (this->*shiftop)(cond, scratch, rm, rs); 1343283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois (this->*instruction)(cond, size, rd, rn, scratch); 1344283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 134588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 134688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 134788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (operand.IsImmediate()) { 13482ec1f7562e90ebd295989c1323d59161a23dadfcMartyn Capewell int32_t imm = operand.GetSignedImmediate(); 1349e2aa8941a5b41fbd9f855906b8663009eac14669Vincent Belliard if (ImmediateT32::IsImmediateT32(~imm)) { 1350e2aa8941a5b41fbd9f855906b8663009eac14669Vincent Belliard if (IsUsingT32()) { 1351e2aa8941a5b41fbd9f855906b8663009eac14669Vincent Belliard switch (type) { 1352e2aa8941a5b41fbd9f855906b8663009eac14669Vincent Belliard case kOrr: 1353283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois orn(cond, rd, rn, ~imm); 1354283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 1355e2aa8941a5b41fbd9f855906b8663009eac14669Vincent Belliard case kOrrs: 1356283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois orns(cond, rd, rn, ~imm); 1357283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 1358e2aa8941a5b41fbd9f855906b8663009eac14669Vincent Belliard default: 1359e2aa8941a5b41fbd9f855906b8663009eac14669Vincent Belliard break; 1360e2aa8941a5b41fbd9f855906b8663009eac14669Vincent Belliard } 1361e2aa8941a5b41fbd9f855906b8663009eac14669Vincent Belliard } 1362e2aa8941a5b41fbd9f855906b8663009eac14669Vincent Belliard } 136388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (imm < 0) { 136488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois InstructionCondSizeRROp asmcb = NULL; 13652aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois // Add and sub are equivalent using an arithmetic negation: 13662aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois // add rd, rn, #imm <-> sub rd, rn, - #imm 13672aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois // Add and sub with carry are equivalent using a bitwise NOT: 13682aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois // adc rd, rn, #imm <-> sbc rd, rn, NOT #imm 136988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois switch (type) { 137088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case kAdd: 137188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois asmcb = &Assembler::sub; 137288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois imm = -imm; 137388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 137488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case kAdds: 137588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois asmcb = &Assembler::subs; 137688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois imm = -imm; 137788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 137888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case kSub: 137988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois asmcb = &Assembler::add; 138088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois imm = -imm; 138188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 13822aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois case kSubs: 13832aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois asmcb = &Assembler::adds; 13842aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois imm = -imm; 13852aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois break; 13862aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois case kAdc: 13872aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois asmcb = &Assembler::sbc; 13882aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois imm = ~imm; 13892aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois break; 13902aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois case kAdcs: 13912aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois asmcb = &Assembler::sbcs; 13922aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois imm = ~imm; 13932aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois break; 139488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case kSbc: 139588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois asmcb = &Assembler::adc; 139688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois imm = ~imm; 139788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 13982aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois case kSbcs: 13992aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois asmcb = &Assembler::adcs; 14002aa0afc4afb9409c97261e1dab9abc456a7551edPierre Langlois imm = ~imm; 140188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 140288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois default: 140388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 140488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 140588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (asmcb != NULL) { 14065c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley CodeBufferCheckScope scope(this, 4 * kMaxInstructionSizeInBytes); 1407283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois (this->*asmcb)(cond, size, rd, rn, Operand(imm)); 1408283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 140988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 141088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 141180b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard 141280b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard // When rn is PC, only handle negative offsets. The correct way to handle 141380b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard // positive offsets isn't clear; does the user want the offset from the 141480b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard // start of the macro, or from the end (to allow a certain amount of space)? 141580b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard // When type is Add or Sub, imm is always positive (imm < 0 has just been 141680b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard // handled and imm == 0 would have been generated without the need of a 141780b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard // delegate). Therefore, only add to PC is forbidden here. 141880b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard if ((((type == kAdd) && !rn.IsPC()) || (type == kSub)) && 141980b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard (IsUsingA32() || (!rd.IsPC() && !rn.IsPC()))) { 142080b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard VIXL_ASSERT(imm > 0); 142180b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard // Try to break the constant into two modified immediates. 142280b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard // For T32 also try to break the constant into one imm12 and one modified 142380b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard // immediate. Count the trailing zeroes and get the biggest even value. 142480b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard int trailing_zeroes = CountTrailingZeros(imm) & ~1u; 142580b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard uint32_t mask = ((trailing_zeroes < 4) && IsUsingT32()) 142680b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard ? 0xfff 142780b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard : (0xff << trailing_zeroes); 142880b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard if (GenerateSplitInstruction(instruction, cond, rd, rn, imm, mask)) { 142980b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard return; 143080b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard } 143180b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard InstructionCondSizeRROp asmcb = NULL; 143280b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard switch (type) { 143380b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard case kAdd: 143480b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard asmcb = &Assembler::sub; 143580b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard break; 143680b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard case kSub: 143780b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard asmcb = &Assembler::add; 143880b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard break; 143980b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard default: 144080b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard VIXL_UNREACHABLE(); 144180b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard } 144280b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard if (GenerateSplitInstruction(asmcb, cond, rd, rn, -imm, mask)) { 144380b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard return; 144480b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard } 144580b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard } 144680b4a1f554a92b2c4d4504265d0bac545c74c69bVincent Belliard 144788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois UseScratchRegisterScope temps(this); 144888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // Allow using the destination as a scratch register if possible. 144988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (!rd.Is(rn)) temps.Include(rd); 14505c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley if (rn.IsPC()) { 14515c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley // If we're reading the PC, we need to do it in the first instruction, 14525c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley // otherwise we'll read the wrong value. We rely on this to handle the 14535c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley // long-range PC-relative MemOperands which can result from user-managed 14545c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley // literals. 14555c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley 14565c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley // Only handle negative offsets. The correct way to handle positive 14575c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley // offsets isn't clear; does the user want the offset from the start of 14585c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley // the macro, or from the end (to allow a certain amount of space)? 14595c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley bool offset_is_negative_or_zero = (imm <= 0); 14605c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley switch (type) { 14615c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley case kAdd: 14625c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley case kAdds: 14635c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley offset_is_negative_or_zero = (imm <= 0); 14645c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley break; 14655c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley case kSub: 14665c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley case kSubs: 14675c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley offset_is_negative_or_zero = (imm >= 0); 14685c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley break; 14695c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley case kAdc: 14705c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley case kAdcs: 14715c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley offset_is_negative_or_zero = (imm < 0); 14725c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley break; 14735c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley case kSbc: 14745c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley case kSbcs: 14755c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley offset_is_negative_or_zero = (imm > 0); 14765c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley break; 14775c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley default: 14785c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley break; 14795c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley } 14805c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley if (offset_is_negative_or_zero) { 14815c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley { 14825c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley rn = temps.Acquire(); 14835c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 14845c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley mov(cond, rn, pc); 14855c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley } 14865c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley // Recurse rather than falling through, to try to get the immediate into 14875c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley // a single instruction. 14885c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley CodeBufferCheckScope scope(this, 3 * kMaxInstructionSizeInBytes); 14895c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley (this->*instruction)(cond, size, rd, rn, operand); 14905c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley return; 14915c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley } 14925c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley } else { 14935c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley Register scratch = temps.Acquire(); 14945c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley // TODO: The scope length was measured empirically. We should analyse the 14955c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley // worst-case size and add targetted tests. 14965c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley CodeBufferCheckScope scope(this, 3 * kMaxInstructionSizeInBytes); 14975c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley mov(cond, scratch, operand.GetImmediate()); 14985c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley (this->*instruction)(cond, size, rd, rn, scratch); 14995c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley return; 15005c76fb48ece5cc54c3000abead7e6147ac843834Jacob Bramley } 150188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 150288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Assembler::Delegate(type, instruction, cond, size, rd, rn, operand); 150388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 150488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 150588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 150688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid MacroAssembler::Delegate(InstructionType type, 150788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois InstructionRL instruction, 150888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register rn, 150988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Label* label) { 15105b698cc633932dee5dd94f44a42f0fdec567fe2bGeorgia Kouveli VIXL_ASSERT((type == kCbz) || (type == kCbnz)); 15115b698cc633932dee5dd94f44a42f0fdec567fe2bGeorgia Kouveli 151221d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell CONTEXT_SCOPE; 1513aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, 2 * kMaxInstructionSizeInBytes); 15145b698cc633932dee5dd94f44a42f0fdec567fe2bGeorgia Kouveli if (IsUsingA32()) { 15155b698cc633932dee5dd94f44a42f0fdec567fe2bGeorgia Kouveli if (type == kCbz) { 15165b698cc633932dee5dd94f44a42f0fdec567fe2bGeorgia Kouveli VIXL_ABORT_WITH_MSG("Cbz is only available for T32.\n"); 15175b698cc633932dee5dd94f44a42f0fdec567fe2bGeorgia Kouveli } else { 15185b698cc633932dee5dd94f44a42f0fdec567fe2bGeorgia Kouveli VIXL_ABORT_WITH_MSG("Cbnz is only available for T32.\n"); 15195b698cc633932dee5dd94f44a42f0fdec567fe2bGeorgia Kouveli } 15205b698cc633932dee5dd94f44a42f0fdec567fe2bGeorgia Kouveli } else if (rn.IsLow()) { 152188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois switch (type) { 152288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case kCbnz: { 152388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Label done; 15248885c17bce593f82cf90c086da242e52943c50efVincent Belliard cbz(rn, &done); 15258885c17bce593f82cf90c086da242e52943c50efVincent Belliard b(label); 152688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Bind(&done); 152788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return; 152888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 152988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case kCbz: { 153088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Label done; 15318885c17bce593f82cf90c086da242e52943c50efVincent Belliard cbnz(rn, &done); 15328885c17bce593f82cf90c086da242e52943c50efVincent Belliard b(label); 153388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Bind(&done); 153488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return; 153588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 153688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois default: 153788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 153888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 153988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 154088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Assembler::Delegate(type, instruction, rn, label); 154188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 154288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 154388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 154488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloistemplate <typename T> 154588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstatic inline bool IsI64BitPattern(T imm) { 154688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois for (T mask = 0xff << ((sizeof(T) - 1) * 8); mask != 0; mask >>= 8) { 154788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (((imm & mask) != mask) && ((imm & mask) != 0)) return false; 154888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 154988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return true; 155088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 155188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 155288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 155388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloistemplate <typename T> 155488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstatic inline bool IsI8BitPattern(T imm) { 155588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois uint8_t imm8 = imm & 0xff; 155688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois for (unsigned rep = sizeof(T) - 1; rep > 0; rep--) { 155788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois imm >>= 8; 155888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if ((imm & 0xff) != imm8) return false; 155988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 156088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return true; 156188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 156288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 156388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 156488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstatic inline bool CanBeInverted(uint32_t imm32) { 156588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois uint32_t fill8 = 0; 156688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 156788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if ((imm32 & 0xffffff00) == 0xffffff00) { 156888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // 11111111 11111111 11111111 abcdefgh 156988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return true; 157088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 157188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (((imm32 & 0xff) == 0) || ((imm32 & 0xff) == 0xff)) { 157288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois fill8 = imm32 & 0xff; 157388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois imm32 >>= 8; 157488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if ((imm32 >> 8) == 0xffff) { 157588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // 11111111 11111111 abcdefgh 00000000 157688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // or 11111111 11111111 abcdefgh 11111111 157788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return true; 157888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 157988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if ((imm32 & 0xff) == fill8) { 158088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois imm32 >>= 8; 158188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if ((imm32 >> 8) == 0xff) { 158288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // 11111111 abcdefgh 00000000 00000000 158388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // or 11111111 abcdefgh 11111111 11111111 158488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return true; 158588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 158688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if ((fill8 == 0xff) && ((imm32 & 0xff) == 0xff)) { 158788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // abcdefgh 11111111 11111111 11111111 158888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return true; 158988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 159088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 159188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 159288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return false; 159388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 159488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 159588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 159688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloistemplate <typename RES, typename T> 159788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstatic inline RES replicate(T imm) { 159888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_ASSERT((sizeof(RES) > sizeof(T)) && 159988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois (((sizeof(RES) / sizeof(T)) * sizeof(T)) == sizeof(RES))); 160088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois RES res = imm; 160188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois for (unsigned i = sizeof(RES) / sizeof(T) - 1; i > 0; i--) { 160288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois res = (res << (sizeof(T) * 8)) | imm; 160388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 160488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return res; 160588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 160688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 160788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 160888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid MacroAssembler::Delegate(InstructionType type, 160988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois InstructionCondDtSSop instruction, 161088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Condition cond, 161188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois DataType dt, 161288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois SRegister rd, 161388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const SOperand& operand) { 161421d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell CONTEXT_SCOPE; 161588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (type == kVmov) { 161688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (operand.IsImmediate() && dt.Is(F32)) { 161788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const NeonImmediate& neon_imm = operand.GetNeonImmediate(); 161888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (neon_imm.CanConvert<float>()) { 161988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // movw ip, imm16 162088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // movk ip, imm16 162188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vmov s0, ip 162288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois UseScratchRegisterScope temps(this); 162388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register scratch = temps.Acquire(); 162488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois float f = neon_imm.GetImmediate<float>(); 1625aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley // TODO: The scope length was measured empirically. We should analyse 1626aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley // the 1627aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley // worst-case size and add targetted tests. 1628aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, 3 * kMaxInstructionSizeInBytes); 16298885c17bce593f82cf90c086da242e52943c50efVincent Belliard mov(cond, scratch, FloatToRawbits(f)); 1630283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois vmov(cond, rd, scratch); 1631283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 163288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 163388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 163488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 163588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Assembler::Delegate(type, instruction, cond, dt, rd, operand); 163688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 163788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 163888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 163988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid MacroAssembler::Delegate(InstructionType type, 164088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois InstructionCondDtDDop instruction, 164188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Condition cond, 164288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois DataType dt, 164388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois DRegister rd, 164488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const DOperand& operand) { 164521d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell CONTEXT_SCOPE; 164688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (type == kVmov) { 164788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (operand.IsImmediate()) { 164888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const NeonImmediate& neon_imm = operand.GetNeonImmediate(); 164988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois switch (dt.GetValue()) { 165088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case I32: 165188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (neon_imm.CanConvert<uint32_t>()) { 165288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois uint32_t imm = neon_imm.GetImmediate<uint32_t>(); 165388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vmov.i32 d0, 0xabababab will translate into vmov.i8 d0, 0xab 165488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (IsI8BitPattern(imm)) { 1655aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 1656283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois vmov(cond, I8, rd, imm & 0xff); 1657283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 165888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 165988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vmov.i32 d0, 0xff0000ff will translate into 166088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vmov.i64 d0, 0xff0000ffff0000ff 166188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (IsI64BitPattern(imm)) { 1662aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 1663283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois vmov(cond, I64, rd, replicate<uint64_t>(imm)); 1664283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 166588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 166688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vmov.i32 d0, 0xffab0000 will translate into 166788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vmvn.i32 d0, 0x0054ffff 166888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (cond.Is(al) && CanBeInverted(imm)) { 1669aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 1670283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois vmvn(I32, rd, ~imm); 1671283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 167288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 167388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 167488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 167588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case I16: 167688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (neon_imm.CanConvert<uint16_t>()) { 167788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois uint16_t imm = neon_imm.GetImmediate<uint16_t>(); 167888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vmov.i16 d0, 0xabab will translate into vmov.i8 d0, 0xab 167988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (IsI8BitPattern(imm)) { 1680aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 1681283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois vmov(cond, I8, rd, imm & 0xff); 1682283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 168388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 168488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 168588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 168688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case I64: 168788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (neon_imm.CanConvert<uint64_t>()) { 168888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois uint64_t imm = neon_imm.GetImmediate<uint64_t>(); 168988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vmov.i64 d0, -1 will translate into vmov.i8 d0, 0xff 169088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (IsI8BitPattern(imm)) { 1691aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 1692283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois vmov(cond, I8, rd, imm & 0xff); 1693283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 169488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 169588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // mov ip, lo(imm64) 169688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vdup d0, ip 169788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vdup is prefered to 'vmov d0[0]' as d0[1] does not need to be 169888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // preserved 169988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois { 170088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois UseScratchRegisterScope temps(this); 170188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register scratch = temps.Acquire(); 1702aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 1703aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley // TODO: The scope length was measured empirically. We should 1704aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley // analyse the 1705aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley // worst-case size and add targetted tests. 1706aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, 1707aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley 2 * kMaxInstructionSizeInBytes); 1708aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley mov(cond, scratch, static_cast<uint32_t>(imm & 0xffffffff)); 1709aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 1710aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 17118885c17bce593f82cf90c086da242e52943c50efVincent Belliard vdup(cond, Untyped32, rd, scratch); 171288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 171388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // mov ip, hi(imm64) 171488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vmov d0[1], ip 171588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois { 171688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois UseScratchRegisterScope temps(this); 171788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register scratch = temps.Acquire(); 1718aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 1719aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley // TODO: The scope length was measured empirically. We should 1720aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley // analyse the 1721aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley // worst-case size and add targetted tests. 1722aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, 1723aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley 2 * kMaxInstructionSizeInBytes); 1724aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley mov(cond, scratch, static_cast<uint32_t>(imm >> 32)); 1725aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 1726aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 17278885c17bce593f82cf90c086da242e52943c50efVincent Belliard vmov(cond, Untyped32, DRegisterLane(rd, 1), scratch); 172888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 172988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return; 173088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 173188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 173288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois default: 173388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 173488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 1735960c80d57d7ec81ad517b9f5117434ca930f05c6Martyn Capewell VIXL_ASSERT(!dt.Is(I8)); // I8 cases should have been handled already. 1736960c80d57d7ec81ad517b9f5117434ca930f05c6Martyn Capewell if ((dt.Is(I16) || dt.Is(I32)) && neon_imm.CanConvert<uint32_t>()) { 173788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // mov ip, imm32 1738960c80d57d7ec81ad517b9f5117434ca930f05c6Martyn Capewell // vdup.16 d0, ip 173988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois UseScratchRegisterScope temps(this); 174088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register scratch = temps.Acquire(); 1741aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 1742960c80d57d7ec81ad517b9f5117434ca930f05c6Martyn Capewell CodeBufferCheckScope scope(this, 2 * kMaxInstructionSizeInBytes); 1743aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley mov(cond, scratch, neon_imm.GetImmediate<uint32_t>()); 1744aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 174588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois DataTypeValue vdup_dt = Untyped32; 174688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois switch (dt.GetValue()) { 174788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case I16: 174888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois vdup_dt = Untyped16; 174988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 175088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case I32: 175188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois vdup_dt = Untyped32; 175288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 175388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois default: 175488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_UNREACHABLE(); 175588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 1756aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 1757283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois vdup(cond, vdup_dt, rd, scratch); 1758283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 175988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 176088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (dt.Is(F32) && neon_imm.CanConvert<float>()) { 176188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois float f = neon_imm.GetImmediate<float>(); 176288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // Punt to vmov.i32 1763aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley // TODO: The scope length was guessed based on the double case below. We 1764aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley // should analyse the worst-case size and add targetted tests. 1765aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, 3 * kMaxInstructionSizeInBytes); 1766283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois vmov(cond, I32, rd, FloatToRawbits(f)); 1767283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 176888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 176988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (dt.Is(F64) && neon_imm.CanConvert<double>()) { 177088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // Punt to vmov.i64 177188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois double d = neon_imm.GetImmediate<double>(); 1772aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley // TODO: The scope length was measured empirically. We should analyse 1773aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley // the 1774aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley // worst-case size and add targetted tests. 1775aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, 6 * kMaxInstructionSizeInBytes); 1776283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois vmov(cond, I64, rd, DoubleToRawbits(d)); 1777283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 177888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 177988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 178088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 178188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Assembler::Delegate(type, instruction, cond, dt, rd, operand); 178288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 178388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 178488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 178588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid MacroAssembler::Delegate(InstructionType type, 178688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois InstructionCondDtQQop instruction, 178788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Condition cond, 178888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois DataType dt, 178988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois QRegister rd, 179088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const QOperand& operand) { 179121d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell CONTEXT_SCOPE; 179288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (type == kVmov) { 179388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (operand.IsImmediate()) { 179488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const NeonImmediate& neon_imm = operand.GetNeonImmediate(); 179588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois switch (dt.GetValue()) { 179688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case I32: 179788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (neon_imm.CanConvert<uint32_t>()) { 179888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois uint32_t imm = neon_imm.GetImmediate<uint32_t>(); 179988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vmov.i32 d0, 0xabababab will translate into vmov.i8 d0, 0xab 180088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (IsI8BitPattern(imm)) { 1801aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 1802283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois vmov(cond, I8, rd, imm & 0xff); 1803283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 180488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 180588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vmov.i32 d0, 0xff0000ff will translate into 180688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vmov.i64 d0, 0xff0000ffff0000ff 180788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (IsI64BitPattern(imm)) { 1808aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 1809283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois vmov(cond, I64, rd, replicate<uint64_t>(imm)); 1810283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 181188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 181288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vmov.i32 d0, 0xffab0000 will translate into 181388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vmvn.i32 d0, 0x0054ffff 181488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (CanBeInverted(imm)) { 1815aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 1816283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois vmvn(cond, I32, rd, ~imm); 1817283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 181888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 181988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 182088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 182188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case I16: 182288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (neon_imm.CanConvert<uint16_t>()) { 182388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois uint16_t imm = neon_imm.GetImmediate<uint16_t>(); 182488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vmov.i16 d0, 0xabab will translate into vmov.i8 d0, 0xab 182588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (IsI8BitPattern(imm)) { 1826aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 1827283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois vmov(cond, I8, rd, imm & 0xff); 1828283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 182988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 183088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 183188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 183288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case I64: 183388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (neon_imm.CanConvert<uint64_t>()) { 183488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois uint64_t imm = neon_imm.GetImmediate<uint64_t>(); 183588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vmov.i64 d0, -1 will translate into vmov.i8 d0, 0xff 183688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (IsI8BitPattern(imm)) { 1837aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 1838283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois vmov(cond, I8, rd, imm & 0xff); 1839283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 184088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 184188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // mov ip, lo(imm64) 184288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vdup q0, ip 184388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vdup is prefered to 'vmov d0[0]' as d0[1-3] don't need to be 184488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // preserved 184588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois { 184688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois UseScratchRegisterScope temps(this); 184788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register scratch = temps.Acquire(); 1848aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 1849960c80d57d7ec81ad517b9f5117434ca930f05c6Martyn Capewell CodeBufferCheckScope scope(this, 1850960c80d57d7ec81ad517b9f5117434ca930f05c6Martyn Capewell 2 * kMaxInstructionSizeInBytes); 1851aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley mov(cond, scratch, static_cast<uint32_t>(imm & 0xffffffff)); 1852aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 1853aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 18548885c17bce593f82cf90c086da242e52943c50efVincent Belliard vdup(cond, Untyped32, rd, scratch); 185588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 185688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // mov ip, hi(imm64) 185788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vmov.i32 d0[1], ip 185888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vmov d1, d0 185988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois { 186088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois UseScratchRegisterScope temps(this); 186188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register scratch = temps.Acquire(); 1862aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 1863960c80d57d7ec81ad517b9f5117434ca930f05c6Martyn Capewell CodeBufferCheckScope scope(this, 1864960c80d57d7ec81ad517b9f5117434ca930f05c6Martyn Capewell 2 * kMaxInstructionSizeInBytes); 1865aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley mov(cond, scratch, static_cast<uint32_t>(imm >> 32)); 1866aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 1867aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 1868aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 1869aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley vmov(cond, 1870aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley Untyped32, 1871aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley DRegisterLane(rd.GetLowDRegister(), 1), 1872aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley scratch); 1873aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 1874aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 18758885c17bce593f82cf90c086da242e52943c50efVincent Belliard vmov(cond, F64, rd.GetHighDRegister(), rd.GetLowDRegister()); 187688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 187788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return; 187888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 187988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 188088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois default: 188188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 188288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 1883960c80d57d7ec81ad517b9f5117434ca930f05c6Martyn Capewell VIXL_ASSERT(!dt.Is(I8)); // I8 cases should have been handled already. 1884960c80d57d7ec81ad517b9f5117434ca930f05c6Martyn Capewell if ((dt.Is(I16) || dt.Is(I32)) && neon_imm.CanConvert<uint32_t>()) { 188588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // mov ip, imm32 1886960c80d57d7ec81ad517b9f5117434ca930f05c6Martyn Capewell // vdup.16 d0, ip 188788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois UseScratchRegisterScope temps(this); 188888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register scratch = temps.Acquire(); 1889aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 1890960c80d57d7ec81ad517b9f5117434ca930f05c6Martyn Capewell CodeBufferCheckScope scope(this, 2 * kMaxInstructionSizeInBytes); 1891aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley mov(cond, scratch, neon_imm.GetImmediate<uint32_t>()); 1892aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 189388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois DataTypeValue vdup_dt = Untyped32; 189488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois switch (dt.GetValue()) { 189588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case I16: 189688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois vdup_dt = Untyped16; 189788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 189888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case I32: 189988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois vdup_dt = Untyped32; 190088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 190188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois default: 190288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_UNREACHABLE(); 190388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 1904aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 1905283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois vdup(cond, vdup_dt, rd, scratch); 1906283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 190788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 190888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (dt.Is(F32) && neon_imm.CanConvert<float>()) { 190988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // Punt to vmov.i64 191088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois float f = neon_imm.GetImmediate<float>(); 1911960c80d57d7ec81ad517b9f5117434ca930f05c6Martyn Capewell CodeBufferCheckScope scope(this, 3 * kMaxInstructionSizeInBytes); 1912283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois vmov(cond, I32, rd, FloatToRawbits(f)); 1913283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 191488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 191588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (dt.Is(F64) && neon_imm.CanConvert<double>()) { 1916960c80d57d7ec81ad517b9f5117434ca930f05c6Martyn Capewell // Use vmov to create the double in the low D register, then duplicate 1917960c80d57d7ec81ad517b9f5117434ca930f05c6Martyn Capewell // it into the high D register. 191888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois double d = neon_imm.GetImmediate<double>(); 1919960c80d57d7ec81ad517b9f5117434ca930f05c6Martyn Capewell CodeBufferCheckScope scope(this, 7 * kMaxInstructionSizeInBytes); 1920960c80d57d7ec81ad517b9f5117434ca930f05c6Martyn Capewell vmov(cond, F64, rd.GetLowDRegister(), d); 1921960c80d57d7ec81ad517b9f5117434ca930f05c6Martyn Capewell vmov(cond, F64, rd.GetHighDRegister(), rd.GetLowDRegister()); 1922283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 192388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 192488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 192588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 192688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Assembler::Delegate(type, instruction, cond, dt, rd, operand); 192788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 192888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 192988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 193088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid MacroAssembler::Delegate(InstructionType type, 1931f8c2284645ce651f99ba410a512279102851076eJacob Bramley InstructionCondRL instruction, 1932f8c2284645ce651f99ba410a512279102851076eJacob Bramley Condition cond, 1933f8c2284645ce651f99ba410a512279102851076eJacob Bramley Register rt, 1934f8c2284645ce651f99ba410a512279102851076eJacob Bramley Label* label) { 1935f8c2284645ce651f99ba410a512279102851076eJacob Bramley VIXL_ASSERT((type == kLdrb) || (type == kLdrh) || (type == kLdrsb) || 1936f8c2284645ce651f99ba410a512279102851076eJacob Bramley (type == kLdrsh)); 1937f8c2284645ce651f99ba410a512279102851076eJacob Bramley 1938f8c2284645ce651f99ba410a512279102851076eJacob Bramley CONTEXT_SCOPE; 1939f8c2284645ce651f99ba410a512279102851076eJacob Bramley 1940f8c2284645ce651f99ba410a512279102851076eJacob Bramley if (label->IsBound()) { 194189d2f7702f0dc1751574bd5f9d35b5182fc65facJacob Bramley CodeBufferCheckScope scope(this, 5 * kMaxInstructionSizeInBytes); 1942f8c2284645ce651f99ba410a512279102851076eJacob Bramley UseScratchRegisterScope temps(this); 1943f8c2284645ce651f99ba410a512279102851076eJacob Bramley temps.Include(rt); 1944f8c2284645ce651f99ba410a512279102851076eJacob Bramley Register scratch = temps.Acquire(); 1945f8c2284645ce651f99ba410a512279102851076eJacob Bramley uint32_t mask = GetOffsetMask(type, Offset); 1946f8c2284645ce651f99ba410a512279102851076eJacob Bramley switch (type) { 1947f8c2284645ce651f99ba410a512279102851076eJacob Bramley case kLdrb: 1948f8c2284645ce651f99ba410a512279102851076eJacob Bramley ldrb(rt, MemOperandComputationHelper(cond, scratch, label, mask)); 1949f8c2284645ce651f99ba410a512279102851076eJacob Bramley return; 1950f8c2284645ce651f99ba410a512279102851076eJacob Bramley case kLdrh: 1951f8c2284645ce651f99ba410a512279102851076eJacob Bramley ldrh(rt, MemOperandComputationHelper(cond, scratch, label, mask)); 1952f8c2284645ce651f99ba410a512279102851076eJacob Bramley return; 1953f8c2284645ce651f99ba410a512279102851076eJacob Bramley case kLdrsb: 1954f8c2284645ce651f99ba410a512279102851076eJacob Bramley ldrsb(rt, MemOperandComputationHelper(cond, scratch, label, mask)); 1955f8c2284645ce651f99ba410a512279102851076eJacob Bramley return; 1956f8c2284645ce651f99ba410a512279102851076eJacob Bramley case kLdrsh: 1957f8c2284645ce651f99ba410a512279102851076eJacob Bramley ldrsh(rt, MemOperandComputationHelper(cond, scratch, label, mask)); 1958f8c2284645ce651f99ba410a512279102851076eJacob Bramley return; 1959f8c2284645ce651f99ba410a512279102851076eJacob Bramley default: 1960f8c2284645ce651f99ba410a512279102851076eJacob Bramley VIXL_UNREACHABLE(); 1961f8c2284645ce651f99ba410a512279102851076eJacob Bramley } 1962f8c2284645ce651f99ba410a512279102851076eJacob Bramley return; 1963f8c2284645ce651f99ba410a512279102851076eJacob Bramley } 1964f8c2284645ce651f99ba410a512279102851076eJacob Bramley 1965f8c2284645ce651f99ba410a512279102851076eJacob Bramley Assembler::Delegate(type, instruction, cond, rt, label); 1966f8c2284645ce651f99ba410a512279102851076eJacob Bramley} 1967f8c2284645ce651f99ba410a512279102851076eJacob Bramley 1968f8c2284645ce651f99ba410a512279102851076eJacob Bramley 1969f8c2284645ce651f99ba410a512279102851076eJacob Bramleyvoid MacroAssembler::Delegate(InstructionType type, 1970f8c2284645ce651f99ba410a512279102851076eJacob Bramley InstructionCondRRL instruction, 1971f8c2284645ce651f99ba410a512279102851076eJacob Bramley Condition cond, 1972f8c2284645ce651f99ba410a512279102851076eJacob Bramley Register rt, 1973f8c2284645ce651f99ba410a512279102851076eJacob Bramley Register rt2, 1974f8c2284645ce651f99ba410a512279102851076eJacob Bramley Label* label) { 1975f8c2284645ce651f99ba410a512279102851076eJacob Bramley VIXL_ASSERT(type == kLdrd); 1976f8c2284645ce651f99ba410a512279102851076eJacob Bramley 1977f8c2284645ce651f99ba410a512279102851076eJacob Bramley CONTEXT_SCOPE; 1978f8c2284645ce651f99ba410a512279102851076eJacob Bramley 1979f8c2284645ce651f99ba410a512279102851076eJacob Bramley if (label->IsBound()) { 198089d2f7702f0dc1751574bd5f9d35b5182fc65facJacob Bramley CodeBufferCheckScope scope(this, 6 * kMaxInstructionSizeInBytes); 1981f8c2284645ce651f99ba410a512279102851076eJacob Bramley UseScratchRegisterScope temps(this); 1982f8c2284645ce651f99ba410a512279102851076eJacob Bramley temps.Include(rt, rt2); 1983f8c2284645ce651f99ba410a512279102851076eJacob Bramley Register scratch = temps.Acquire(); 1984f8c2284645ce651f99ba410a512279102851076eJacob Bramley uint32_t mask = GetOffsetMask(type, Offset); 1985f8c2284645ce651f99ba410a512279102851076eJacob Bramley ldrd(rt, rt2, MemOperandComputationHelper(cond, scratch, label, mask)); 1986f8c2284645ce651f99ba410a512279102851076eJacob Bramley return; 1987f8c2284645ce651f99ba410a512279102851076eJacob Bramley } 1988f8c2284645ce651f99ba410a512279102851076eJacob Bramley 1989f8c2284645ce651f99ba410a512279102851076eJacob Bramley Assembler::Delegate(type, instruction, cond, rt, rt2, label); 1990f8c2284645ce651f99ba410a512279102851076eJacob Bramley} 1991f8c2284645ce651f99ba410a512279102851076eJacob Bramley 1992f8c2284645ce651f99ba410a512279102851076eJacob Bramley 1993f8c2284645ce651f99ba410a512279102851076eJacob Bramleyvoid MacroAssembler::Delegate(InstructionType type, 199488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois InstructionCondSizeRMop instruction, 199588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Condition cond, 199688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois EncodingSize size, 199788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register rd, 199888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const MemOperand& operand) { 199921d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell CONTEXT_SCOPE; 200088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_ASSERT(size.IsBest()); 2001fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli VIXL_ASSERT((type == kLdr) || (type == kLdrb) || (type == kLdrh) || 2002fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli (type == kLdrsb) || (type == kLdrsh) || (type == kStr) || 2003fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli (type == kStrb) || (type == kStrh)); 200488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (operand.IsImmediate()) { 200588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const Register& rn = operand.GetBaseRegister(); 200688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois AddrMode addrmode = operand.GetAddrMode(); 200788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois int32_t offset = operand.GetOffsetImmediate(); 2008b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard uint32_t extra_offset_mask = GetOffsetMask(type, addrmode); 2009b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard // Try to maximize the offset used by the MemOperand (load_store_offset). 2010b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard // Add the part which can't be used by the MemOperand (add_offset). 2011b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard uint32_t load_store_offset = offset & extra_offset_mask; 2012b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard uint32_t add_offset = offset & ~extra_offset_mask; 2013b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard if ((add_offset != 0) && 2014b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard (IsModifiedImmediate(offset) || IsModifiedImmediate(-offset))) { 2015b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard load_store_offset = 0; 2016b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard add_offset = offset; 2017fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli } 2018fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli switch (addrmode) { 2019fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli case PreIndex: 2020fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // Avoid the unpredictable case 'str r0, [r0, imm]!' 2021fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli if (!rn.Is(rd)) { 2022a5372b10e91d4ecaddedc9c4aec2d61bf952a2caVincent Belliard // Pre-Indexed case: 2023a5372b10e91d4ecaddedc9c4aec2d61bf952a2caVincent Belliard // ldr r0, [r1, 12345]! will translate into 2024a5372b10e91d4ecaddedc9c4aec2d61bf952a2caVincent Belliard // add r1, r1, 12345 202588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // ldr r0, [r1] 2026aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 2027a5372b10e91d4ecaddedc9c4aec2d61bf952a2caVincent Belliard CodeBufferCheckScope scope(this, 3 * kMaxInstructionSizeInBytes); 2028b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard add(cond, rn, rn, add_offset); 2029aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 2030aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 2031aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 2032a5372b10e91d4ecaddedc9c4aec2d61bf952a2caVincent Belliard (this->*instruction)(cond, 2033a5372b10e91d4ecaddedc9c4aec2d61bf952a2caVincent Belliard size, 2034a5372b10e91d4ecaddedc9c4aec2d61bf952a2caVincent Belliard rd, 2035a5372b10e91d4ecaddedc9c4aec2d61bf952a2caVincent Belliard MemOperand(rn, load_store_offset, PreIndex)); 2036a5372b10e91d4ecaddedc9c4aec2d61bf952a2caVincent Belliard } 2037a5372b10e91d4ecaddedc9c4aec2d61bf952a2caVincent Belliard return; 2038fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli } 2039fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli break; 2040fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli case Offset: { 2041fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli UseScratchRegisterScope temps(this); 2042fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // Allow using the destination as a scratch register if possible. 2043fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli if ((type != kStr) && (type != kStrb) && (type != kStrh) && 2044fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli !rd.Is(rn)) { 2045fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli temps.Include(rd); 2046fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli } 2047fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli Register scratch = temps.Acquire(); 2048fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // Offset case: 2049fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // ldr r0, [r1, 12345] will translate into 2050fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // add r0, r1, 12345 2051fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // ldr r0, [r0] 2052fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli { 2053fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli CodeBufferCheckScope scope(this, 3 * kMaxInstructionSizeInBytes); 2054b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard add(cond, scratch, rn, add_offset); 2055fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli } 2056fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli { 2057fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 2058fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli (this->*instruction)(cond, 2059fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli size, 2060fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli rd, 2061fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli MemOperand(scratch, load_store_offset)); 2062fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli } 2063fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli return; 2064fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli } 2065fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli case PostIndex: 2066fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // Avoid the unpredictable case 'ldr r0, [r0], imm' 2067fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli if (!rn.Is(rd)) { 2068fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // Post-indexed case: 2069fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // ldr r0. [r1], imm32 will translate into 2070fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // ldr r0, [r1] 2071fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // movw ip. imm32 & 0xffffffff 2072fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // movt ip, imm32 >> 16 2073fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // add r1, r1, ip 2074a5372b10e91d4ecaddedc9c4aec2d61bf952a2caVincent Belliard { 2075a5372b10e91d4ecaddedc9c4aec2d61bf952a2caVincent Belliard CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 2076a5372b10e91d4ecaddedc9c4aec2d61bf952a2caVincent Belliard (this->*instruction)(cond, 2077a5372b10e91d4ecaddedc9c4aec2d61bf952a2caVincent Belliard size, 2078a5372b10e91d4ecaddedc9c4aec2d61bf952a2caVincent Belliard rd, 2079fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli MemOperand(rn, load_store_offset, PostIndex)); 2080a5372b10e91d4ecaddedc9c4aec2d61bf952a2caVincent Belliard } 2081fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli { 2082fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli CodeBufferCheckScope scope(this, 3 * kMaxInstructionSizeInBytes); 2083b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard add(cond, rn, rn, add_offset); 2084a5372b10e91d4ecaddedc9c4aec2d61bf952a2caVincent Belliard } 2085fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli return; 2086fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli } 2087fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli break; 208888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 2089fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli } else if (operand.IsPlainRegister()) { 209088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const Register& rn = operand.GetBaseRegister(); 209188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois AddrMode addrmode = operand.GetAddrMode(); 209288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const Register& rm = operand.GetOffsetRegister(); 2093fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli if (rm.IsPC()) { 2094fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli VIXL_ABORT_WITH_MSG( 2095fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli "The MacroAssembler does not convert loads and stores with a PC " 2096fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli "offset register.\n"); 2097fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli } 2098d17e348e16bf0d6eca4f9ea0e935c7544098d045Vincent Belliard if (rn.IsPC()) { 2099d17e348e16bf0d6eca4f9ea0e935c7544098d045Vincent Belliard if (addrmode == Offset) { 2100d17e348e16bf0d6eca4f9ea0e935c7544098d045Vincent Belliard if (IsUsingT32()) { 2101d17e348e16bf0d6eca4f9ea0e935c7544098d045Vincent Belliard VIXL_ABORT_WITH_MSG( 2102d17e348e16bf0d6eca4f9ea0e935c7544098d045Vincent Belliard "The MacroAssembler does not convert loads and stores with a PC " 2103d17e348e16bf0d6eca4f9ea0e935c7544098d045Vincent Belliard "base register for T32.\n"); 2104d17e348e16bf0d6eca4f9ea0e935c7544098d045Vincent Belliard } 2105d17e348e16bf0d6eca4f9ea0e935c7544098d045Vincent Belliard } else { 2106d17e348e16bf0d6eca4f9ea0e935c7544098d045Vincent Belliard VIXL_ABORT_WITH_MSG( 2107d17e348e16bf0d6eca4f9ea0e935c7544098d045Vincent Belliard "The MacroAssembler does not convert loads and stores with a PC " 2108d17e348e16bf0d6eca4f9ea0e935c7544098d045Vincent Belliard "base register in pre-index or post-index mode.\n"); 2109d17e348e16bf0d6eca4f9ea0e935c7544098d045Vincent Belliard } 2110fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli } 211188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois switch (addrmode) { 211288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case PreIndex: 2113fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // Avoid the unpredictable case 'str r0, [r0, imm]!' 2114fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli if (!rn.Is(rd)) { 2115fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // Pre-Indexed case: 2116fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // ldr r0, [r1, r2]! will translate into 2117fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // add r1, r1, r2 2118fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // ldr r0, [r1] 2119fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli { 2120fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 2121fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli if (operand.GetSign().IsPlus()) { 2122fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli add(cond, rn, rn, rm); 2123fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli } else { 2124fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli sub(cond, rn, rn, rm); 2125fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli } 2126aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 2127fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli { 2128fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 2129fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli (this->*instruction)(cond, size, rd, MemOperand(rn, Offset)); 2130fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli } 2131fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli return; 2132aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 2133fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli break; 213488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case Offset: { 213588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois UseScratchRegisterScope temps(this); 2136fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // Allow using the destination as a scratch register if this is not a 2137fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // store. 2138fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli // Avoid using PC as a temporary as this has side-effects. 213988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if ((type != kStr) && (type != kStrb) && (type != kStrh) && 2140fad927c4321a9dd7e235b91aadd88f5542561370Georgia Kouveli !rd.IsPC()) { 214188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois temps.Include(rd); 214288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 214388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register scratch = temps.Acquire(); 214488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // Offset case: 214588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // ldr r0, [r1, r2] will translate into 214688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // add r0, r1, r2 214788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // ldr r0, [r0] 2148aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 2149aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 2150aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley if (operand.GetSign().IsPlus()) { 2151aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley add(cond, scratch, rn, rm); 2152aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } else { 2153aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley sub(cond, scratch, rn, rm); 2154aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 2155aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 2156aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 2157aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 2158aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley (this->*instruction)(cond, size, rd, MemOperand(scratch, Offset)); 215988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 216088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return; 216188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 216288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case PostIndex: 216388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // Avoid the unpredictable case 'ldr r0, [r0], imm' 216488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (!rn.Is(rd)) { 216588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // Post-indexed case: 216688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // ldr r0. [r1], r2 will translate into 216788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // ldr r0, [r1] 216888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // add r1, r1, r2 2169aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 2170aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 2171aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley (this->*instruction)(cond, size, rd, MemOperand(rn, Offset)); 2172aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 2173aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 2174aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 2175aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley if (operand.GetSign().IsPlus()) { 2176aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley add(cond, rn, rn, rm); 2177aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } else { 2178aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley sub(cond, rn, rn, rm); 2179aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 218088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 218188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return; 218288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 218388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois break; 218488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 218588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 218688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Assembler::Delegate(type, instruction, cond, size, rd, operand); 218788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 218888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 218988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 219088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid MacroAssembler::Delegate(InstructionType type, 219188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois InstructionCondRRMop instruction, 219288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Condition cond, 219388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register rt, 219488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register rt2, 219588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const MemOperand& operand) { 2196b44f7a6ee7f9cd194cde9577f5a941f2864795a4Pierre Langlois if ((type == kLdaexd) || (type == kLdrexd) || (type == kStlex) || 2197b44f7a6ee7f9cd194cde9577f5a941f2864795a4Pierre Langlois (type == kStlexb) || (type == kStlexh) || (type == kStrex) || 2198b44f7a6ee7f9cd194cde9577f5a941f2864795a4Pierre Langlois (type == kStrexb) || (type == kStrexh)) { 2199283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois UnimplementedDelegate(type); 2200283bbdf1908649c90069ff80dfca45de4f675de4Pierre Langlois return; 2201b44f7a6ee7f9cd194cde9577f5a941f2864795a4Pierre Langlois } 2202b44f7a6ee7f9cd194cde9577f5a941f2864795a4Pierre Langlois 2203b44f7a6ee7f9cd194cde9577f5a941f2864795a4Pierre Langlois VIXL_ASSERT((type == kLdrd) || (type == kStrd)); 2204b44f7a6ee7f9cd194cde9577f5a941f2864795a4Pierre Langlois 220521d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell CONTEXT_SCOPE; 220688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 22077f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // TODO: Should we allow these cases? 2208b44f7a6ee7f9cd194cde9577f5a941f2864795a4Pierre Langlois if (IsUsingA32()) { 22097f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // The first register needs to be even. 22107f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois if ((rt.GetCode() & 1) != 0) { 22117f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois UnimplementedDelegate(type); 22127f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois return; 22137f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } 22147f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // Registers need to be adjacent. 22157f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois if (((rt.GetCode() + 1) % kNumberOfRegisters) != rt2.GetCode()) { 22167f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois UnimplementedDelegate(type); 22177f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois return; 22187f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } 22197f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // LDRD lr, pc [...] is not allowed. 22207f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois if (rt.Is(lr)) { 22217f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois UnimplementedDelegate(type); 22227f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois return; 22237f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } 222488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 222588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 22267f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois if (operand.IsImmediate()) { 22277f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois const Register& rn = operand.GetBaseRegister(); 22287f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois AddrMode addrmode = operand.GetAddrMode(); 22297f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois int32_t offset = operand.GetOffsetImmediate(); 2230b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard uint32_t extra_offset_mask = GetOffsetMask(type, addrmode); 2231b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard // Try to maximize the offset used by the MemOperand (load_store_offset). 2232b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard // Add the part which can't be used by the MemOperand (add_offset). 2233b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard uint32_t load_store_offset = offset & extra_offset_mask; 2234b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard uint32_t add_offset = offset & ~extra_offset_mask; 2235b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard if ((add_offset != 0) && 2236b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard (IsModifiedImmediate(offset) || IsModifiedImmediate(-offset))) { 2237b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard load_store_offset = 0; 2238b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard add_offset = offset; 2239b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard } 22407f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois switch (addrmode) { 22417f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois case PreIndex: { 22427f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // Allow using the destinations as a scratch registers if possible. 22437f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois UseScratchRegisterScope temps(this); 22447f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois if (type == kLdrd) { 22457f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois if (!rt.Is(rn)) temps.Include(rt); 22467f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois if (!rt2.Is(rn)) temps.Include(rt2); 224788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 22487f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois 22497f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // Pre-Indexed case: 22507f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // ldrd r0, r1, [r2, 12345]! will translate into 22517f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // add r2, 12345 22527f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // ldrd r0, r1, [r2] 22537f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois { 22547f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois CodeBufferCheckScope scope(this, 3 * kMaxInstructionSizeInBytes); 2255b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard add(cond, rn, rn, add_offset); 22567f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } 22577f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois { 22587f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 2259b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard (this->*instruction)(cond, 2260b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard rt, 2261b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard rt2, 2262b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard MemOperand(rn, load_store_offset, PreIndex)); 22637f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } 22647f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois return; 226588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 22667f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois case Offset: { 22677f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois UseScratchRegisterScope temps(this); 22687f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // Allow using the destinations as a scratch registers if possible. 22697f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois if (type == kLdrd) { 22707f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois if (!rt.Is(rn)) temps.Include(rt); 22717f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois if (!rt2.Is(rn)) temps.Include(rt2); 22727f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } 22737f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois Register scratch = temps.Acquire(); 22747f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // Offset case: 22757f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // ldrd r0, r1, [r2, 12345] will translate into 22767f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // add r0, r2, 12345 22777f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // ldrd r0, r1, [r0] 22787f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois { 22797f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois CodeBufferCheckScope scope(this, 3 * kMaxInstructionSizeInBytes); 2280b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard add(cond, scratch, rn, add_offset); 22817f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } 22827f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois { 22837f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 2284b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard (this->*instruction)(cond, 2285b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard rt, 2286b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard rt2, 2287b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard MemOperand(scratch, load_store_offset)); 22887f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } 22897f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois return; 22907f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } 22917f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois case PostIndex: 22927f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // Avoid the unpredictable case 'ldrd r0, r1, [r0], imm' 22937f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois if (!rn.Is(rt) && !rn.Is(rt2)) { 22947f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // Post-indexed case: 22957f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // ldrd r0, r1, [r2], imm32 will translate into 229688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // ldrd r0, r1, [r2] 22977f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // movw ip. imm32 & 0xffffffff 22987f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // movt ip, imm32 >> 16 22997f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // add r2, ip 2300aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 2301aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 2302b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard (this->*instruction)(cond, 2303b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard rt, 2304b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard rt2, 2305b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard MemOperand(rn, load_store_offset, PostIndex)); 2306aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 2307aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 23087f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois CodeBufferCheckScope scope(this, 3 * kMaxInstructionSizeInBytes); 2309b2838fee50499a1c7963167b0d8144552f194e15Vincent Belliard add(cond, rn, rn, add_offset); 231088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 231188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return; 23127f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } 23137f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois break; 23147f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } 23157f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } 23167f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois if (operand.IsPlainRegister()) { 23177f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois const Register& rn = operand.GetBaseRegister(); 23187f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois const Register& rm = operand.GetOffsetRegister(); 23197f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois AddrMode addrmode = operand.GetAddrMode(); 23207f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois switch (addrmode) { 23217f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois case PreIndex: 23227f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // ldrd r0, r1, [r2, r3]! will translate into 23237f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // add r2, r3 23247f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // ldrd r0, r1, [r2] 23257f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois { 23267f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 23277f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois if (operand.GetSign().IsPlus()) { 23287f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois add(cond, rn, rn, rm); 23297f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } else { 23307f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois sub(cond, rn, rn, rm); 233188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 23327f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } 23337f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois { 23347f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 23357f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois (this->*instruction)(cond, rt, rt2, MemOperand(rn, Offset)); 23367f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } 23377f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois return; 23387f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois case PostIndex: 23397f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // ldrd r0, r1, [r2], r3 will translate into 23407f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // ldrd r0, r1, [r2] 23417f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // add r2, r3 23427f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois { 23437f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 23447f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois (this->*instruction)(cond, rt, rt2, MemOperand(rn, Offset)); 23457f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } 23467f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois { 23477f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 23487f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois if (operand.GetSign().IsPlus()) { 23497f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois add(cond, rn, rn, rm); 23507f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } else { 23517f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois sub(cond, rn, rn, rm); 2352aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 23537f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } 23547f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois return; 23557f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois case Offset: { 23567f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois UseScratchRegisterScope temps(this); 23577f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // Allow using the destinations as a scratch registers if possible. 23587f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois if (type == kLdrd) { 23597f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois if (!rt.Is(rn)) temps.Include(rt); 23607f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois if (!rt2.Is(rn)) temps.Include(rt2); 23617f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } 23627f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois Register scratch = temps.Acquire(); 23637f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // Offset case: 23647f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // ldrd r0, r1, [r2, r3] will translate into 23657f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // add r0, r2, r3 23667f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois // ldrd r0, r1, [r0] 23677f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois { 23687f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 23697f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois if (operand.GetSign().IsPlus()) { 23707f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois add(cond, scratch, rn, rm); 23717f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } else { 23727f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois sub(cond, scratch, rn, rm); 237388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 237488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 23757f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois { 23767f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 23777f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois (this->*instruction)(cond, rt, rt2, MemOperand(scratch, Offset)); 23787f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois } 23797f2a44c6dce08e942080f14af19f83a202162104Pierre Langlois return; 238088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 238188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 238288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 238388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Assembler::Delegate(type, instruction, cond, rt, rt2, operand); 238488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 238588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 238688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 238788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid MacroAssembler::Delegate(InstructionType type, 238888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois InstructionCondDtSMop instruction, 238988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Condition cond, 239088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois DataType dt, 239188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois SRegister rd, 239288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const MemOperand& operand) { 239321d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell CONTEXT_SCOPE; 239488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (operand.IsImmediate()) { 239588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const Register& rn = operand.GetBaseRegister(); 239688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois AddrMode addrmode = operand.GetAddrMode(); 239788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois int32_t offset = operand.GetOffsetImmediate(); 2398df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell VIXL_ASSERT(((offset > 0) && operand.GetSign().IsPlus()) || 2399df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell ((offset < 0) && operand.GetSign().IsMinus()) || (offset == 0)); 2400df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell if (rn.IsPC()) { 2401df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell VIXL_ABORT_WITH_MSG( 2402df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell "The MacroAssembler does not convert vldr or vstr with a PC base " 2403df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell "register.\n"); 2404df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell } 240588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois switch (addrmode) { 240688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case PreIndex: 240788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // Pre-Indexed case: 240888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vldr.32 s0, [r1, 12345]! will translate into 240988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // add r1, 12345 241088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vldr.32 s0, [r1] 2411df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell if (offset != 0) { 2412df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell CodeBufferCheckScope scope(this, 3 * kMaxInstructionSizeInBytes); 2413df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell add(cond, rn, rn, offset); 2414aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 2415aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 2416aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 2417aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley (this->*instruction)(cond, dt, rd, MemOperand(rn, Offset)); 241888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 241988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return; 242088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case Offset: { 242188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois UseScratchRegisterScope temps(this); 242288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register scratch = temps.Acquire(); 242388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // Offset case: 242488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vldr.32 s0, [r1, 12345] will translate into 242588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // add ip, r1, 12345 242688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vldr.32 s0, [ip] 2427aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 2428df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell VIXL_ASSERT(offset != 0); 2429df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell CodeBufferCheckScope scope(this, 3 * kMaxInstructionSizeInBytes); 2430df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell add(cond, scratch, rn, offset); 2431aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 2432aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 2433aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 2434aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley (this->*instruction)(cond, dt, rd, MemOperand(scratch, Offset)); 243588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 243688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return; 243788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 243888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case PostIndex: 243988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // Post-indexed case: 244088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vldr.32 s0, [r1], imm32 will translate into 244188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vldr.32 s0, [r1] 244288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // movw ip. imm32 & 0xffffffff 244388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // movt ip, imm32 >> 16 244488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // add r1, ip 2445aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 2446aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 2447aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley (this->*instruction)(cond, dt, rd, MemOperand(rn, Offset)); 2448aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 2449df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell if (offset != 0) { 2450df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell CodeBufferCheckScope scope(this, 3 * kMaxInstructionSizeInBytes); 2451df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell add(cond, rn, rn, offset); 245288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 245388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return; 245488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 245588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 245688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Assembler::Delegate(type, instruction, cond, dt, rd, operand); 245788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 245888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 245988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 246088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid MacroAssembler::Delegate(InstructionType type, 246188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois InstructionCondDtDMop instruction, 246288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Condition cond, 246388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois DataType dt, 246488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois DRegister rd, 246588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const MemOperand& operand) { 246621d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell CONTEXT_SCOPE; 246788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois if (operand.IsImmediate()) { 246888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const Register& rn = operand.GetBaseRegister(); 246988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois AddrMode addrmode = operand.GetAddrMode(); 247088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois int32_t offset = operand.GetOffsetImmediate(); 2471df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell VIXL_ASSERT(((offset > 0) && operand.GetSign().IsPlus()) || 2472df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell ((offset < 0) && operand.GetSign().IsMinus()) || (offset == 0)); 2473df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell if (rn.IsPC()) { 2474df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell VIXL_ABORT_WITH_MSG( 2475df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell "The MacroAssembler does not convert vldr or vstr with a PC base " 2476df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell "register.\n"); 2477df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell } 247888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois switch (addrmode) { 247988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case PreIndex: 248088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // Pre-Indexed case: 248188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vldr.64 d0, [r1, 12345]! will translate into 248288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // add r1, 12345 248388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vldr.64 d0, [r1] 2484df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell if (offset != 0) { 2485df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell CodeBufferCheckScope scope(this, 3 * kMaxInstructionSizeInBytes); 2486df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell add(cond, rn, rn, offset); 2487aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 2488aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 2489aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 2490aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley (this->*instruction)(cond, dt, rd, MemOperand(rn, Offset)); 249188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 249288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return; 249388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case Offset: { 249488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois UseScratchRegisterScope temps(this); 249588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Register scratch = temps.Acquire(); 249688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // Offset case: 249788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vldr.64 d0, [r1, 12345] will translate into 249888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // add ip, r1, 12345 249988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vldr.32 s0, [ip] 2500aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 2501df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell VIXL_ASSERT(offset != 0); 2502df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell CodeBufferCheckScope scope(this, 3 * kMaxInstructionSizeInBytes); 2503df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell add(cond, scratch, rn, offset); 2504aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 2505aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 2506aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 2507aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley (this->*instruction)(cond, dt, rd, MemOperand(scratch, Offset)); 250888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 250988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return; 251088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 251188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois case PostIndex: 251288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // Post-indexed case: 251388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vldr.64 d0. [r1], imm32 will translate into 251488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // vldr.64 d0, [r1] 251588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // movw ip. imm32 & 0xffffffff 251688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // movt ip, imm32 >> 16 251788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois // add r1, ip 2518aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley { 2519aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 2520aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley (this->*instruction)(cond, dt, rd, MemOperand(rn, Offset)); 2521aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 2522df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell if (offset != 0) { 2523df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell CodeBufferCheckScope scope(this, 3 * kMaxInstructionSizeInBytes); 2524df9f46669cb7ea55844ab6e5ac0b12c26399b233Martyn Capewell add(cond, rn, rn, offset); 252588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 252688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois return; 252788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 252888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois } 252988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Assembler::Delegate(type, instruction, cond, dt, rd, operand); 253088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 253188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 253288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 253388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisvoid MacroAssembler::Delegate(InstructionType type, 2534a01fbf25f9e2c9c53e82774126c4717ee37c1d91Georgia Kouveli InstructionCondMsrOp instruction, 253588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois Condition cond, 253688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois MaskedSpecialRegister spec_reg, 253788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois const Operand& operand) { 253888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois USE(type); 253988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois VIXL_ASSERT(type == kMsr); 2540a01fbf25f9e2c9c53e82774126c4717ee37c1d91Georgia Kouveli if (operand.IsImmediate()) { 2541a01fbf25f9e2c9c53e82774126c4717ee37c1d91Georgia Kouveli UseScratchRegisterScope temps(this); 2542a01fbf25f9e2c9c53e82774126c4717ee37c1d91Georgia Kouveli Register scratch = temps.Acquire(); 2543a01fbf25f9e2c9c53e82774126c4717ee37c1d91Georgia Kouveli { 2544a01fbf25f9e2c9c53e82774126c4717ee37c1d91Georgia Kouveli CodeBufferCheckScope scope(this, 2 * kMaxInstructionSizeInBytes); 2545a01fbf25f9e2c9c53e82774126c4717ee37c1d91Georgia Kouveli mov(cond, scratch, operand); 2546a01fbf25f9e2c9c53e82774126c4717ee37c1d91Georgia Kouveli } 2547aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley CodeBufferCheckScope scope(this, kMaxInstructionSizeInBytes); 2548a01fbf25f9e2c9c53e82774126c4717ee37c1d91Georgia Kouveli msr(cond, spec_reg, scratch); 2549a01fbf25f9e2c9c53e82774126c4717ee37c1d91Georgia Kouveli return; 2550aaac397e490f27ca3011e8ba2cb61f4f455c1a4dJacob Bramley } 2551a01fbf25f9e2c9c53e82774126c4717ee37c1d91Georgia Kouveli Assembler::Delegate(type, instruction, cond, spec_reg, operand); 255288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} 255388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois 2554f8c2284645ce651f99ba410a512279102851076eJacob Bramley 2555f8c2284645ce651f99ba410a512279102851076eJacob Bramleyvoid MacroAssembler::Delegate(InstructionType type, 2556f8c2284645ce651f99ba410a512279102851076eJacob Bramley InstructionCondDtDL instruction, 2557f8c2284645ce651f99ba410a512279102851076eJacob Bramley Condition cond, 2558f8c2284645ce651f99ba410a512279102851076eJacob Bramley DataType dt, 2559f8c2284645ce651f99ba410a512279102851076eJacob Bramley DRegister rd, 2560f8c2284645ce651f99ba410a512279102851076eJacob Bramley Label* label) { 2561f8c2284645ce651f99ba410a512279102851076eJacob Bramley VIXL_ASSERT(type == kVldr); 2562f8c2284645ce651f99ba410a512279102851076eJacob Bramley 2563f8c2284645ce651f99ba410a512279102851076eJacob Bramley CONTEXT_SCOPE; 2564f8c2284645ce651f99ba410a512279102851076eJacob Bramley 2565f8c2284645ce651f99ba410a512279102851076eJacob Bramley if (label->IsBound()) { 256689d2f7702f0dc1751574bd5f9d35b5182fc65facJacob Bramley CodeBufferCheckScope scope(this, 5 * kMaxInstructionSizeInBytes); 2567f8c2284645ce651f99ba410a512279102851076eJacob Bramley UseScratchRegisterScope temps(this); 2568f8c2284645ce651f99ba410a512279102851076eJacob Bramley Register scratch = temps.Acquire(); 2569f8c2284645ce651f99ba410a512279102851076eJacob Bramley uint32_t mask = GetOffsetMask(type, Offset); 2570f8c2284645ce651f99ba410a512279102851076eJacob Bramley vldr(dt, rd, MemOperandComputationHelper(cond, scratch, label, mask)); 2571f8c2284645ce651f99ba410a512279102851076eJacob Bramley return; 2572f8c2284645ce651f99ba410a512279102851076eJacob Bramley } 2573f8c2284645ce651f99ba410a512279102851076eJacob Bramley 2574f8c2284645ce651f99ba410a512279102851076eJacob Bramley Assembler::Delegate(type, instruction, cond, dt, rd, label); 2575f8c2284645ce651f99ba410a512279102851076eJacob Bramley} 2576f8c2284645ce651f99ba410a512279102851076eJacob Bramley 2577f8c2284645ce651f99ba410a512279102851076eJacob Bramley 2578f8c2284645ce651f99ba410a512279102851076eJacob Bramleyvoid MacroAssembler::Delegate(InstructionType type, 2579f8c2284645ce651f99ba410a512279102851076eJacob Bramley InstructionCondDtSL instruction, 2580f8c2284645ce651f99ba410a512279102851076eJacob Bramley Condition cond, 2581f8c2284645ce651f99ba410a512279102851076eJacob Bramley DataType dt, 2582f8c2284645ce651f99ba410a512279102851076eJacob Bramley SRegister rd, 2583f8c2284645ce651f99ba410a512279102851076eJacob Bramley Label* label) { 2584f8c2284645ce651f99ba410a512279102851076eJacob Bramley VIXL_ASSERT(type == kVldr); 2585f8c2284645ce651f99ba410a512279102851076eJacob Bramley 2586f8c2284645ce651f99ba410a512279102851076eJacob Bramley CONTEXT_SCOPE; 2587f8c2284645ce651f99ba410a512279102851076eJacob Bramley 2588f8c2284645ce651f99ba410a512279102851076eJacob Bramley if (label->IsBound()) { 258989d2f7702f0dc1751574bd5f9d35b5182fc65facJacob Bramley CodeBufferCheckScope scope(this, 5 * kMaxInstructionSizeInBytes); 2590f8c2284645ce651f99ba410a512279102851076eJacob Bramley UseScratchRegisterScope temps(this); 2591f8c2284645ce651f99ba410a512279102851076eJacob Bramley Register scratch = temps.Acquire(); 2592f8c2284645ce651f99ba410a512279102851076eJacob Bramley uint32_t mask = GetOffsetMask(type, Offset); 2593f8c2284645ce651f99ba410a512279102851076eJacob Bramley vldr(dt, rd, MemOperandComputationHelper(cond, scratch, label, mask)); 2594f8c2284645ce651f99ba410a512279102851076eJacob Bramley return; 2595f8c2284645ce651f99ba410a512279102851076eJacob Bramley } 2596f8c2284645ce651f99ba410a512279102851076eJacob Bramley 2597f8c2284645ce651f99ba410a512279102851076eJacob Bramley Assembler::Delegate(type, instruction, cond, dt, rd, label); 2598f8c2284645ce651f99ba410a512279102851076eJacob Bramley} 2599f8c2284645ce651f99ba410a512279102851076eJacob Bramley 2600f8c2284645ce651f99ba410a512279102851076eJacob Bramley 260121d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell#undef CONTEXT_SCOPE 260221d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell#undef TOSTRING 260321d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell#undef STRINGIFY 260421d8d8d551fc50cb15fc137f00a154ea65eb2b81Martyn Capewell 260588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// Start of generated code. 260688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// End of generated code. 260788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} // namespace aarch32 260888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois} // namespace vixl 2609