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