📄 assembler-arm.cc.svn-base
字号:
// Copyright (c) 1994-2006 Sun Microsystems Inc.// All Rights Reserved.//// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions// are met://// - Redistributions of source code must retain the above copyright notice,// this list of conditions and the following disclaimer.//// - Redistribution in binary form must reproduce the above copyright// notice, this list of conditions and the following disclaimer in the// documentation and/or other materials provided with the// distribution.//// - Neither the name of Sun Microsystems or the names of contributors may// be used to endorse or promote products derived from this software without// specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED// OF THE POSSIBILITY OF SUCH DAMAGE.// The original source code covered by the above license above has been modified// significantly by Google Inc.// Copyright 2006-2008 the V8 project authors. All rights reserved.#include "v8.h"#include "assembler-arm-inl.h"#include "serialize.h"namespace v8 { namespace internal {// -----------------------------------------------------------------------------// Implementation of Register and CRegisterRegister no_reg = { -1 };Register r0 = { 0 };Register r1 = { 1 };Register r2 = { 2 };Register r3 = { 3 };Register r4 = { 4 };Register r5 = { 5 };Register r6 = { 6 };Register r7 = { 7 };Register r8 = { 8 };Register r9 = { 9 };Register r10 = { 10 };Register fp = { 11 };Register ip = { 12 };Register sp = { 13 };Register lr = { 14 };Register pc = { 15 };CRegister no_creg = { -1 };CRegister cr0 = { 0 };CRegister cr1 = { 1 };CRegister cr2 = { 2 };CRegister cr3 = { 3 };CRegister cr4 = { 4 };CRegister cr5 = { 5 };CRegister cr6 = { 6 };CRegister cr7 = { 7 };CRegister cr8 = { 8 };CRegister cr9 = { 9 };CRegister cr10 = { 10 };CRegister cr11 = { 11 };CRegister cr12 = { 12 };CRegister cr13 = { 13 };CRegister cr14 = { 14 };CRegister cr15 = { 15 };// In order to determine the pc store offset, we execute a small code sequence.// See ARM Architecture Reference Manual section A-2.4.3// Note that 'str pc, [sp]' and 'stmia sp, {pc}' were using different offsets// under the QEMU emulator (now fixed), so we are careful to test the actual// instruction we are interested in (stmia).int PcStoreOffset() {#if !defined(__arm__) // Building an ARM emulator based target. The emulator is wired for 8 byte // pc offsets as is the default in the spec. static int pc_store_offset = 8;#elif defined(__arm__) && !defined(__thumb__) // __arm__ may be defined in thumb mode. static int pc_store_offset = -1; asm volatile( "sub sp, sp, #4 \n\t" "sub r1, pc, #4 \n\t" "stmia sp, {pc} \n\t" "ldr r0, [sp] \n\t" "add sp, sp, #4 \n\t" "sub %0, r0, r1 \n\t" : "=r" (pc_store_offset) : : "r0", "r1", "memory");#elif defined(__thumb__) static int pc_store_offset = -1; asm volatile( "@ Enter ARM Mode \n\t" "adr r2, 1f \n\t" "bx r2 \n\t" ".ALIGN 4 \n\t" ".ARM \n" "1: sub sp, sp, #4 \n\t" "sub r1, pc, #4 \n\t" "stmia sp, {pc} \n\t" "ldr r0, [sp] \n\t" "add sp, sp, #4 \n\t" "sub %0, r0, r1 \n" "@ Enter THUMB Mode\n\t" "adr r2, 2f+1 \n\t" "bx r2 \n\t" ".THUMB \n" "2: \n\t" : "=r" (pc_store_offset) : : "r0", "r1", "r2", "memory");#else#error unsupported architecture#endif ASSERT(pc_store_offset == 8 || pc_store_offset == 12); return pc_store_offset;}// -----------------------------------------------------------------------------// Implementation of RelocInfoconst int RelocInfo::kApplyMask = 0;void RelocInfo::patch_code(byte* instructions, int instruction_count) { // Patch the code at the current address with the supplied instructions. UNIMPLEMENTED();}// Patch the code at the current PC with a call to the target address.// Additional guard int3 instructions can be added if required.void RelocInfo::patch_code_with_call(Address target, int guard_bytes) { // Patch the code at the current address with a call to the target. UNIMPLEMENTED();}// -----------------------------------------------------------------------------// Implementation of Operand and MemOperand// See assembler-arm-inl.h for inlined constructorsOperand::Operand(Handle<Object> handle) { rm_ = no_reg; // Verify all Objects referred by code are NOT in new space. Object* obj = *handle; ASSERT(!Heap::InNewSpace(obj)); if (obj->IsHeapObject()) { imm32_ = reinterpret_cast<intptr_t>(handle.location()); rmode_ = RelocInfo::EMBEDDED_OBJECT; } else { // no relocation needed imm32_ = reinterpret_cast<intptr_t>(obj); rmode_ = RelocInfo::NONE; }}Operand::Operand(Register rm, ShiftOp shift_op, int shift_imm) { ASSERT(is_uint5(shift_imm)); ASSERT(shift_op != ROR || shift_imm != 0); // use RRX if you mean it rm_ = rm; rs_ = no_reg; shift_op_ = shift_op; shift_imm_ = shift_imm & 31; if (shift_op == RRX) { // encoded as ROR with shift_imm == 0 ASSERT(shift_imm == 0); shift_op_ = ROR; shift_imm_ = 0; }}Operand::Operand(Register rm, ShiftOp shift_op, Register rs) { ASSERT(shift_op != RRX); rm_ = rm; rs_ = no_reg; shift_op_ = shift_op; rs_ = rs;}MemOperand::MemOperand(Register rn, int32_t offset, AddrMode am) { rn_ = rn; rm_ = no_reg; offset_ = offset; am_ = am;}MemOperand::MemOperand(Register rn, Register rm, AddrMode am) { rn_ = rn; rm_ = rm; shift_op_ = LSL; shift_imm_ = 0; am_ = am;}MemOperand::MemOperand(Register rn, Register rm, ShiftOp shift_op, int shift_imm, AddrMode am) { ASSERT(is_uint5(shift_imm)); rn_ = rn; rm_ = rm; shift_op_ = shift_op; shift_imm_ = shift_imm & 31; am_ = am;}// -----------------------------------------------------------------------------// Implementation of Assembler// Instruction encoding bitsenum { H = 1 << 5, // halfword (or byte) S6 = 1 << 6, // signed (or unsigned) L = 1 << 20, // load (or store) S = 1 << 20, // set condition code (or leave unchanged) W = 1 << 21, // writeback base register (or leave unchanged) A = 1 << 21, // accumulate in multiply instruction (or not) B = 1 << 22, // unsigned byte (or word) N = 1 << 22, // long (or short) U = 1 << 23, // positive (or negative) offset/index P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing) I = 1 << 25, // immediate shifter operand (or not) B4 = 1 << 4, B5 = 1 << 5, B7 = 1 << 7, B8 = 1 << 8, B12 = 1 << 12, B16 = 1 << 16, B20 = 1 << 20, B21 = 1 << 21, B22 = 1 << 22, B23 = 1 << 23, B24 = 1 << 24, B25 = 1 << 25, B26 = 1 << 26, B27 = 1 << 27, // Instruction bit masks RdMask = 15 << 12, // in str instruction CondMask = 15 << 28, OpCodeMask = 15 << 21, // in data-processing instructions Imm24Mask = (1 << 24) - 1, Off12Mask = (1 << 12) - 1, // Reserved condition nv = 15 << 28};// add(sp, sp, 4) instruction (aka Pop())static const Instr kPopInstruction = al | 4 * B21 | 4 | LeaveCC | I | sp.code() * B16 | sp.code() * B12;// str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r))// register r is not encoded.static const Instr kPushRegPattern = al | B26 | 4 | NegPreIndex | sp.code() * B16;// ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r))// register r is not encoded.static const Instr kPopRegPattern = al | B26 | L | 4 | PostIndex | sp.code() * B16;// spare_buffer_static const int kMinimalBufferSize = 4*KB;static byte* spare_buffer_ = NULL;Assembler::Assembler(void* buffer, int buffer_size) { if (buffer == NULL) { // do our own buffer management if (buffer_size <= kMinimalBufferSize) { buffer_size = kMinimalBufferSize; if (spare_buffer_ != NULL) { buffer = spare_buffer_; spare_buffer_ = NULL; } } if (buffer == NULL) { buffer_ = NewArray<byte>(buffer_size); } else { buffer_ = static_cast<byte*>(buffer); } buffer_size_ = buffer_size; own_buffer_ = true; } else { // use externally provided buffer instead ASSERT(buffer_size > 0); buffer_ = static_cast<byte*>(buffer); buffer_size_ = buffer_size; own_buffer_ = false; } // setup buffer pointers ASSERT(buffer_ != NULL); pc_ = buffer_; reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); num_prinfo_ = 0; next_buffer_check_ = 0; no_const_pool_before_ = 0; last_const_pool_end_ = 0; last_bound_pos_ = 0; last_position_ = RelocInfo::kNoPosition; last_position_is_statement_ = false;}Assembler::~Assembler() { if (own_buffer_) { if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { spare_buffer_ = buffer_; } else { DeleteArray(buffer_); } }}void Assembler::GetCode(CodeDesc* desc) { // finalize code if (unbound_label_.is_linked()) bind_to(&unbound_label_, binding_pos_); // emit constant pool if necessary CheckConstPool(true, false); ASSERT(num_prinfo_ == 0); // setup desc desc->buffer = buffer_; desc->buffer_size = buffer_size_; desc->instr_size = pc_offset(); desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();}void Assembler::Align(int m) { ASSERT(m >= 4 && IsPowerOf2(m)); while ((pc_offset() & (m - 1)) != 0) { nop(); }}// Labels refer to positions in the (to be) generated code.// There are bound, linked, and unused labels.//// Bound labels refer to known positions in the already// generated code. pos() is the position the label refers to.//// Linked labels refer to unknown positions in the code// to be generated; pos() is the position of the last// instruction using the label.// The link chain is terminated by a negative code position (must be aligned)const int kEndOfChain = -4;int Assembler::target_at(int pos) { Instr instr = instr_at(pos); ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 int imm26 = ((instr & Imm24Mask) << 8) >> 6; if ((instr & CondMask) == nv && (instr & B24) != 0) // blx uses bit 24 to encode bit 2 of imm26 imm26 += 2; return pos + 8 + imm26;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -