| Index: src/arm/assembler-arm.cc
|
| diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
|
| index 33b61a3480321fcf083ccd0cd7aa1ca5c5056c8f..7a6155f2e8388fad1cfc6ec8e97ebd7a6f02871f 100644
|
| --- a/src/arm/assembler-arm.cc
|
| +++ b/src/arm/assembler-arm.cc
|
| @@ -228,7 +228,8 @@ const char* DwVfpRegister::AllocationIndexToString(int index) {
|
| // -----------------------------------------------------------------------------
|
| // Implementation of RelocInfo
|
|
|
| -const int RelocInfo::kApplyMask = 0;
|
| +// static
|
| +const int RelocInfo::kApplyMask = 1 << RelocInfo::INTERNAL_REFERENCE;
|
|
|
|
|
| bool RelocInfo::IsCodedSpecially() {
|
| @@ -796,14 +797,20 @@ int Assembler::target_at(int pos) {
|
| // Emitted link to a label, not part of a branch.
|
| return instr;
|
| }
|
| - DCHECK((instr & 7*B25) == 5*B25); // b, bl, or blx imm24
|
| - int imm26 = ((instr & kImm24Mask) << 8) >> 6;
|
| - if ((Instruction::ConditionField(instr) == kSpecialCondition) &&
|
| - ((instr & B24) != 0)) {
|
| - // blx uses bit 24 to encode bit 2 of imm26
|
| - imm26 += 2;
|
| + if ((instr & 7 * B25) == 5 * B25) {
|
| + int imm26 = ((instr & kImm24Mask) << 8) >> 6;
|
| + // b, bl, or blx imm24
|
| + if ((Instruction::ConditionField(instr) == kSpecialCondition) &&
|
| + ((instr & B24) != 0)) {
|
| + // blx uses bit 24 to encode bit 2 of imm26
|
| + imm26 += 2;
|
| + }
|
| + return pos + kPcLoadDelta + imm26;
|
| }
|
| - return pos + kPcLoadDelta + imm26;
|
| + // Internal reference to the label.
|
| + DCHECK_EQ(7 * B25 | 1 * B0, instr & (7 * B25 | 1 * B0));
|
| + int imm26 = (((instr >> 1) & kImm24Mask) << 8) >> 6;
|
| + return pos + imm26;
|
| }
|
|
|
|
|
| @@ -877,19 +884,25 @@ void Assembler::target_at_put(int pos, int target_pos) {
|
| }
|
| return;
|
| }
|
| - int imm26 = target_pos - (pos + kPcLoadDelta);
|
| - DCHECK((instr & 7*B25) == 5*B25); // b, bl, or blx imm24
|
| - if (Instruction::ConditionField(instr) == kSpecialCondition) {
|
| - // blx uses bit 24 to encode bit 2 of imm26
|
| - DCHECK((imm26 & 1) == 0);
|
| - instr = (instr & ~(B24 | kImm24Mask)) | ((imm26 & 2) >> 1)*B24;
|
| - } else {
|
| - DCHECK((imm26 & 3) == 0);
|
| - instr &= ~kImm24Mask;
|
| + if ((instr & 7 * B25) == 5 * B25) {
|
| + // b, bl, or blx imm24
|
| + int imm26 = target_pos - (pos + kPcLoadDelta);
|
| + if (Instruction::ConditionField(instr) == kSpecialCondition) {
|
| + // blx uses bit 24 to encode bit 2 of imm26
|
| + DCHECK((imm26 & 1) == 0);
|
| + instr = (instr & ~(B24 | kImm24Mask)) | ((imm26 & 2) >> 1) * B24;
|
| + } else {
|
| + DCHECK((imm26 & 3) == 0);
|
| + instr &= ~kImm24Mask;
|
| + }
|
| + int imm24 = imm26 >> 2;
|
| + DCHECK(is_int24(imm24));
|
| + instr_at_put(pos, instr | (imm24 & kImm24Mask));
|
| + return;
|
| }
|
| - int imm24 = imm26 >> 2;
|
| - DCHECK(is_int24(imm24));
|
| - instr_at_put(pos, instr | (imm24 & kImm24Mask));
|
| + // Patch internal reference to label.
|
| + DCHECK_EQ(7 * B25 | 1 * B0, instr & (7 * B25 | 1 * B0));
|
| + instr_at_put(pos, reinterpret_cast<Instr>(buffer_ + target_pos));
|
| }
|
|
|
|
|
| @@ -3426,9 +3439,16 @@ void Assembler::GrowBuffer() {
|
| 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 internal references.
|
| + for (RelocIterator it(desc); !it.done(); it.next()) {
|
| + if (it.rinfo()->rmode() == RelocInfo::INTERNAL_REFERENCE) {
|
| + // Don't patch unbound internal references (bit 0 set); those are still
|
| + // hooked up in the Label chain and will be automatically patched once
|
| + // the label is bound.
|
| + int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
|
| + if ((*p & 1 * B0) == 0) *p += pc_delta;
|
| + }
|
| + }
|
|
|
| // Relocate pending relocation entries.
|
| for (int i = 0; i < num_pending_32_bit_reloc_info_; i++) {
|
| @@ -3472,6 +3492,37 @@ void Assembler::dd(uint32_t data) {
|
| }
|
|
|
|
|
| +void Assembler::dd(Label* label) {
|
| + CheckBuffer();
|
| + RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
|
| + if (label->is_bound()) {
|
| + uint32_t data = reinterpret_cast<uint32_t>(buffer_ + label->pos());
|
| + DCHECK_EQ(0u, data & 1 * B0);
|
| + *reinterpret_cast<uint32_t*>(pc_) = data;
|
| + pc_ += sizeof(uint32_t);
|
| + } else {
|
| + int target_pos;
|
| + if (label->is_linked()) {
|
| + // Point to previous instruction that uses the link.
|
| + target_pos = label->pos();
|
| + } else {
|
| + // First entry of the link chain points to itself.
|
| + target_pos = pc_offset();
|
| + }
|
| + label->link_to(pc_offset());
|
| + // Encode internal reference to unbound label. We set the least significant
|
| + // bit to distinguish unbound internal references in GrowBuffer() below.
|
| + int imm26 = target_pos - pc_offset();
|
| + DCHECK_EQ(0, imm26 & 3);
|
| + int imm24 = imm26 >> 2;
|
| + DCHECK(is_int24(imm24));
|
| + // We use bit pattern 0000111<imm24>1 because that doesn't match any branch
|
| + // or load that would also appear on the label chain.
|
| + emit(7 * B25 | ((imm24 & kImm24Mask) << 1) | 1 * B0);
|
| + }
|
| +}
|
| +
|
| +
|
| void Assembler::emit_code_stub_address(Code* stub) {
|
| CheckBuffer();
|
| *reinterpret_cast<uint32_t*>(pc_) =
|
|
|