📄 assembler-arm.cc.svn-base
字号:
void Assembler::swi(uint32_t imm24, Condition cond) { ASSERT(is_uint24(imm24)); emit(cond | 15*B24 | imm24);}// Coprocessor instructionsvoid Assembler::cdp(Coprocessor coproc, int opcode_1, CRegister crd, CRegister crn, CRegister crm, int opcode_2, Condition cond) { ASSERT(is_uint4(opcode_1) && is_uint3(opcode_2)); emit(cond | B27 | B26 | B25 | (opcode_1 & 15)*B20 | crn.code()*B16 | crd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | crm.code());}void Assembler::cdp2(Coprocessor coproc, int opcode_1, CRegister crd, CRegister crn, CRegister crm, int opcode_2) { // v5 and above cdp(coproc, opcode_1, crd, crn, crm, opcode_2, static_cast<Condition>(nv));}void Assembler::mcr(Coprocessor coproc, int opcode_1, Register rd, CRegister crn, CRegister crm, int opcode_2, Condition cond) { ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2)); emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | crn.code()*B16 | rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());}void Assembler::mcr2(Coprocessor coproc, int opcode_1, Register rd, CRegister crn, CRegister crm, int opcode_2) { // v5 and above mcr(coproc, opcode_1, rd, crn, crm, opcode_2, static_cast<Condition>(nv));}void Assembler::mrc(Coprocessor coproc, int opcode_1, Register rd, CRegister crn, CRegister crm, int opcode_2, Condition cond) { ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2)); emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | L | crn.code()*B16 | rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());}void Assembler::mrc2(Coprocessor coproc, int opcode_1, Register rd, CRegister crn, CRegister crm, int opcode_2) { // v5 and above mrc(coproc, opcode_1, rd, crn, crm, opcode_2, static_cast<Condition>(nv));}void Assembler::ldc(Coprocessor coproc, CRegister crd, const MemOperand& src, LFlag l, Condition cond) { addrmod5(cond | B27 | B26 | l | L | coproc*B8, crd, src);}void Assembler::ldc(Coprocessor coproc, CRegister crd, Register rn, int option, LFlag l, Condition cond) { // unindexed addressing ASSERT(is_uint8(option)); emit(cond | B27 | B26 | U | l | L | rn.code()*B16 | crd.code()*B12 | coproc*B8 | (option & 255));}void Assembler::ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src, LFlag l) { // v5 and above ldc(coproc, crd, src, l, static_cast<Condition>(nv));}void Assembler::ldc2(Coprocessor coproc, CRegister crd, Register rn, int option, LFlag l) { // v5 and above ldc(coproc, crd, rn, option, l, static_cast<Condition>(nv));}void Assembler::stc(Coprocessor coproc, CRegister crd, const MemOperand& dst, LFlag l, Condition cond) { addrmod5(cond | B27 | B26 | l | coproc*B8, crd, dst);}void Assembler::stc(Coprocessor coproc, CRegister crd, Register rn, int option, LFlag l, Condition cond) { // unindexed addressing ASSERT(is_uint8(option)); emit(cond | B27 | B26 | U | l | rn.code()*B16 | crd.code()*B12 | coproc*B8 | (option & 255));}void Assembler::stc2(Coprocessor coproc, CRegister crd, const MemOperand& dst, LFlag l) { // v5 and above stc(coproc, crd, dst, l, static_cast<Condition>(nv));}void Assembler::stc2(Coprocessor coproc, CRegister crd, Register rn, int option, LFlag l) { // v5 and above stc(coproc, crd, rn, option, l, static_cast<Condition>(nv));}// Pseudo instructionsvoid Assembler::lea(Register dst, const MemOperand& x, SBit s, Condition cond) { int am = x.am_; if (!x.rm_.is_valid()) { // immediate offset if ((am & P) == 0) // post indexing mov(dst, Operand(x.rn_), s, cond); else if ((am & U) == 0) // negative indexing sub(dst, x.rn_, Operand(x.offset_), s, cond); else add(dst, x.rn_, Operand(x.offset_), s, cond); } else { // Register offset (shift_imm_ and shift_op_ are 0) or scaled // register offset the constructors make sure than both shift_imm_ // and shift_op_ are initialized. ASSERT(!x.rm_.is(pc)); if ((am & P) == 0) // post indexing mov(dst, Operand(x.rn_), s, cond); else if ((am & U) == 0) // negative indexing sub(dst, x.rn_, Operand(x.rm_, x.shift_op_, x.shift_imm_), s, cond); else add(dst, x.rn_, Operand(x.rm_, x.shift_op_, x.shift_imm_), s, cond); }}// Debuggingvoid Assembler::RecordComment(const char* msg) { if (FLAG_debug_code) { CheckBuffer(); RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg)); }}void Assembler::RecordPosition(int pos) { if (pos == RelocInfo::kNoPosition) return; ASSERT(pos >= 0); if (pos == last_position_) return; CheckBuffer(); RecordRelocInfo(RelocInfo::POSITION, pos); last_position_ = pos; last_position_is_statement_ = false;}void Assembler::RecordStatementPosition(int pos) { if (pos == last_position_) return; CheckBuffer(); RecordRelocInfo(RelocInfo::STATEMENT_POSITION, pos); last_position_ = pos; last_position_is_statement_ = true;}void Assembler::GrowBuffer() { if (!own_buffer_) FATAL("external code buffer is too small"); // compute new buffer size CodeDesc desc; // the new buffer if (buffer_size_ < 4*KB) { desc.buffer_size = 4*KB; } else if (buffer_size_ < 1*MB) { desc.buffer_size = 2*buffer_size_; } else { desc.buffer_size = buffer_size_ + 1*MB; } CHECK_GT(desc.buffer_size, 0); // no overflow // setup new buffer desc.buffer = NewArray<byte>(desc.buffer_size); desc.instr_size = pc_offset(); desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); // copy the data int pc_delta = desc.buffer - buffer_; int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_); memmove(desc.buffer, buffer_, desc.instr_size); memmove(reloc_info_writer.pos() + rc_delta, reloc_info_writer.pos(), desc.reloc_size); // switch buffers DeleteArray(buffer_); buffer_ = desc.buffer; buffer_size_ = desc.buffer_size; pc_ += pc_delta; reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, reloc_info_writer.last_pc() + pc_delta); // none of our relocation types are pc relative pointing outside the code // buffer nor pc absolute pointing inside the code buffer, so there is no need // to relocate any emitted relocation entries // relocate pending relocation entries for (int i = 0; i < num_prinfo_; i++) { RelocInfo& rinfo = prinfo_[i]; ASSERT(rinfo.rmode() != RelocInfo::COMMENT && rinfo.rmode() != RelocInfo::POSITION); rinfo.set_pc(rinfo.pc() + pc_delta); }}void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { RelocInfo rinfo(pc_, rmode, data); // we do not try to reuse pool constants if (rmode >= RelocInfo::COMMENT && rmode <= RelocInfo::STATEMENT_POSITION) { // adjust code for new modes ASSERT(RelocInfo::IsComment(rmode) || RelocInfo::IsPosition(rmode)); // these modes do not need an entry in the constant pool } else { ASSERT(num_prinfo_ < kMaxNumPRInfo); prinfo_[num_prinfo_++] = rinfo; // Make sure the constant pool is not emitted in place of the next // instruction for which we just recorded relocation info BlockConstPoolBefore(pc_offset() + kInstrSize); } if (rinfo.rmode() != RelocInfo::NONE) { // Don't record external references unless the heap will be serialized. if (rmode == RelocInfo::EXTERNAL_REFERENCE && !Serializer::enabled() && !FLAG_debug_code) { return; } ASSERT(buffer_space() >= kMaxRelocSize); // too late to grow buffer here reloc_info_writer.Write(&rinfo); }}void Assembler::CheckConstPool(bool force_emit, bool require_jump) { // Calculate the offset of the next check. It will be overwritten // when a const pool is generated or when const pools are being // blocked for a specific range. next_buffer_check_ = pc_offset() + kCheckConstInterval; // There is nothing to do if there are no pending relocation info entries if (num_prinfo_ == 0) return; // We emit a constant pool at regular intervals of about kDistBetweenPools // or when requested by parameter force_emit (e.g. after each function). // We prefer not to emit a jump unless the max distance is reached or if we // are running low on slots, which can happen if a lot of constants are being // emitted (e.g. --debug-code and many static references). int dist = pc_offset() - last_const_pool_end_; if (!force_emit && dist < kMaxDistBetweenPools && (require_jump || dist < kDistBetweenPools) && // TODO(1236125): Cleanup the "magic" number below. We know that // the code generation will test every kCheckConstIntervalInst. // Thus we are safe as long as we generate less than 7 constant // entries per instruction. (num_prinfo_ < (kMaxNumPRInfo - (7 * kCheckConstIntervalInst)))) { return; } // If we did not return by now, we need to emit the constant pool soon. // However, some small sequences of instructions must not be broken up by the // insertion of a constant pool; such sequences are protected by setting // no_const_pool_before_, which is checked here. Also, recursive calls to // CheckConstPool are blocked by no_const_pool_before_. if (pc_offset() < no_const_pool_before_) { // Emission is currently blocked; make sure we try again as soon as possible next_buffer_check_ = no_const_pool_before_; // Something is wrong if emission is forced and blocked at the same time ASSERT(!force_emit); return; } int jump_instr = require_jump ? kInstrSize : 0; // Check that the code buffer is large enough before emitting the constant // pool and relocation information (include the jump over the pool and the // constant pool marker). int max_needed_space = jump_instr + kInstrSize + num_prinfo_*(kInstrSize + kMaxRelocSize); while (buffer_space() <= (max_needed_space + kGap)) GrowBuffer(); // Block recursive calls to CheckConstPool BlockConstPoolBefore(pc_offset() + jump_instr + kInstrSize + num_prinfo_*kInstrSize); // Don't bother to check for the emit calls below. next_buffer_check_ = no_const_pool_before_; // Emit jump over constant pool if necessary Label after_pool; if (require_jump) b(&after_pool); RecordComment("[ Constant Pool"); // Put down constant pool marker // "Undefined instruction" as specified by A3.1 Instruction set encoding emit(0x03000000 | num_prinfo_); // Emit constant pool entries for (int i = 0; i < num_prinfo_; i++) { RelocInfo& rinfo = prinfo_[i]; ASSERT(rinfo.rmode() != RelocInfo::COMMENT && rinfo.rmode() != RelocInfo::POSITION && rinfo.rmode() != RelocInfo::STATEMENT_POSITION); Instr instr = instr_at(rinfo.pc()); // Instruction to patch must be a ldr/str [pc, #offset] // P and U set, B and W clear, Rn == pc, offset12 still 0 ASSERT((instr & (7*B25 | P | U | B | W | 15*B16 | Off12Mask)) == (2*B25 | P | U | pc.code()*B16)); int delta = pc_ - rinfo.pc() - 8; ASSERT(delta >= -4); // instr could be ldr pc, [pc, #-4] followed by targ32 if (delta < 0) { instr &= ~U; delta = -delta; } ASSERT(is_uint12(delta)); instr_at_put(rinfo.pc(), instr + delta); emit(rinfo.data()); } num_prinfo_ = 0; last_const_pool_end_ = pc_offset(); RecordComment("]"); if (after_pool.is_linked()) { bind(&after_pool); } // Since a constant pool was just emitted, move the check offset forward by // the standard interval. next_buffer_check_ = pc_offset() + kCheckConstInterval;}} } // namespace v8::internal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -