Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(39)

Unified Diff: src/arm/assembler-arm-inl.h

Issue 24714004: Thumb2 Backend: Update Code objects with mode, separate Assembler methods for Thumb2 Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/arm/assembler-thumb.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/arm/assembler-thumb.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698