📄 assembler-arm.h.svn-base
字号:
// // Takes a branch opcode (cc) and a label (L) and generates // either a backward branch or a forward branch and links it // to the label fixup chain. Usage: // // Label L; // unbound label // j(cc, &L); // forward branch to unbound label // bind(&L); // bind label to the current pc // j(cc, &L); // backward branch to bound label // bind(&L); // illegal: a label may be bound only once // // Note: The same Label can be used for forward and backward branches // but it may be bound only once. void bind(Label* L); // binds an unbound label L to the current code position // Returns the branch offset to the given label from the current code position // Links the label to the current position if it is still unbound // Manages the jump elimination optimization if the second parameter is true. int branch_offset(Label* L, bool jump_elimination_allowed); // Return the address in the constant pool of the code target address used by // the branch/call instruction at pc. INLINE(static Address target_address_address_at(Address pc)); // Read/Modify the code target address in the branch/call instruction at pc. INLINE(static Address target_address_at(Address pc)); INLINE(static void set_target_address_at(Address pc, Address target)); // Distance between the instruction referring to the address of the call // target (ldr pc, [target addr in const pool]) and the return address static const int kTargetAddrToReturnAddrDist = sizeof(Instr); // --------------------------------------------------------------------------- // Code generation // Insert the smallest number of nop instructions // possible to align the pc offset to a multiple // of m. m must be a power of 2 (>= 4). void Align(int m); // Branch instructions void b(int branch_offset, Condition cond = al); void bl(int branch_offset, Condition cond = al); void blx(int branch_offset); // v5 and above void blx(Register target, Condition cond = al); // v5 and above void bx(Register target, Condition cond = al); // v5 and above, plus v4t // Convenience branch instructions using labels void b(Label* L, Condition cond = al) { b(branch_offset(L, cond == al), cond); } void b(Condition cond, Label* L) { b(branch_offset(L, cond == al), cond); } void bl(Label* L, Condition cond = al) { bl(branch_offset(L, false), cond); } void bl(Condition cond, Label* L) { bl(branch_offset(L, false), cond); } void blx(Label* L) { blx(branch_offset(L, false)); } // v5 and above // Data-processing instructions void and_(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC, Condition cond = al); void eor(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC, Condition cond = al); void sub(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC, Condition cond = al); void sub(Register dst, Register src1, Register src2, SBit s = LeaveCC, Condition cond = al) { sub(dst, src1, Operand(src2), s, cond); } void rsb(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC, Condition cond = al); void add(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC, Condition cond = al); void adc(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC, Condition cond = al); void sbc(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC, Condition cond = al); void rsc(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC, Condition cond = al); void tst(Register src1, const Operand& src2, Condition cond = al); void tst(Register src1, Register src2, Condition cond = al) { tst(src1, Operand(src2), cond); } void teq(Register src1, const Operand& src2, Condition cond = al); void cmp(Register src1, const Operand& src2, Condition cond = al); void cmp(Register src1, Register src2, Condition cond = al) { cmp(src1, Operand(src2), cond); } void cmn(Register src1, const Operand& src2, Condition cond = al); void orr(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC, Condition cond = al); void orr(Register dst, Register src1, Register src2, SBit s = LeaveCC, Condition cond = al) { orr(dst, src1, Operand(src2), s, cond); } void mov(Register dst, const Operand& src, SBit s = LeaveCC, Condition cond = al); void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) { mov(dst, Operand(src), s, cond); } void bic(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC, Condition cond = al); void mvn(Register dst, const Operand& src, SBit s = LeaveCC, Condition cond = al); // Multiply instructions void mla(Register dst, Register src1, Register src2, Register srcA, SBit s = LeaveCC, Condition cond = al); void mul(Register dst, Register src1, Register src2, SBit s = LeaveCC, Condition cond = al); void smlal(Register dstL, Register dstH, Register src1, Register src2, SBit s = LeaveCC, Condition cond = al); void smull(Register dstL, Register dstH, Register src1, Register src2, SBit s = LeaveCC, Condition cond = al); void umlal(Register dstL, Register dstH, Register src1, Register src2, SBit s = LeaveCC, Condition cond = al); void umull(Register dstL, Register dstH, Register src1, Register src2, SBit s = LeaveCC, Condition cond = al); // Miscellaneous arithmetic instructions void clz(Register dst, Register src, Condition cond = al); // v5 and above // Status register access instructions void mrs(Register dst, SRegister s, Condition cond = al); void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al); // Load/Store instructions void ldr(Register dst, const MemOperand& src, Condition cond = al); void str(Register src, const MemOperand& dst, Condition cond = al); void ldrb(Register dst, const MemOperand& src, Condition cond = al); void strb(Register src, const MemOperand& dst, Condition cond = al); void ldrh(Register dst, const MemOperand& src, Condition cond = al); void strh(Register src, const MemOperand& dst, Condition cond = al); void ldrsb(Register dst, const MemOperand& src, Condition cond = al); void ldrsh(Register dst, const MemOperand& src, Condition cond = al); // Load/Store multiple instructions void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al); void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al); // Semaphore instructions void swp(Register dst, Register src, Register base, Condition cond = al); void swpb(Register dst, Register src, Register base, Condition cond = al); // Exception-generating instructions and debugging support void stop(const char* msg); void bkpt(uint32_t imm16); // v5 and above void swi(uint32_t imm24, Condition cond = al); // Coprocessor instructions void cdp(Coprocessor coproc, int opcode_1, CRegister crd, CRegister crn, CRegister crm, int opcode_2, Condition cond = al); void cdp2(Coprocessor coproc, int opcode_1, CRegister crd, CRegister crn, CRegister crm, int opcode_2); // v5 and above void mcr(Coprocessor coproc, int opcode_1, Register rd, CRegister crn, CRegister crm, int opcode_2 = 0, Condition cond = al); void mcr2(Coprocessor coproc, int opcode_1, Register rd, CRegister crn, CRegister crm, int opcode_2 = 0); // v5 and above void mrc(Coprocessor coproc, int opcode_1, Register rd, CRegister crn, CRegister crm, int opcode_2 = 0, Condition cond = al); void mrc2(Coprocessor coproc, int opcode_1, Register rd, CRegister crn, CRegister crm, int opcode_2 = 0); // v5 and above void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src, LFlag l = Short, Condition cond = al); void ldc(Coprocessor coproc, CRegister crd, Register base, int option, LFlag l = Short, Condition cond = al); void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src, LFlag l = Short); // v5 and above void ldc2(Coprocessor coproc, CRegister crd, Register base, int option, LFlag l = Short); // v5 and above void stc(Coprocessor coproc, CRegister crd, const MemOperand& dst, LFlag l = Short, Condition cond = al); void stc(Coprocessor coproc, CRegister crd, Register base, int option, LFlag l = Short, Condition cond = al); void stc2(Coprocessor coproc, CRegister crd, const MemOperand& dst, LFlag l = Short); // v5 and above void stc2(Coprocessor coproc, CRegister crd, Register base, int option, LFlag l = Short); // v5 and above // Pseudo instructions void nop() { mov(r0, Operand(r0)); } void push(Register src) { str(src, MemOperand(sp, 4, NegPreIndex), al); } void pop(Register dst) { ldr(dst, MemOperand(sp, 4, PostIndex), al); } void pop() { add(sp, sp, Operand(kPointerSize)); } // Load effective address of memory operand x into register dst void lea(Register dst, const MemOperand& x, SBit s = LeaveCC, Condition cond = al); // Jump unconditionally to given label. void jmp(Label* L) { b(L, al); } // Debugging // Record a comment relocation entry that can be used by a disassembler. // Use --debug_code to enable. void RecordComment(const char* msg); void RecordPosition(int pos); void RecordStatementPosition(int pos); int pc_offset() const { return pc_ - buffer_; } int last_position() const { return last_position_; } bool last_position_is_statement() const { return last_position_is_statement_; } // Temporary helper function. Used by codegen.cc. int last_statement_position() const { return last_position_; } protected: int buffer_space() const { return reloc_info_writer.pos() - pc_; } // Read/patch instructions Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); } void instr_at_put(byte* pc, Instr instr) { *reinterpret_cast<Instr*>(pc) = instr; } Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); } void instr_at_put(int pos, Instr instr) { *reinterpret_cast<Instr*>(buffer_ + pos) = instr; } // Decode branch instruction at pos and return branch target pos int target_at(int pos); // Patch branch instruction at pos to branch to given branch target pos void target_at_put(int pos, int target_pos); private: // Code buffer: // The buffer into which code and relocation info are generated. byte* buffer_; int buffer_size_; // True if the assembler owns the buffer, false if buffer is external. bool own_buffer_; // Buffer size and constant pool distance are checked together at regular // intervals of kBufferCheckInterval emitted bytes static const int kBufferCheckInterval = 1*KB/2; int next_buffer_check_; // pc offset of next buffer check // Code generation static const int kInstrSize = sizeof(Instr); // signed size // The relocation writer's position is at least kGap bytes below the end of // the generated instructions. This is so that multi-instruction sequences do // not have to check for overflow. The same is true for writes of large // relocation info entries. static const int kGap = 32; byte* pc_; // the program counter; moves forward // Constant pool generation // Pools are emitted in the instruction stream, preferably after unconditional // jumps or after returns from functions (in dead code locations). // If a long code sequence does not contain unconditional jumps, it is // necessary to emit the constant pool before the pool gets too far from the // location it is accessed from. In this case, we emit a jump over the emitted // constant pool. // Constants in the pool may be addresses of functions that gets relocated; // if so, a relocation info entry is associated to the constant pool entry. // Repeated checking whether the constant pool should be emitted is rather // expensive. By default we only check again once a number of instructions // has been generated. That also means that the sizing of the buffers is not // an exact science, and that we rely on some slop to not overrun buffers. static const int kCheckConstIntervalInst = 32; static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize; // Pools are emitted after function return and in dead code at (more or less) // regular intervals of kDistBetweenPools bytes static const int kDistBetweenPools = 1*KB; // Constants in pools are accessed via pc relative addressing, which can // reach +/-4KB thereby defining a maximum distance between the instruction // and the accessed constant. We satisfy this constraint by limiting the // distance between pools. static const int kMaxDistBetweenPools = 4*KB - 2*kBufferCheckInterval; // Emission of the constant pool may be blocked in some code sequences int no_const_pool_before_; // block emission before this pc offset // Keep track of the last emitted pool to guarantee a maximal distance int last_const_pool_end_; // pc offset following the last constant pool // Relocation info generation // Each relocation is encoded as a variable size value static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; RelocInfoWriter reloc_info_writer; // Relocation info records are also used during code generation as temporary // containers for constants and code target addresses until they are emitted // to the constant pool. These pending relocation info records are temporarily // stored in a separate buffer until a constant pool is emitted. // If every instruction in a long sequence is accessing the pool, we need one // pending relocation entry per instruction. static const int kMaxNumPRInfo = kMaxDistBetweenPools/kInstrSize; RelocInfo prinfo_[kMaxNumPRInfo]; // the buffer of pending relocation info int num_prinfo_; // number of pending reloc info entries in the buffer // Jump-to-jump elimination: // The last label to be bound to _binding_pos, if unbound. Label unbound_label_; // The position to which _unbound_label has to be bound, if present. int binding_pos_; // The position before which jumps cannot be eliminated. int last_bound_pos_; // source position information int last_position_; bool last_position_is_statement_; // Code emission inline void CheckBuffer(); void GrowBuffer(); inline void emit(Instr x); // Instruction generation void addrmod1(Instr instr, Register rn, Register rd, const Operand& x); void addrmod2(Instr instr, Register rd, const MemOperand& x); void addrmod3(Instr instr, Register rd, const MemOperand& x); void addrmod4(Instr instr, Register rn, RegList rl); void addrmod5(Instr instr, CRegister crd, const MemOperand& x); // Labels void print(Label* L); void bind_to(Label* L, int pos); void link_to(Label* L, Label* appendix); void next(Label* L); // Record reloc info for current pc_ void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); // Check if is time to emit a constant pool for pending reloc info entries void CheckConstPool(bool force_emit, bool require_jump); // Block the emission of the constant pool before pc_offset void BlockConstPoolBefore(int pc_offset) { if (no_const_pool_before_ < pc_offset) no_const_pool_before_ = pc_offset; }};} } // namespace v8::internal#endif // V8_ASSEMBLER_ARM_H_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -