| Index: src/arm/assembler-arm-inl.h
|
| diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h
|
| index 41287e64d9f2c9a85031a978f0349ce6bb86ad1f..84fcf289e58c9a2fa2c4edebb44a38a800c1ab4e 100644
|
| --- a/src/arm/assembler-arm-inl.h
|
| +++ b/src/arm/assembler-arm-inl.h
|
| @@ -155,7 +155,9 @@ void RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) {
|
| host() != NULL &&
|
| target->IsHeapObject()) {
|
| host()->GetHeap()->incremental_marking()->RecordWrite(
|
| - host(), &Memory::Object_at(pc_), HeapObject::cast(target));
|
| + host(),
|
| + &Memory::Object_at(Assembler::UntagAddress(pc_)),
|
| + HeapObject::cast(target));
|
| }
|
| }
|
|
|
| @@ -380,6 +382,10 @@ void Assembler::CheckBuffer() {
|
|
|
|
|
| void Assembler::emit(Instr x) {
|
| + if (is_thumb_mode()) {
|
| + emit32(x);
|
| + return;
|
| + }
|
| CheckBuffer();
|
| *reinterpret_cast<Instr*>(pc_) = x;
|
| pc_ += kInstrSize;
|
| @@ -403,6 +409,10 @@ void Assembler::emit32(Instr x) {
|
|
|
|
|
| Address Assembler::target_pointer_address_at(Address pc) {
|
| + if (IsThumbAddress(pc)) {
|
| + return thumb_target_pointer_address_at(UntagAddress(pc));
|
| + }
|
| +
|
| Address target_pc = pc;
|
| Instr instr = Memory::int32_at(target_pc);
|
| // If we have a bx instruction, the instruction before the bx is
|
| @@ -430,6 +440,9 @@ Address Assembler::target_pointer_address_at(Address pc) {
|
|
|
|
|
| Address Assembler::target_pointer_at(Address pc) {
|
| + if (IsThumbAddress(pc)) {
|
| + return thumb_target_pointer_at(UntagAddress(pc));
|
| + }
|
| if (IsMovW(Memory::int32_at(pc))) {
|
| ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize)));
|
| Instruction* instr = Instruction::At(pc);
|
| @@ -458,6 +471,17 @@ Address Assembler::target_address_from_return_address(Address pc) {
|
| Instr candidate_instr(Memory::int32_at(candidate));
|
| if (IsLdrPcImmediateOffset(candidate_instr)) {
|
| return candidate;
|
| + } else {
|
| + candidate = pc - Assembler::kInstrSize - Assembler::kInstr16Size - 1;
|
| + if (IsThumbLdrPcImmediateOffset(thumb32_instr_at(candidate))) {
|
| + return candidate + 1;
|
| + } else {
|
| + candidate = pc - 2 * Assembler::kInstrSize - Assembler::kInstr16Size - 1;
|
| + if (IsMovWThumb(thumb32_instr_at(candidate))) {
|
| + ASSERT(IsMovTThumb(thumb32_instr_at(candidate + kInstrSize)));
|
| + return candidate + 1;
|
| + }
|
| + }
|
| }
|
| candidate = pc - 3 * Assembler::kInstrSize;
|
| ASSERT(IsMovW(Memory::int32_at(candidate)) &&
|
| @@ -467,6 +491,16 @@ Address Assembler::target_address_from_return_address(Address pc) {
|
|
|
|
|
| Address Assembler::return_address_from_call_start(Address pc) {
|
| + if (IsThumbAddress(pc)) {
|
| + pc = UntagAddress(pc);
|
| + Instr instr = thumb32_instr_at(pc);
|
| + if (IsThumbLdrPcImmediateOffset(instr)) {
|
| + return pc + kInstrSize + kInstr16Size;
|
| + }
|
| + ASSERT(IsMovWThumb(instr));
|
| + ASSERT(IsMovTThumb(thumb32_instr_at(pc + kInstrSize)));
|
| + return pc + kInstrSize * 2 + kInstr16Size;
|
| + }
|
| if (IsLdrPcImmediateOffset(Memory::int32_at(pc))) {
|
| return pc + kInstrSize * 2;
|
| } else {
|
| @@ -496,6 +530,10 @@ static Instr EncodeMovwImmediate(uint32_t immediate) {
|
|
|
|
|
| void Assembler::set_target_pointer_at(Address pc, Address target) {
|
| + if (IsThumbAddress(pc)) {
|
| + thumb_set_target_pointer_at(UntagAddress(pc), target);
|
| + return;
|
| + }
|
| if (IsMovW(Memory::int32_at(pc))) {
|
| ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize)));
|
| uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc);
|
| @@ -542,6 +580,76 @@ void Assembler::emit_it(Condition cond) {
|
| }
|
| }
|
|
|
| +
|
| +Address Assembler::AlignAddress(Address addr) {
|
| + return (Address)((uint32_t)addr &(~3));
|
| +}
|
| +
|
| +
|
| +Address Assembler::UntagAddress(Address addr) {
|
| + return (Address)((uint32_t)addr & (~1));
|
| +}
|
| +
|
| +
|
| +bool Assembler::IsThumbAddress(Address addr) {
|
| + return (((uint32_t)addr) & 1) == 1;
|
| +}
|
| +
|
| +
|
| +Address Assembler::thumb_target_pointer_at(Address pc) {
|
| + Instr instr = thumb32_instr_at(pc);
|
| + if (IsMovWThumb(instr)) {
|
| + Instr next_instr = thumb32_instr_at(pc + kInstrSize);
|
| + ASSERT(IsMovTThumb(next_instr));
|
| + return reinterpret_cast<Address>(
|
| + (thumb32_movw_immediate(next_instr) << 16) |
|
| + thumb32_movw_immediate(instr));
|
| + }
|
| + return Memory::Address_at(thumb_target_pointer_address_at(pc));
|
| +}
|
| +
|
| +
|
| +Address Assembler::thumb_target_pointer_address_at(Address pc) {
|
| + // We must have a load from the constant pool. The address in the constant
|
| + // pool is what needs to be patched.
|
| + Instr instr = thumb32_instr_at(pc);
|
| + ASSERT(IsThumbLdrPcImmediateOffset(instr));
|
| + pc = AlignAddress(pc);
|
| +
|
| + int offset = instr & 0xfff; // offset_12 is unsigned
|
| + if ((instr & (1 << 23)) == 0) offset = -offset; // U bit defines offset sign
|
| + // Verify that the constant pool comes after the instruction referencing it.
|
| + ASSERT(offset >= -4);
|
| + return pc + offset + kThumbPcLoadDelta;
|
| +}
|
| +
|
| +
|
| +void Assembler::thumb_set_target_pointer_at(Address pc,
|
| + Address target,
|
| + Code* host) {
|
| + Instr instr = thumb32_instr_at(pc);
|
| + uint32_t immediate = reinterpret_cast<uint32_t>(target);
|
| + if (IsMovWThumb(instr)) {
|
| + Instr next_instr = thumb32_instr_at(pc + kInstrSize);
|
| + ASSERT(IsMovTThumb(next_instr));
|
| + uint16_t* instr_ptr = reinterpret_cast<uint16_t*>(pc);
|
| + uint32_t immediate_mask = thumb32_set_movw_immediate(0xFFFF);
|
| + instr &= ~immediate_mask;
|
| + instr |= thumb32_set_movw_immediate(immediate & 0xFFFF);
|
| + next_instr &= ~immediate_mask;
|
| + next_instr |= thumb32_set_movw_immediate(immediate >> 16);
|
| + instr_ptr[0] = instr >> 16;
|
| + instr_ptr[1] = instr & 0xFFFF;
|
| + instr_ptr[2] = next_instr >> 16;
|
| + instr_ptr[3] = next_instr & 0xFFFF;
|
| + CPU::FlushICache(pc, 2 * kInstrSize);
|
| + return;
|
| + } else if (IsThumbLdrPcImmediateOffset(instr)) {
|
| + Memory::Address_at(thumb_target_pointer_address_at(pc)) = target;
|
| + return;
|
| + }
|
| +}
|
| +
|
| } } // namespace v8::internal
|
|
|
| #endif // V8_ARM_ASSEMBLER_ARM_INL_H_
|
|
|