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