📄 assembler-arm.h.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.// A light-weight ARM Assembler// Generates user mode instructions for the ARM architecture up to version 5#ifndef V8_ASSEMBLER_ARM_H_#define V8_ASSEMBLER_ARM_H_#include "assembler.h"namespace v8 { namespace internal {// CPU Registers.//// 1) We would prefer to use an enum, but enum values are assignment-// compatible with int, which has caused code-generation bugs.//// 2) We would prefer to use a class instead of a struct but we don't like// the register initialization to depend on the particular initialization// order (which appears to be different on OS X, Linux, and Windows for the// installed versions of C++ we tried). Using a struct permits C-style// "initialization". Also, the Register objects cannot be const as this// forces initialization stubs in MSVC, making us dependent on initialization// order.//// 3) By not using an enum, we are possibly preventing the compiler from// doing certain constant folds, which may significantly reduce the// code generated for some assembly instructions (because they boil down// to a few constants). If this is a problem, we could change the code// such that we use an enum in optimized mode, and the struct in debug// mode. This way we get the compile-time error checking in debug mode// and best performance in optimized code.//// Core registerstruct Register { bool is_valid() const { return 0 <= code_ && code_ < 16; } bool is(Register reg) const { return code_ == reg.code_; } int code() const { ASSERT(is_valid()); return code_; } int bit() const { ASSERT(is_valid()); return 1 << code_; } // (unfortunately we can't make this private in a struct) int code_;};extern Register no_reg;extern Register r0;extern Register r1;extern Register r2;extern Register r3;extern Register r4;extern Register r5;extern Register r6;extern Register r7;extern Register r8;extern Register r9;extern Register r10;extern Register fp;extern Register ip;extern Register sp;extern Register lr;extern Register pc;// Coprocessor registerstruct CRegister { bool is_valid() const { return 0 <= code_ && code_ < 16; } bool is(CRegister creg) const { return code_ == creg.code_; } int code() const { ASSERT(is_valid()); return code_; } int bit() const { ASSERT(is_valid()); return 1 << code_; } // (unfortunately we can't make this private in a struct) int code_;};extern CRegister no_creg;extern CRegister cr0;extern CRegister cr1;extern CRegister cr2;extern CRegister cr3;extern CRegister cr4;extern CRegister cr5;extern CRegister cr6;extern CRegister cr7;extern CRegister cr8;extern CRegister cr9;extern CRegister cr10;extern CRegister cr11;extern CRegister cr12;extern CRegister cr13;extern CRegister cr14;extern CRegister cr15;// Coprocessor numberenum Coprocessor { p0 = 0, p1 = 1, p2 = 2, p3 = 3, p4 = 4, p5 = 5, p6 = 6, p7 = 7, p8 = 8, p9 = 9, p10 = 10, p11 = 11, p12 = 12, p13 = 13, p14 = 14, p15 = 15};// Condition field in instructionsenum Condition { eq = 0 << 28, ne = 1 << 28, cs = 2 << 28, hs = 2 << 28, cc = 3 << 28, lo = 3 << 28, mi = 4 << 28, pl = 5 << 28, vs = 6 << 28, vc = 7 << 28, hi = 8 << 28, ls = 9 << 28, ge = 10 << 28, lt = 11 << 28, gt = 12 << 28, le = 13 << 28, al = 14 << 28};// Returns the equivalent of !cc.INLINE(Condition NegateCondition(Condition cc));// Corresponds to transposing the operands of a comparison.inline Condition ReverseCondition(Condition cc) { switch (cc) { case lo: return hi; case hi: return lo; case hs: return ls; case ls: return hs; case lt: return gt; case gt: return lt; case ge: return le; case le: return ge; default: return cc; };}// The pc store offset may be 8 or 12 depending on the processor implementation.int PcStoreOffset();// -----------------------------------------------------------------------------// Addressing modes and instruction variants// Shifter operand shift operationenum ShiftOp { LSL = 0 << 5, LSR = 1 << 5, ASR = 2 << 5, ROR = 3 << 5, RRX = -1};// Condition code updating modeenum SBit { SetCC = 1 << 20, // set condition code LeaveCC = 0 << 20 // leave condition code unchanged};// Status register selectionenum SRegister { CPSR = 0 << 22, SPSR = 1 << 22};// Status register fieldsenum SRegisterField { CPSR_c = CPSR | 1 << 16, CPSR_x = CPSR | 1 << 17, CPSR_s = CPSR | 1 << 18, CPSR_f = CPSR | 1 << 19, SPSR_c = SPSR | 1 << 16, SPSR_x = SPSR | 1 << 17, SPSR_s = SPSR | 1 << 18, SPSR_f = SPSR | 1 << 19};// Status register field mask (or'ed SRegisterField enum values)typedef uint32_t SRegisterFieldMask;// Memory operand addressing modeenum AddrMode { // bit encoding P U W Offset = (8|4|0) << 21, // offset (without writeback to base) PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback NegOffset = (8|0|0) << 21, // negative offset (without writeback to base) NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback};// Load/store multiple addressing modeenum BlockAddrMode { // bit encoding P U W da = (0|0|0) << 21, // decrement after ia = (0|4|0) << 21, // increment after db = (8|0|0) << 21, // decrement before ib = (8|4|0) << 21, // increment before da_w = (0|0|1) << 21, // decrement after with writeback to base ia_w = (0|4|1) << 21, // increment after with writeback to base db_w = (8|0|1) << 21, // decrement before with writeback to base ib_w = (8|4|1) << 21 // increment before with writeback to base};// Coprocessor load/store operand sizeenum LFlag { Long = 1 << 22, // long load/store coprocessor Short = 0 << 22 // short load/store coprocessor};// -----------------------------------------------------------------------------// Machine instruction Operands// Class Operand represents a shifter operand in data processing instructionsclass Operand BASE_EMBEDDED { public: // immediate INLINE(explicit Operand(int32_t immediate, RelocInfo::Mode rmode = RelocInfo::NONE)); INLINE(explicit Operand(const ExternalReference& f)); INLINE(explicit Operand(const char* s)); INLINE(explicit Operand(Object** opp)); INLINE(explicit Operand(Context** cpp)); explicit Operand(Handle<Object> handle); INLINE(explicit Operand(Smi* value)); // rm INLINE(explicit Operand(Register rm)); // rm <shift_op> shift_imm explicit Operand(Register rm, ShiftOp shift_op, int shift_imm); // rm <shift_op> rs explicit Operand(Register rm, ShiftOp shift_op, Register rs); // Return true if this is a register operand. INLINE(bool is_reg() const); Register rm() const { return rm_; } private: Register rm_; Register rs_; ShiftOp shift_op_; int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg int32_t imm32_; // valid if rm_ == no_reg RelocInfo::Mode rmode_; friend class Assembler;};// Class MemOperand represents a memory operand in load and store instructionsclass MemOperand BASE_EMBEDDED { public: // [rn +/- offset] Offset/NegOffset // [rn +/- offset]! PreIndex/NegPreIndex // [rn], +/- offset PostIndex/NegPostIndex // offset is any signed 32-bit value; offset is first loaded to register ip if // it does not fit the addressing mode (12-bit unsigned and sign bit) explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset); // [rn +/- rm] Offset/NegOffset // [rn +/- rm]! PreIndex/NegPreIndex // [rn], +/- rm PostIndex/NegPostIndex explicit MemOperand(Register rn, Register rm, AddrMode am = Offset); // [rn +/- rm <shift_op> shift_imm] Offset/NegOffset // [rn +/- rm <shift_op> shift_imm]! PreIndex/NegPreIndex // [rn], +/- rm <shift_op> shift_imm PostIndex/NegPostIndex explicit MemOperand(Register rn, Register rm, ShiftOp shift_op, int shift_imm, AddrMode am = Offset); private: Register rn_; // base Register rm_; // register offset int32_t offset_; // valid if rm_ == no_reg ShiftOp shift_op_; int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg AddrMode am_; // bits P, U, and W friend class Assembler;};typedef int32_t Instr;class Assembler : public Malloced { public: // Create an assembler. Instructions and relocation information are emitted // into a buffer, with the instructions starting from the beginning and the // relocation information starting from the end of the buffer. See CodeDesc // for a detailed comment on the layout (globals.h). // // If the provided buffer is NULL, the assembler allocates and grows its own // buffer, and buffer_size determines the initial buffer size. The buffer is // owned by the assembler and deallocated upon destruction of the assembler. // // If the provided buffer is not NULL, the assembler uses the provided buffer // for code generation and assumes its size to be buffer_size. If the buffer // is too small, a fatal error occurs. No deallocation of the buffer is done // upon destruction of the assembler. Assembler(void* buffer, int buffer_size); ~Assembler(); // GetCode emits any pending (non-emitted) code and fills the descriptor // desc. GetCode() is idempotent; it returns the same result if no other // Assembler functions are invoked inbetween GetCode() calls. void GetCode(CodeDesc* desc); // Label operations & relative jumps (PPUM Appendix D)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -