assembler-arm.cc revision d0582a6c46733687d045e4188a1bcd0123c758a1
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 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The original source code covered by the above license above has been modified 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// significantly by Google Inc. 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2008 the V8 project authors. All rights reserved. 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "arm/assembler-arm-inl.h" 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "serialize.h" 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 45d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Safe default is no features. 46d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockunsigned CpuFeatures::supported_ = 0; 47d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockunsigned CpuFeatures::enabled_ = 0; 48d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockunsigned CpuFeatures::found_by_runtime_probing_ = 0; 49d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 50d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid CpuFeatures::Probe() { 51d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the compiler is allowed to use vfp then we can use vfp too in our 52d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // code generation. 53d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#if !defined(__arm__) 54d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // For the simulator=arm build, always use VFP since the arm simulator has 55d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // VFP support. 56d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block supported_ |= 1u << VFP3; 57d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#else 58d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (Serializer::enabled()) { 59d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block supported_ |= OS::CpuFeaturesImpliedByPlatform(); 60d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return; // No features if we might serialize. 61d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 62d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 63d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (OS::ArmCpuHasFeature(VFP3)) { 64d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This implementation also sets the VFP flags if 65d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // runtime detection of VFP returns true. 66d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block supported_ |= 1u << VFP3; 67d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block found_by_runtime_probing_ |= 1u << VFP3; 68d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 69d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif 70d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 71d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 72d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------- 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of Register and CRegister 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister no_reg = { -1 }; 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r0 = { 0 }; 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r1 = { 1 }; 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r2 = { 2 }; 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r3 = { 3 }; 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r4 = { 4 }; 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r5 = { 5 }; 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r6 = { 6 }; 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r7 = { 7 }; 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r8 = { 8 }; 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r9 = { 9 }; 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister r10 = { 10 }; 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister fp = { 11 }; 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister ip = { 12 }; 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister sp = { 13 }; 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister lr = { 14 }; 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister pc = { 15 }; 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister no_creg = { -1 }; 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr0 = { 0 }; 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr1 = { 1 }; 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr2 = { 2 }; 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr3 = { 3 }; 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr4 = { 4 }; 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr5 = { 5 }; 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr6 = { 6 }; 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr7 = { 7 }; 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr8 = { 8 }; 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr9 = { 9 }; 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr10 = { 10 }; 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr11 = { 11 }; 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr12 = { 12 }; 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr13 = { 13 }; 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr14 = { 14 }; 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCRegister cr15 = { 15 }; 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 115d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Support for the VFP registers s0 to s31 (d0 to d15). 116d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Note that "sN:sM" is the same as "dN/2". 117d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s0 = { 0 }; 118d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s1 = { 1 }; 119d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s2 = { 2 }; 120d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s3 = { 3 }; 121d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s4 = { 4 }; 122d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s5 = { 5 }; 123d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s6 = { 6 }; 124d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s7 = { 7 }; 125d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s8 = { 8 }; 126d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s9 = { 9 }; 127d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s10 = { 10 }; 128d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s11 = { 11 }; 129d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s12 = { 12 }; 130d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s13 = { 13 }; 131d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s14 = { 14 }; 132d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s15 = { 15 }; 133d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s16 = { 16 }; 134d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s17 = { 17 }; 135d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s18 = { 18 }; 136d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s19 = { 19 }; 137d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s20 = { 20 }; 138d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s21 = { 21 }; 139d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s22 = { 22 }; 140d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s23 = { 23 }; 141d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s24 = { 24 }; 142d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s25 = { 25 }; 143d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s26 = { 26 }; 144d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s27 = { 27 }; 145d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s28 = { 28 }; 146d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s29 = { 29 }; 147d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s30 = { 30 }; 148d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister s31 = { 31 }; 149d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 150d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d0 = { 0 }; 151d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d1 = { 1 }; 152d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d2 = { 2 }; 153d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d3 = { 3 }; 154d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d4 = { 4 }; 155d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d5 = { 5 }; 156d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d6 = { 6 }; 157d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d7 = { 7 }; 158d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d8 = { 8 }; 159d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d9 = { 9 }; 160d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d10 = { 10 }; 161d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d11 = { 11 }; 162d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d12 = { 12 }; 163d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d13 = { 13 }; 164d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d14 = { 14 }; 165d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockRegister d15 = { 15 }; 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------- 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of RelocInfo 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int RelocInfo::kApplyMask = 0; 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RelocInfo::PatchCode(byte* instructions, int instruction_count) { 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the code at the current address with the supplied instructions. 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Instr* pc = reinterpret_cast<Instr*>(pc_); 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Instr* instr = reinterpret_cast<Instr*>(instructions); 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < instruction_count; i++) { 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *(pc + i) = *(instr + i); 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Indicate that code has changed. 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CPU::FlushICache(pc_, instruction_count * Assembler::kInstrSize); 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Patch the code at the current PC with a call to the target address. 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Additional guard instructions can be added if required. 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) { 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the code at the current address with a call to the target. 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNIMPLEMENTED(); 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------- 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of Operand and MemOperand 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// See assembler-arm-inl.h for inlined constructors 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand::Operand(Handle<Object> handle) { 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rm_ = no_reg; 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Verify all Objects referred by code are NOT in new space. 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* obj = *handle; 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!Heap::InNewSpace(obj)); 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (obj->IsHeapObject()) { 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block imm32_ = reinterpret_cast<intptr_t>(handle.location()); 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rmode_ = RelocInfo::EMBEDDED_OBJECT; 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // no relocation needed 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block imm32_ = reinterpret_cast<intptr_t>(obj); 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rmode_ = RelocInfo::NONE; 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand::Operand(Register rm, ShiftOp shift_op, int shift_imm) { 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_uint5(shift_imm)); 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(shift_op != ROR || shift_imm != 0); // use RRX if you mean it 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rm_ = rm; 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rs_ = no_reg; 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift_op_ = shift_op; 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift_imm_ = shift_imm & 31; 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (shift_op == RRX) { 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // encoded as ROR with shift_imm == 0 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(shift_imm == 0); 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift_op_ = ROR; 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift_imm_ = 0; 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand::Operand(Register rm, ShiftOp shift_op, Register rs) { 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(shift_op != RRX); 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rm_ = rm; 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rs_ = no_reg; 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift_op_ = shift_op; 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rs_ = rs; 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMemOperand::MemOperand(Register rn, int32_t offset, AddrMode am) { 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rn_ = rn; 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rm_ = no_reg; 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block offset_ = offset; 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block am_ = am; 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMemOperand::MemOperand(Register rn, Register rm, AddrMode am) { 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rn_ = rn; 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rm_ = rm; 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift_op_ = LSL; 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift_imm_ = 0; 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block am_ = am; 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMemOperand::MemOperand(Register rn, Register rm, 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ShiftOp shift_op, int shift_imm, AddrMode am) { 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_uint5(shift_imm)); 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rn_ = rn; 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rm_ = rm; 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift_op_ = shift_op; 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shift_imm_ = shift_imm & 31; 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block am_ = am; 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------- 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of Assembler 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Instruction encoding bits 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum { 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block H = 1 << 5, // halfword (or byte) 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block S6 = 1 << 6, // signed (or unsigned) 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block L = 1 << 20, // load (or store) 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block S = 1 << 20, // set condition code (or leave unchanged) 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block W = 1 << 21, // writeback base register (or leave unchanged) 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block A = 1 << 21, // accumulate in multiply instruction (or not) 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block B = 1 << 22, // unsigned byte (or word) 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block N = 1 << 22, // long (or short) 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block U = 1 << 23, // positive (or negative) offset/index 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing) 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block I = 1 << 25, // immediate shifter operand (or not) 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block B4 = 1 << 4, 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block B5 = 1 << 5, 285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block B6 = 1 << 6, 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block B7 = 1 << 7, 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block B8 = 1 << 8, 288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block B9 = 1 << 9, 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block B12 = 1 << 12, 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block B16 = 1 << 16, 291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block B18 = 1 << 18, 292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block B19 = 1 << 19, 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block B20 = 1 << 20, 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block B21 = 1 << 21, 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block B22 = 1 << 22, 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block B23 = 1 << 23, 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block B24 = 1 << 24, 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block B25 = 1 << 25, 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block B26 = 1 << 26, 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block B27 = 1 << 27, 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instruction bit masks 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RdMask = 15 << 12, // in str instruction 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CondMask = 15 << 28, 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CoprocessorMask = 15 << 8, 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OpCodeMask = 15 << 21, // in data-processing instructions 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Imm24Mask = (1 << 24) - 1, 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Off12Mask = (1 << 12) - 1, 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reserved condition 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block nv = 15 << 28 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// add(sp, sp, 4) instruction (aka Pop()) 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const Instr kPopInstruction = 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block al | 4 * B21 | 4 | LeaveCC | I | sp.code() * B16 | sp.code() * B12; 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r)) 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register r is not encoded. 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const Instr kPushRegPattern = 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block al | B26 | 4 | NegPreIndex | sp.code() * B16; 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r)) 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register r is not encoded. 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const Instr kPopRegPattern = 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block al | B26 | L | 4 | PostIndex | sp.code() * B16; 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// mov lr, pc 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst Instr kMovLrPc = al | 13*B21 | pc.code() | lr.code() * B12; 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ldr pc, [pc, #XXX] 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst Instr kLdrPCPattern = al | B26 | L | pc.code() * B16; 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// spare_buffer_ 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kMinimalBufferSize = 4*KB; 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic byte* spare_buffer_ = NULL; 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAssembler::Assembler(void* buffer, int buffer_size) { 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (buffer == NULL) { 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // do our own buffer management 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (buffer_size <= kMinimalBufferSize) { 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer_size = kMinimalBufferSize; 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (spare_buffer_ != NULL) { 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer = spare_buffer_; 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block spare_buffer_ = NULL; 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (buffer == NULL) { 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer_ = NewArray<byte>(buffer_size); 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer_ = static_cast<byte*>(buffer); 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer_size_ = buffer_size; 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block own_buffer_ = true; 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // use externally provided buffer instead 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(buffer_size > 0); 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer_ = static_cast<byte*>(buffer); 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer_size_ = buffer_size; 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block own_buffer_ = false; 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // setup buffer pointers 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(buffer_ != NULL); 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc_ = buffer_; 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_prinfo_ = 0; 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block next_buffer_check_ = 0; 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block no_const_pool_before_ = 0; 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block last_const_pool_end_ = 0; 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block last_bound_pos_ = 0; 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current_statement_position_ = RelocInfo::kNoPosition; 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current_position_ = RelocInfo::kNoPosition; 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block written_statement_position_ = current_statement_position_; 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block written_position_ = current_position_; 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAssembler::~Assembler() { 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (own_buffer_) { 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block spare_buffer_ = buffer_; 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DeleteArray(buffer_); 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::GetCode(CodeDesc* desc) { 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // emit constant pool if necessary 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckConstPool(true, false); 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(num_prinfo_ == 0); 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // setup desc 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block desc->buffer = buffer_; 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block desc->buffer_size = buffer_size_; 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block desc->instr_size = pc_offset(); 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::Align(int m) { 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(m >= 4 && IsPowerOf2(m)); 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while ((pc_offset() & (m - 1)) != 0) { 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block nop(); 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Labels refer to positions in the (to be) generated code. 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// There are bound, linked, and unused labels. 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Bound labels refer to known positions in the already 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// generated code. pos() is the position the label refers to. 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Linked labels refer to unknown positions in the code 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to be generated; pos() is the position of the last 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// instruction using the label. 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The link chain is terminated by a negative code position (must be aligned) 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int kEndOfChain = -4; 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Assembler::target_at(int pos) { 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Instr instr = instr_at(pos); 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((instr & ~Imm24Mask) == 0) { 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emitted label constant, not part of a branch. 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return instr - (Code::kHeaderSize - kHeapObjectTag); 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int imm26 = ((instr & Imm24Mask) << 8) >> 6; 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((instr & CondMask) == nv && (instr & B24) != 0) 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // blx uses bit 24 to encode bit 2 of imm26 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block imm26 += 2; 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return pos + kPcLoadDelta + imm26; 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::target_at_put(int pos, int target_pos) { 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Instr instr = instr_at(pos); 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((instr & ~Imm24Mask) == 0) { 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(target_pos == kEndOfChain || target_pos >= 0); 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emitted label constant, not part of a branch. 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make label relative to Code* of generated Code object. 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int imm26 = target_pos - (pos + kPcLoadDelta); 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((instr & CondMask) == nv) { 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // blx uses bit 24 to encode bit 2 of imm26 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((imm26 & 1) == 0); 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr = (instr & ~(B24 | Imm24Mask)) | ((imm26 & 2) >> 1)*B24; 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((imm26 & 3) == 0); 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr &= ~Imm24Mask; 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int imm24 = imm26 >> 2; 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_int24(imm24)); 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr_at_put(pos, instr | (imm24 & Imm24Mask)); 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::print(Label* L) { 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (L->is_unused()) { 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("unused label\n"); 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (L->is_bound()) { 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("bound label to %d\n", L->pos()); 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (L->is_linked()) { 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label l = *L; 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("unbound label"); 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (l.is_linked()) { 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("@ %d ", l.pos()); 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Instr instr = instr_at(l.pos()); 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((instr & ~Imm24Mask) == 0) { 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("value\n"); 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int cond = instr & CondMask; 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* b; 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* c; 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (cond == nv) { 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block b = "blx"; 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block c = ""; 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((instr & B24) != 0) 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block b = "bl"; 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block else 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block b = "b"; 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (cond) { 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case eq: c = "eq"; break; 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ne: c = "ne"; break; 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case hs: c = "hs"; break; 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case lo: c = "lo"; break; 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case mi: c = "mi"; break; 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case pl: c = "pl"; break; 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case vs: c = "vs"; break; 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case vc: c = "vc"; break; 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case hi: c = "hi"; break; 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ls: c = "ls"; break; 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ge: c = "ge"; break; 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case lt: c = "lt"; break; 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case gt: c = "gt"; break; 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case le: c = "le"; break; 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case al: c = ""; break; 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block c = ""; 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("%s%s\n", b, c); 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block next(&l); 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("label in inconsistent state (pos = %d)\n", L->pos_); 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bind_to(Label* L, int pos) { 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(0 <= pos && pos <= pc_offset()); // must have a valid binding position 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (L->is_linked()) { 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int fixup_pos = L->pos(); 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block next(L); // call next before overwriting link with target at fixup_pos 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block target_at_put(fixup_pos, pos); 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block L->bind_to(pos); 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Keep track of the last bound label so we don't eliminate any instructions 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // before a bound label. 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (pos > last_bound_pos_) 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block last_bound_pos_ = pos; 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::link_to(Label* L, Label* appendix) { 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (appendix->is_linked()) { 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (L->is_linked()) { 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // append appendix to L's list 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int fixup_pos; 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int link = L->pos(); 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block do { 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fixup_pos = link; 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block link = target_at(fixup_pos); 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } while (link > 0); 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(link == kEndOfChain); 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block target_at_put(fixup_pos, appendix->pos()); 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // L is empty, simply use appendix 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *L = *appendix; 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block appendix->Unuse(); // appendix should not be used anymore 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bind(Label* L) { 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!L->is_bound()); // label can only be bound once 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind_to(L, pc_offset()); 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::next(Label* L) { 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(L->is_linked()); 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int link = target_at(L->pos()); 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (link > 0) { 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block L->link_to(link); 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(link == kEndOfChain); 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block L->Unuse(); 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Low-level code emission routines depending on the addressing mode 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool fits_shifter(uint32_t imm32, 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t* rotate_imm, 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t* immed_8, 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Instr* instr) { 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // imm32 must be unsigned 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int rot = 0; rot < 16; rot++) { 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t imm8 = (imm32 << 2*rot) | (imm32 >> (32 - 2*rot)); 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((imm8 <= 0xff)) { 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *rotate_imm = rot; 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *immed_8 = imm8; 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // if the opcode is mov or mvn and if ~imm32 fits, change the opcode 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (instr != NULL && (*instr & 0xd*B21) == 0xd*B21) { 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) { 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *instr ^= 0x2*B21; 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We have to use the temporary register for things that can be relocated even 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// if they can be encoded in the ARM's 12 bits of immediate-offset instruction 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// space. There is no guarantee that the relocated location can be similarly 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// encoded. 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool MustUseIp(RelocInfo::Mode rmode) { 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rmode == RelocInfo::EXTERNAL_REFERENCE) { 609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG 610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (!Serializer::enabled()) { 611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Serializer::TooLateToEnableNow(); 612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Serializer::enabled(); 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (rmode == RelocInfo::NONE) { 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod1(Instr instr, 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register rn, 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register rd, 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const Operand& x) { 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckBuffer(); 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((instr & ~(CondMask | OpCodeMask | S)) == 0); 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!x.rm_.is_valid()) { 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // immediate 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t rotate_imm; 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t immed_8; 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (MustUseIp(x.rmode_) || 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) { 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The immediate operand cannot be encoded as a shifter operand, so load 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // it first to register ip and change the original instruction to use ip. 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // However, if the original instruction is a 'mov rd, x' (not setting the 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // condition code), then replace it with a 'ldr rd, [pc]' 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordRelocInfo(x.rmode_, x.imm32_); 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(!rn.is(ip)); // rn should never be ip, or will be trashed 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition cond = static_cast<Condition>(instr & CondMask); 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((instr & ~CondMask) == 13*B21) { // mov, S not set 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ldr(rd, MemOperand(pc, 0), cond); 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ldr(ip, MemOperand(pc, 0), cond); 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod1(instr, rn, rd, Operand(ip)); 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr |= I | rotate_imm*B8 | immed_8; 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (!x.rs_.is_valid()) { 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // immediate shift 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr |= x.shift_imm_*B7 | x.shift_op_ | x.rm_.code(); 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register shift 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc)); 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr |= x.rs_.code()*B8 | x.shift_op_ | B4 | x.rm_.code(); 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(instr | rn.code()*B16 | rd.code()*B12); 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rn.is(pc) || x.rm_.is(pc)) 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // block constant pool emission for one instruction after reading pc 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BlockConstPoolBefore(pc_offset() + kInstrSize); 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod2(Instr instr, Register rd, const MemOperand& x) { 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((instr & ~(CondMask | B | L)) == B26); 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int am = x.am_; 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!x.rm_.is_valid()) { 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // immediate offset 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset_12 = x.offset_; 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (offset_12 < 0) { 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block offset_12 = -offset_12; 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block am ^= U; 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!is_uint12(offset_12)) { 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // immediate offset cannot be encoded, load it first to register ip 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rn (and rd in a load) should never be ip, or will be trashed 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip))); 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(ip, Operand(x.offset_), LeaveCC, 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static_cast<Condition>(instr & CondMask)); 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod2(instr, rd, MemOperand(x.rn_, ip, x.am_)); 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(offset_12 >= 0); // no masking needed 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr |= offset_12; 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register offset (shift_imm_ and shift_op_ are 0) or scaled 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register offset the constructors make sure than both shift_imm_ 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // and shift_op_ are initialized 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!x.rm_.is(pc)); 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr |= B25 | x.shift_imm_*B7 | x.shift_op_ | x.rm_.code(); 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(instr | am | x.rn_.code()*B16 | rd.code()*B12); 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod3(Instr instr, Register rd, const MemOperand& x) { 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((instr & ~(CondMask | L | S6 | H)) == (B4 | B7)); 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(x.rn_.is_valid()); 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int am = x.am_; 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!x.rm_.is_valid()) { 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // immediate offset 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset_8 = x.offset_; 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (offset_8 < 0) { 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block offset_8 = -offset_8; 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block am ^= U; 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!is_uint8(offset_8)) { 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // immediate offset cannot be encoded, load it first to register ip 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rn (and rd in a load) should never be ip, or will be trashed 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip))); 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(ip, Operand(x.offset_), LeaveCC, 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static_cast<Condition>(instr & CondMask)); 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_)); 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(offset_8 >= 0); // no masking needed 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr |= B | (offset_8 >> 4)*B8 | (offset_8 & 0xf); 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (x.shift_imm_ != 0) { 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scaled register offset not supported, load index first 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rn (and rd in a load) should never be ip, or will be trashed 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip))); 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(ip, Operand(x.rm_, x.shift_op_, x.shift_imm_), LeaveCC, 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static_cast<Condition>(instr & CondMask)); 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_)); 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register offset 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((am & (P|W)) == P || !x.rm_.is(pc)); // no pc index with writeback 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr |= x.rm_.code(); 732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(instr | am | x.rn_.code()*B16 | rd.code()*B12); 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod4(Instr instr, Register rn, RegList rl) { 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((instr & ~(CondMask | P | U | W | L)) == B27); 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(rl != 0); 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!rn.is(pc)); 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(instr | rn.code()*B16 | rl); 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::addrmod5(Instr instr, CRegister crd, const MemOperand& x) { 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // unindexed addressing is not encoded by this function 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ((B27 | B26), 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (instr & ~(CondMask | CoprocessorMask | P | U | N | W | L))); 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(x.rn_.is_valid() && !x.rm_.is_valid()); 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int am = x.am_; 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset_8 = x.offset_; 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((offset_8 & 3) == 0); // offset must be an aligned word offset 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block offset_8 >>= 2; 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (offset_8 < 0) { 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block offset_8 = -offset_8; 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block am ^= U; 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_uint8(offset_8)); // unsigned word offset must fit in a byte 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // post-indexed addressing requires W == 1; different than in addrmod2/3 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((am & P) == 0) 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block am |= W; 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(offset_8 >= 0); // no masking needed 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8); 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int target_pos; 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (L->is_bound()) { 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block target_pos = L->pos(); 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (L->is_linked()) { 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block target_pos = L->pos(); // L's link 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block target_pos = kEndOfChain; 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block L->link_to(pc_offset()); 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Block the emission of the constant pool, since the branch instruction must 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // be emitted at the pc offset recorded by the label 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BlockConstPoolBefore(pc_offset() + kInstrSize); 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return target_pos - (pc_offset() + kPcLoadDelta); 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::label_at_put(Label* L, int at_offset) { 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int target_pos; 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (L->is_bound()) { 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block target_pos = L->pos(); 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (L->is_linked()) { 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block target_pos = L->pos(); // L's link 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block target_pos = kEndOfChain; 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block L->link_to(at_offset); 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag)); 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Branch instructions 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::b(int branch_offset, Condition cond) { 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((branch_offset & 3) == 0); 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int imm24 = branch_offset >> 2; 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_int24(imm24)); 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | B27 | B25 | (imm24 & Imm24Mask)); 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (cond == al) 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // dead code is a good location to emit the constant pool 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckConstPool(false, false); 817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bl(int branch_offset, Condition cond) { 821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((branch_offset & 3) == 0); 822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int imm24 = branch_offset >> 2; 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_int24(imm24)); 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | B27 | B25 | B24 | (imm24 & Imm24Mask)); 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::blx(int branch_offset) { // v5 and above 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WriteRecordedPositions(); 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((branch_offset & 1) == 0); 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int h = ((branch_offset & 2) >> 1)*B24; 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int imm24 = branch_offset >> 2; 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_int24(imm24)); 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(15 << 28 | B27 | B25 | h | (imm24 & Imm24Mask)); 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::blx(Register target, Condition cond) { // v5 and above 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WriteRecordedPositions(); 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!target.is(pc)); 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | 3*B4 | target.code()); 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bx(Register target, Condition cond) { // v5 and above, plus v4t 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WriteRecordedPositions(); 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!target.is(pc)); // use of pc is actually allowed, but discouraged 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | B4 | target.code()); 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Data-processing instructions 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::and_(Register dst, Register src1, const Operand& src2, 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s, Condition cond) { 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod1(cond | 0*B21 | s, src1, dst, src2); 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::eor(Register dst, Register src1, const Operand& src2, 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s, Condition cond) { 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod1(cond | 1*B21 | s, src1, dst, src2); 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::sub(Register dst, Register src1, const Operand& src2, 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s, Condition cond) { 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod1(cond | 2*B21 | s, src1, dst, src2); 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::rsb(Register dst, Register src1, const Operand& src2, 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s, Condition cond) { 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod1(cond | 3*B21 | s, src1, dst, src2); 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::add(Register dst, Register src1, const Operand& src2, 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s, Condition cond) { 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod1(cond | 4*B21 | s, src1, dst, src2); 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Eliminate pattern: push(r), pop() 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // str(src, MemOperand(sp, 4, NegPreIndex), al); 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // add(sp, sp, Operand(kPointerSize)); 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Both instructions can be eliminated. 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int pattern_size = 2 * kInstrSize; 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_push_pop_elimination && 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block last_bound_pos_ <= (pc_offset() - pattern_size) && 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reloc_info_writer.last_pc() <= (pc_ - pattern_size) && 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // pattern 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr_at(pc_ - 1 * kInstrSize) == kPopInstruction && 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (instr_at(pc_ - 2 * kInstrSize) & ~RdMask) == kPushRegPattern) { 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc_ -= 2 * kInstrSize; 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_print_push_pop_elimination) { 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("%x push(reg)/pop() eliminated\n", pc_offset()); 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::adc(Register dst, Register src1, const Operand& src2, 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s, Condition cond) { 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod1(cond | 5*B21 | s, src1, dst, src2); 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::sbc(Register dst, Register src1, const Operand& src2, 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s, Condition cond) { 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod1(cond | 6*B21 | s, src1, dst, src2); 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::rsc(Register dst, Register src1, const Operand& src2, 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s, Condition cond) { 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod1(cond | 7*B21 | s, src1, dst, src2); 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::tst(Register src1, const Operand& src2, Condition cond) { 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod1(cond | 8*B21 | S, src1, r0, src2); 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::teq(Register src1, const Operand& src2, Condition cond) { 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod1(cond | 9*B21 | S, src1, r0, src2); 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::cmp(Register src1, const Operand& src2, Condition cond) { 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod1(cond | 10*B21 | S, src1, r0, src2); 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::cmn(Register src1, const Operand& src2, Condition cond) { 934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod1(cond | 11*B21 | S, src1, r0, src2); 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::orr(Register dst, Register src1, const Operand& src2, 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s, Condition cond) { 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod1(cond | 12*B21 | s, src1, dst, src2); 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) { 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (dst.is(pc)) { 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WriteRecordedPositions(); 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod1(cond | 13*B21 | s, r0, dst, src); 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bic(Register dst, Register src1, const Operand& src2, 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s, Condition cond) { 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod1(cond | 14*B21 | s, src1, dst, src2); 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) { 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod1(cond | 15*B21 | s, r0, dst, src); 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Multiply instructions 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mla(Register dst, Register src1, Register src2, Register srcA, 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s, Condition cond) { 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc)); 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | A | s | dst.code()*B16 | srcA.code()*B12 | 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block src2.code()*B8 | B7 | B4 | src1.code()); 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mul(Register dst, Register src1, Register src2, 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s, Condition cond) { 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc)); 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // dst goes in bits 16-19 for this instruction! 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | s | dst.code()*B16 | src2.code()*B8 | B7 | B4 | src1.code()); 977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::smlal(Register dstL, 981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register dstH, 982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s, 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition cond) { 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dstL.is(dstH)); 988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | B23 | B22 | A | s | dstH.code()*B16 | dstL.code()*B12 | 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block src2.code()*B8 | B7 | B4 | src1.code()); 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::smull(Register dstL, 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register dstH, 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s, 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition cond) { 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dstL.is(dstH)); 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 | 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block src2.code()*B8 | B7 | B4 | src1.code()); 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::umlal(Register dstL, 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register dstH, 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s, 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition cond) { 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dstL.is(dstH)); 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | B23 | A | s | dstH.code()*B16 | dstL.code()*B12 | 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block src2.code()*B8 | B7 | B4 | src1.code()); 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::umull(Register dstL, 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register dstH, 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src1, 1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src2, 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s, 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition cond) { 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dstL.is(dstH)); 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | B23 | s | dstH.code()*B16 | dstL.code()*B12 | 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block src2.code()*B8 | B7 | B4 | src1.code()); 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Miscellaneous arithmetic instructions 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::clz(Register dst, Register src, Condition cond) { 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // v5 and above. 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(pc) && !src.is(pc)); 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | B24 | B22 | B21 | 15*B16 | dst.code()*B12 | 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15*B8 | B4 | src.code()); 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Status register access instructions 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mrs(Register dst, SRegister s, Condition cond) { 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(pc)); 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | B24 | s | 15*B16 | dst.code()*B12); 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::msr(SRegisterFieldMask fields, const Operand& src, 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition cond) { 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(fields >= B16 && fields < B20); // at least one field set 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Instr instr; 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!src.rm_.is_valid()) { 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // immediate 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t rotate_imm; 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t immed_8; 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (MustUseIp(src.rmode_) || 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) { 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // immediate operand cannot be encoded, load it first to register ip 1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordRelocInfo(src.rmode_, src.imm32_); 1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ldr(ip, MemOperand(pc, 0), cond); 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block msr(fields, Operand(ip), cond); 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr = I | rotate_imm*B8 | immed_8; 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!src.rs_.is_valid() && src.shift_imm_ == 0); // only rm allowed 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr = src.rm_.code(); 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | instr | B24 | B21 | fields | 15*B12); 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load/Store instructions 1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { 1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (dst.is(pc)) { 1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WriteRecordedPositions(); 1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod2(cond | B26 | L, dst, src); 1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Eliminate pattern: push(r), pop(r) 1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // str(r, MemOperand(sp, 4, NegPreIndex), al) 1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ldr(r, MemOperand(sp, 4, PostIndex), al) 1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Both instructions can be eliminated. 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int pattern_size = 2 * kInstrSize; 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_push_pop_elimination && 1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block last_bound_pos_ <= (pc_offset() - pattern_size) && 1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reloc_info_writer.last_pc() <= (pc_ - pattern_size) && 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // pattern 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr_at(pc_ - 1 * kInstrSize) == (kPopRegPattern | dst.code() * B12) && 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr_at(pc_ - 2 * kInstrSize) == (kPushRegPattern | dst.code() * B12)) { 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc_ -= 2 * kInstrSize; 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_print_push_pop_elimination) { 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("%x push/pop (same reg) eliminated\n", pc_offset()); 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::str(Register src, const MemOperand& dst, Condition cond) { 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod2(cond | B26, src, dst); 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Eliminate pattern: pop(), push(r) 1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // add sp, sp, #4 LeaveCC, al; str r, [sp, #-4], al 1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -> str r, [sp, 0], al 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int pattern_size = 2 * kInstrSize; 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_push_pop_elimination && 1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block last_bound_pos_ <= (pc_offset() - pattern_size) && 1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reloc_info_writer.last_pc() <= (pc_ - pattern_size) && 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr_at(pc_ - 1 * kInstrSize) == (kPushRegPattern | src.code() * B12) && 1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr_at(pc_ - 2 * kInstrSize) == kPopInstruction) { 1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc_ -= 2 * kInstrSize; 1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(al | B26 | 0 | Offset | sp.code() * B16 | src.code() * B12); 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_print_push_pop_elimination) { 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("%x pop()/push(reg) eliminated\n", pc_offset()); 1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) { 1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod2(cond | B26 | B | L, dst, src); 1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::strb(Register src, const MemOperand& dst, Condition cond) { 1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod2(cond | B26 | B, src, dst); 1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) { 1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod3(cond | L | B7 | H | B4, dst, src); 1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::strh(Register src, const MemOperand& dst, Condition cond) { 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod3(cond | B7 | H | B4, src, dst); 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) { 1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod3(cond | L | B7 | S6 | B4, dst, src); 1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) { 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod3(cond | L | B7 | S6 | H | B4, dst, src); 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load/Store multiple instructions 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldm(BlockAddrMode am, 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register base, 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RegList dst, 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition cond) { 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ABI stack constraint: ldmxx base, {..sp..} base != sp is not restartable 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(base.is(sp) || (dst & sp.bit()) == 0); 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod4(cond | B27 | am | L, base, dst); 1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // emit the constant pool after a function return implemented by ldm ..{..pc} 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (cond == al && (dst & pc.bit()) != 0) { 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // There is a slight chance that the ldm instruction was actually a call, 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // in which case it would be wrong to return into the constant pool; we 1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // recognize this case by checking if the emission of the pool was blocked 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // at the pc of the ldm instruction by a mov lr, pc instruction; if this is 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the case, we emit a jump over the pool. 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckConstPool(true, no_const_pool_before_ == pc_offset() - kInstrSize); 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::stm(BlockAddrMode am, 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register base, 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RegList src, 1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition cond) { 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod4(cond | B27 | am, base, src); 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Semaphore instructions 1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::swp(Register dst, Register src, Register base, Condition cond) { 1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(pc) && !src.is(pc) && !base.is(pc)); 1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(base) && !src.is(base)); 1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | P | base.code()*B16 | dst.code()*B12 | 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block B7 | B4 | src.code()); 1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::swpb(Register dst, 1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register src, 1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register base, 1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition cond) { 1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(pc) && !src.is(pc) && !base.is(pc)); 1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!dst.is(base) && !src.is(base)); 1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | P | B | base.code()*B16 | dst.code()*B12 | 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block B7 | B4 | src.code()); 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Exception-generating instructions and debugging support 1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::stop(const char* msg) { 1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if !defined(__arm__) 1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The simulator handles these special instructions and stops execution. 1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(15 << 28 | ((intptr_t) msg)); 1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Just issue a simple break instruction for now. Alternatively we could use 1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the swi(0x9f0001) instruction on Linux. 1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bkpt(0); 1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::bkpt(uint32_t imm16) { // v5 and above 1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_uint16(imm16)); 1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(al | B24 | B21 | (imm16 >> 4)*B8 | 7*B4 | (imm16 & 0xf)); 1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::swi(uint32_t imm24, Condition cond) { 1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_uint24(imm24)); 1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | 15*B24 | imm24); 1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Coprocessor instructions 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::cdp(Coprocessor coproc, 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int opcode_1, 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crd, 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crn, 1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crm, 1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int opcode_2, 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition cond) { 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_uint4(opcode_1) && is_uint3(opcode_2)); 1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | B27 | B26 | B25 | (opcode_1 & 15)*B20 | crn.code()*B16 | 1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block crd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | crm.code()); 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::cdp2(Coprocessor coproc, 1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int opcode_1, 1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crd, 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crn, 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crm, 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int opcode_2) { // v5 and above 1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cdp(coproc, opcode_1, crd, crn, crm, opcode_2, static_cast<Condition>(nv)); 1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mcr(Coprocessor coproc, 1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int opcode_1, 1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register rd, 1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crn, 1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crm, 1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int opcode_2, 1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition cond) { 1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2)); 1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | crn.code()*B16 | 1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code()); 1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mcr2(Coprocessor coproc, 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int opcode_1, 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register rd, 1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crn, 1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crm, 1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int opcode_2) { // v5 and above 1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mcr(coproc, opcode_1, rd, crn, crm, opcode_2, static_cast<Condition>(nv)); 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mrc(Coprocessor coproc, 1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int opcode_1, 1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register rd, 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crn, 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crm, 1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int opcode_2, 1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition cond) { 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2)); 1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | L | crn.code()*B16 | 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code()); 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::mrc2(Coprocessor coproc, 1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int opcode_1, 1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register rd, 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crn, 1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crm, 1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int opcode_2) { // v5 and above 1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mrc(coproc, opcode_1, rd, crn, crm, opcode_2, static_cast<Condition>(nv)); 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldc(Coprocessor coproc, 1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crd, 1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const MemOperand& src, 1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LFlag l, 1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition cond) { 1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod5(cond | B27 | B26 | l | L | coproc*B8, crd, src); 1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldc(Coprocessor coproc, 1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crd, 1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register rn, 1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int option, 1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LFlag l, 1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition cond) { 1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // unindexed addressing 1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_uint8(option)); 1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | B27 | B26 | U | l | L | rn.code()*B16 | crd.code()*B12 | 1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block coproc*B8 | (option & 255)); 1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldc2(Coprocessor coproc, 1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crd, 1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const MemOperand& src, 1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LFlag l) { // v5 and above 1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ldc(coproc, crd, src, l, static_cast<Condition>(nv)); 1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::ldc2(Coprocessor coproc, 1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crd, 1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register rn, 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int option, 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LFlag l) { // v5 and above 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ldc(coproc, crd, rn, option, l, static_cast<Condition>(nv)); 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::stc(Coprocessor coproc, 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crd, 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const MemOperand& dst, 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LFlag l, 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition cond) { 1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addrmod5(cond | B27 | B26 | l | coproc*B8, crd, dst); 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::stc(Coprocessor coproc, 1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crd, 1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register rn, 1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int option, 1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LFlag l, 1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition cond) { 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // unindexed addressing 1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_uint8(option)); 1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(cond | B27 | B26 | U | l | rn.code()*B16 | crd.code()*B12 | 1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block coproc*B8 | (option & 255)); 1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::stc2(Coprocessor 1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block coproc, CRegister crd, 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const MemOperand& dst, 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LFlag l) { // v5 and above 1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stc(coproc, crd, dst, l, static_cast<Condition>(nv)); 1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::stc2(Coprocessor coproc, 1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRegister crd, 1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register rn, 1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int option, 1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LFlag l) { // v5 and above 1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stc(coproc, crd, rn, option, l, static_cast<Condition>(nv)); 1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Support for VFP. 1374d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::fmdrr(const Register dst, 1375d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Register src1, 1376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Register src2, 1377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const SBit s, 1378d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Condition cond) { 1379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Dm = <Rt,Rt2>. 1380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Instruction details available in ARM DDI 0406A, A8-646. 1381d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) | 1382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm 1383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(CpuFeatures::IsEnabled(VFP3)); 1384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(!src1.is(pc) && !src2.is(pc)); 1385d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block emit(cond | 0xC*B24 | B22 | src2.code()*B16 | 1386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block src1.code()*B12 | 0xB*B8 | B4 | dst.code()); 1387d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1389d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::fmrrd(const Register dst1, 1391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Register dst2, 1392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Register src, 1393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const SBit s, 1394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Condition cond) { 1395d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // <Rt,Rt2> = Dm. 1396d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Instruction details available in ARM DDI 0406A, A8-646. 1397d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) | 1398d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm 1399d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(CpuFeatures::IsEnabled(VFP3)); 1400d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(!dst1.is(pc) && !dst2.is(pc)); 1401d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 | 1402d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block dst1.code()*B12 | 0xB*B8 | B4 | src.code()); 1403d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1404d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1405d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1406d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::fmsr(const Register dst, 1407d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Register src, 1408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const SBit s, 1409d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Condition cond) { 1410d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Sn = Rt. 1411d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Instruction details available in ARM DDI 0406A, A8-642. 1412d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) | 1413d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0) 1414d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(CpuFeatures::IsEnabled(VFP3)); 1415d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(!src.is(pc)); 1416d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block emit(cond | 0xE*B24 | (dst.code() >> 1)*B16 | 1417d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block src.code()*B12 | 0xA*B8 | (0x1 & dst.code())*B7 | B4); 1418d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1420d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::fmrs(const Register dst, 1422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Register src, 1423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const SBit s, 1424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Condition cond) { 1425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Rt = Sn. 1426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Instruction details available in ARM DDI 0406A, A8-642. 1427d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) | 1428d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0) 1429d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(CpuFeatures::IsEnabled(VFP3)); 1430d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(!dst.is(pc)); 1431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block emit(cond | 0xE*B24 | B20 | (src.code() >> 1)*B16 | 1432d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block dst.code()*B12 | 0xA*B8 | (0x1 & src.code())*B7 | B4); 1433d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1434d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1435d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1436d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::fsitod(const Register dst, 1437d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Register src, 1438d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const SBit s, 1439d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Condition cond) { 1440d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Dd = Sm (integer in Sm converted to IEEE 64-bit doubles in Dd). 1441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Instruction details available in ARM DDI 0406A, A8-576. 1442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // cond(31-28) | 11101(27-23)| D=?(22) | 11(21-20) | 1(19) |opc2=000(18-16) | 1443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Vd(15-12) | 101(11-9) | sz(8)=1 | op(7)=1 | 1(6) | M=?(5) | 0(4) | Vm(3-0) 1444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(CpuFeatures::IsEnabled(VFP3)); 1445d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block emit(cond | 0xE*B24 | B23 | 0x3*B20 | B19 | 1446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block dst.code()*B12 | 0x5*B9 | B8 | B7 | B6 | 1447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block (0x1 & src.code())*B5 | (src.code() >> 1)); 1448d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1449d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1450d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::ftosid(const Register dst, 1452d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Register src, 1453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const SBit s, 1454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Condition cond) { 1455d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Sd = Dm (IEEE 64-bit doubles in Dm converted to 32 bit integer in Sd). 1456d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Instruction details available in ARM DDI 0406A, A8-576. 1457d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // cond(31-28) | 11101(27-23)| D=?(22) | 11(21-20) | 1(19) | opc2=101(18-16)| 1458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Vd(15-12) | 101(11-9) | sz(8)=1 | op(7)=? | 1(6) | M=?(5) | 0(4) | Vm(3-0) 1459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(CpuFeatures::IsEnabled(VFP3)); 1460d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block emit(cond | 0xE*B24 | B23 |(0x1 & dst.code())*B22 | 1461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 0x3*B20 | B19 | 0x5*B16 | (dst.code() >> 1)*B12 | 1462d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 0x5*B9 | B8 | B7 | B6 | src.code()); 1463d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1464d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1465d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1466d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::faddd(const Register dst, 1467d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Register src1, 1468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Register src2, 1469d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const SBit s, 1470d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Condition cond) { 1471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Dd = faddd(Dn, Dm) double precision floating point addition. 1472d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. 1473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Instruction details available in ARM DDI 0406A, A8-536. 1474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) | 1475d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0) 1476d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(CpuFeatures::IsEnabled(VFP3)); 1477d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 | 1478d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block dst.code()*B12 | 0x5*B9 | B8 | src2.code()); 1479d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1480d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1481d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1482d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::fsubd(const Register dst, 1483d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Register src1, 1484d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Register src2, 1485d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const SBit s, 1486d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Condition cond) { 1487d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Dd = fsubd(Dn, Dm) double precision floating point subtraction. 1488d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. 1489d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Instruction details available in ARM DDI 0406A, A8-784. 1490d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) | 1491d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 1(6) | M=?(5) | 0(4) | Vm(3-0) 1492d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(CpuFeatures::IsEnabled(VFP3)); 1493d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 | 1494d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block dst.code()*B12 | 0x5*B9 | B8 | B6 | src2.code()); 1495d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1496d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1497d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::fmuld(const Register dst, 1499d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Register src1, 1500d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Register src2, 1501d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const SBit s, 1502d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Condition cond) { 1503d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Dd = fmuld(Dn, Dm) double precision floating point multiplication. 1504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. 1505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Instruction details available in ARM DDI 0406A, A8-784. 1506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // cond(31-28) | 11100(27-23)| D=?(22) | 10(21-20) | Vn(19-16) | 1507d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0) 1508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(CpuFeatures::IsEnabled(VFP3)); 1509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block emit(cond | 0xE*B24 | 0x2*B20 | src1.code()*B16 | 1510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block dst.code()*B12 | 0x5*B9 | B8 | src2.code()); 1511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1512d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1514d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::fdivd(const Register dst, 1515d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Register src1, 1516d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Register src2, 1517d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const SBit s, 1518d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Condition cond) { 1519d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Dd = fdivd(Dn, Dm) double precision floating point division. 1520d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. 1521d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Instruction details available in ARM DDI 0406A, A8-584. 1522d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // cond(31-28) | 11101(27-23)| D=?(22) | 00(21-20) | Vn(19-16) | 1523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=? | 0(6) | M=?(5) | 0(4) | Vm(3-0) 1524d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(CpuFeatures::IsEnabled(VFP3)); 1525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block emit(cond | 0xE*B24 | B23 | src1.code()*B16 | 1526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block dst.code()*B12 | 0x5*B9 | B8 | src2.code()); 1527d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1528d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1529d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::fcmp(const Register src1, 1531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Register src2, 1532d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const SBit s, 1533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const Condition cond) { 1534d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // vcmp(Dd, Dm) double precision floating point comparison. 1535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Instruction details available in ARM DDI 0406A, A8-570. 1536d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0100 (19-16) | 1537d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=? | 1(6) | M(5)=? | 0(4) | Vm(3-0) 1538d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(CpuFeatures::IsEnabled(VFP3)); 1539d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 | 1540d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block src1.code()*B12 | 0x5*B9 | B8 | B6 | src2.code()); 1541d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1542d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::vmrs(Register dst, Condition cond) { 1545d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Instruction details available in ARM DDI 0406A, A8-652. 1546d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) | 1547d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0) 1548d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(CpuFeatures::IsEnabled(VFP3)); 1549d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block emit(cond | 0xE*B24 | 0xF*B20 | B16 | 1550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block dst.code()*B12 | 0xA*B8 | B4); 1551d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Pseudo instructions 1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::lea(Register dst, 1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const MemOperand& x, 1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SBit s, 1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Condition cond) { 1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int am = x.am_; 1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!x.rm_.is_valid()) { 1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // immediate offset 1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((am & P) == 0) // post indexing 1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(dst, Operand(x.rn_), s, cond); 1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block else if ((am & U) == 0) // negative indexing 1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sub(dst, x.rn_, Operand(x.offset_), s, cond); 1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block else 1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block add(dst, x.rn_, Operand(x.offset_), s, cond); 1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Register offset (shift_imm_ and shift_op_ are 0) or scaled 1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // register offset the constructors make sure than both shift_imm_ 1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // and shift_op_ are initialized. 1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!x.rm_.is(pc)); 1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((am & P) == 0) // post indexing 1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mov(dst, Operand(x.rn_), s, cond); 1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block else if ((am & U) == 0) // negative indexing 1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sub(dst, x.rn_, Operand(x.rm_, x.shift_op_, x.shift_imm_), s, cond); 1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block else 1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block add(dst, x.rn_, Operand(x.rm_, x.shift_op_, x.shift_imm_), s, cond); 1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockbool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) { 1584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block uint32_t dummy1; 1585d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block uint32_t dummy2; 1586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return fits_shifter(imm32, &dummy1, &dummy2, NULL); 1587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1589d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Assembler::BlockConstPoolFor(int instructions) { 1591d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block BlockConstPoolBefore(pc_offset() + instructions * kInstrSize); 1592d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1593d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1594d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Debugging 1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::RecordJSReturn() { 1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WriteRecordedPositions(); 1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckBuffer(); 1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordRelocInfo(RelocInfo::JS_RETURN); 1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::RecordComment(const char* msg) { 1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckBuffer(); 1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg)); 1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::RecordPosition(int pos) { 1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (pos == RelocInfo::kNoPosition) return; 1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(pos >= 0); 1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current_position_ = pos; 1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::RecordStatementPosition(int pos) { 1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (pos == RelocInfo::kNoPosition) return; 1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(pos >= 0); 1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current_statement_position_ = pos; 1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::WriteRecordedPositions() { 1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Write the statement position if it is different from what was written last 1627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // time. 1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (current_statement_position_ != written_statement_position_) { 1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckBuffer(); 1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_); 1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block written_statement_position_ = current_statement_position_; 1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Write the position if it is different from what was written last time and 1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // also different from the written statement position. 1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (current_position_ != written_position_ && 1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current_position_ != written_statement_position_) { 1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckBuffer(); 1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordRelocInfo(RelocInfo::POSITION, current_position_); 1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block written_position_ = current_position_; 1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::GrowBuffer() { 1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!own_buffer_) FATAL("external code buffer is too small"); 1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // compute new buffer size 1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CodeDesc desc; // the new buffer 1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (buffer_size_ < 4*KB) { 1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block desc.buffer_size = 4*KB; 1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (buffer_size_ < 1*MB) { 1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block desc.buffer_size = 2*buffer_size_; 1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block desc.buffer_size = buffer_size_ + 1*MB; 1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_GT(desc.buffer_size, 0); // no overflow 1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // setup new buffer 1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block desc.buffer = NewArray<byte>(desc.buffer_size); 1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block desc.instr_size = pc_offset(); 1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // copy the data 1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int pc_delta = desc.buffer - buffer_; 1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_); 1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block memmove(desc.buffer, buffer_, desc.instr_size); 1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block memmove(reloc_info_writer.pos() + rc_delta, 1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reloc_info_writer.pos(), desc.reloc_size); 1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // switch buffers 1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DeleteArray(buffer_); 1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer_ = desc.buffer; 1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer_size_ = desc.buffer_size; 1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc_ += pc_delta; 1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, 1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reloc_info_writer.last_pc() + pc_delta); 1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // none of our relocation types are pc relative pointing outside the code 1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // buffer nor pc absolute pointing inside the code buffer, so there is no need 1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to relocate any emitted relocation entries 1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // relocate pending relocation entries 1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < num_prinfo_; i++) { 1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo& rinfo = prinfo_[i]; 1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(rinfo.rmode() != RelocInfo::COMMENT && 1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rinfo.rmode() != RelocInfo::POSITION); 1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rinfo.rmode() != RelocInfo::JS_RETURN) { 1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rinfo.set_pc(rinfo.pc() + pc_delta); 1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { 1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo rinfo(pc_, rmode, data); // we do not try to reuse pool constants 1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::STATEMENT_POSITION) { 1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust code for new modes 1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(RelocInfo::IsJSReturn(rmode) 1701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block || RelocInfo::IsComment(rmode) 1702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block || RelocInfo::IsPosition(rmode)); 1703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // these modes do not need an entry in the constant pool 1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(num_prinfo_ < kMaxNumPRInfo); 1706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block prinfo_[num_prinfo_++] = rinfo; 1707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure the constant pool is not emitted in place of the next 1708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // instruction for which we just recorded relocation info 1709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BlockConstPoolBefore(pc_offset() + kInstrSize); 1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rinfo.rmode() != RelocInfo::NONE) { 1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Don't record external references unless the heap will be serialized. 1713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (rmode == RelocInfo::EXTERNAL_REFERENCE) { 1714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG 1715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (!Serializer::enabled()) { 1716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Serializer::TooLateToEnableNow(); 1717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif 1719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (!Serializer::enabled() && !FLAG_debug_code) { 1720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return; 1721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(buffer_space() >= kMaxRelocSize); // too late to grow buffer here 1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reloc_info_writer.Write(&rinfo); 1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::CheckConstPool(bool force_emit, bool require_jump) { 1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the offset of the next check. It will be overwritten 1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // when a const pool is generated or when const pools are being 1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // blocked for a specific range. 1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block next_buffer_check_ = pc_offset() + kCheckConstInterval; 1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // There is nothing to do if there are no pending relocation info entries 1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_prinfo_ == 0) return; 1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We emit a constant pool at regular intervals of about kDistBetweenPools 1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // or when requested by parameter force_emit (e.g. after each function). 1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We prefer not to emit a jump unless the max distance is reached or if we 1741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // are running low on slots, which can happen if a lot of constants are being 1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // emitted (e.g. --debug-code and many static references). 1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int dist = pc_offset() - last_const_pool_end_; 1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!force_emit && dist < kMaxDistBetweenPools && 1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (require_jump || dist < kDistBetweenPools) && 1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(1236125): Cleanup the "magic" number below. We know that 1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the code generation will test every kCheckConstIntervalInst. 1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Thus we are safe as long as we generate less than 7 constant 1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // entries per instruction. 1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (num_prinfo_ < (kMaxNumPRInfo - (7 * kCheckConstIntervalInst)))) { 1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we did not return by now, we need to emit the constant pool soon. 1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // However, some small sequences of instructions must not be broken up by the 1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // insertion of a constant pool; such sequences are protected by setting 1758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // no_const_pool_before_, which is checked here. Also, recursive calls to 1759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // CheckConstPool are blocked by no_const_pool_before_. 1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (pc_offset() < no_const_pool_before_) { 1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emission is currently blocked; make sure we try again as soon as possible 1762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block next_buffer_check_ = no_const_pool_before_; 1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Something is wrong if emission is forced and blocked at the same time 1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!force_emit); 1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int jump_instr = require_jump ? kInstrSize : 0; 1770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the code buffer is large enough before emitting the constant 1772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // pool and relocation information (include the jump over the pool and the 1773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // constant pool marker). 1774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int max_needed_space = 1775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block jump_instr + kInstrSize + num_prinfo_*(kInstrSize + kMaxRelocSize); 1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (buffer_space() <= (max_needed_space + kGap)) GrowBuffer(); 1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Block recursive calls to CheckConstPool 1779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BlockConstPoolBefore(pc_offset() + jump_instr + kInstrSize + 1780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_prinfo_*kInstrSize); 1781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Don't bother to check for the emit calls below. 1782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block next_buffer_check_ = no_const_pool_before_; 1783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emit jump over constant pool if necessary 1785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label after_pool; 1786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (require_jump) b(&after_pool); 1787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordComment("[ Constant Pool"); 1789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Put down constant pool marker 1791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // "Undefined instruction" as specified by A3.1 Instruction set encoding 1792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(0x03000000 | num_prinfo_); 1793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Emit constant pool entries 1795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < num_prinfo_; i++) { 1796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo& rinfo = prinfo_[i]; 1797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(rinfo.rmode() != RelocInfo::COMMENT && 1798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rinfo.rmode() != RelocInfo::POSITION && 1799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rinfo.rmode() != RelocInfo::STATEMENT_POSITION); 1800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Instr instr = instr_at(rinfo.pc()); 1801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instruction to patch must be a ldr/str [pc, #offset] 1803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // P and U set, B and W clear, Rn == pc, offset12 still 0 1804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((instr & (7*B25 | P | U | B | W | 15*B16 | Off12Mask)) == 1805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (2*B25 | P | U | pc.code()*B16)); 1806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int delta = pc_ - rinfo.pc() - 8; 1807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(delta >= -4); // instr could be ldr pc, [pc, #-4] followed by targ32 1808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (delta < 0) { 1809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr &= ~U; 1810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delta = -delta; 1811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(is_uint12(delta)); 1813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instr_at_put(rinfo.pc(), instr + delta); 1814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block emit(rinfo.data()); 1815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_prinfo_ = 0; 1817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block last_const_pool_end_ = pc_offset(); 1818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RecordComment("]"); 1820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (after_pool.is_linked()) { 1822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bind(&after_pool); 1823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Since a constant pool was just emitted, move the check offset forward by 1826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the standard interval. 1827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block next_buffer_check_ = pc_offset() + kCheckConstInterval; 1828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 1832