| Index: src/arm/assembler-thumb2-inl.h
|
| ===================================================================
|
| --- src/arm/assembler-thumb2-inl.h (revision 3826)
|
| +++ src/arm/assembler-thumb2-inl.h (working copy)
|
| @@ -113,7 +113,7 @@
|
| ASSERT(IsPatchedReturnSequence());
|
| // The 2 instructions offset assumes patched return sequence.
|
| ASSERT(IsJSReturn(rmode()));
|
| - return Memory::Address_at(pc_ + 2 * Assembler::kInstrSize);
|
| + return Memory::Address_at(pc_ + 2 * Assembler::kInstrArmSize);
|
| }
|
|
|
|
|
| @@ -121,7 +121,7 @@
|
| ASSERT(IsPatchedReturnSequence());
|
| // The 2 instructions offset assumes patched return sequence.
|
| ASSERT(IsJSReturn(rmode()));
|
| - Memory::Address_at(pc_ + 2 * Assembler::kInstrSize) = target;
|
| + Memory::Address_at(pc_ + 2 * Assembler::kInstrArmSize) = target;
|
| }
|
|
|
|
|
| @@ -134,7 +134,7 @@
|
| ASSERT(IsPatchedReturnSequence());
|
| // The 2 instructions offset assumes patched return sequence.
|
| ASSERT(IsJSReturn(rmode()));
|
| - return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize);
|
| + return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrArmSize);
|
| }
|
|
|
|
|
| @@ -147,9 +147,9 @@
|
| // On ARM a "call instruction" is actually two instructions.
|
| // mov lr, pc
|
| // ldr pc, [pc, #XXX]
|
| - return (Assembler::instr_at(pc_) == kMovLrPc)
|
| - && ((Assembler::instr_at(pc_ + Assembler::kInstrSize) & kLdrPCPattern)
|
| - == kLdrPCPattern);
|
| + return (Assembler::instr_arm_at(pc_) == kMovLrPc) &&
|
| + ((Assembler::instr_arm_at(pc_ + Assembler::kInstrArmSize) &
|
| + kLdrPCPattern) == kLdrPCPattern);
|
| }
|
|
|
|
|
| @@ -220,23 +220,70 @@
|
| }
|
| }
|
|
|
| +void Assembler::EnsureArmMode() {
|
| + if (thumb_mode_) {
|
| + ASSERT((pc_offset() & 1) == 0);
|
| + if (pc_offset() & 2 != 0) {
|
| + DataProcessingImm(ADD, LeaveCC, pc, pc, 1);
|
| + // Pad with a T1 NOP
|
| + emit_thumb((int16_t) (b1011 * B12 | b1111 * B8));
|
| + } else {
|
| + DataProcessingImm(SUB, LeaveCC, pc, pc, 1);
|
| + }
|
| + ASSERT((pc_offset() & 3) == 0);
|
| + thumb_mode_ = false;
|
| + }
|
| + CheckBuffer();
|
| +}
|
|
|
| -void Assembler::emit(Instr x) {
|
| +void Assembler::EnsureThumbMode() {
|
| + if (!thumb_mode_) {
|
| + ASSERT((pc_offset() & 1) == 0);
|
| + emit_arm(al | B25 | B22 | pc.code() * B16 | pc.code() * B12 | 3);
|
| + thumb_mode_ = true;
|
| + ASSERT((pc_offset() & 1) == 0);
|
| + }
|
| CheckBuffer();
|
| - *reinterpret_cast<Instr*>(pc_) = x;
|
| - pc_ += kInstrSize;
|
| }
|
|
|
| +void Assembler::emit_arm(InstrArm x) {
|
| + EnsureArmMode();
|
| + *reinterpret_cast<InstrArm*>(pc_) = x;
|
| + pc_ += kInstrArmSize;
|
| +}
|
|
|
| +void Assembler::emit_int32(int32_t x) {
|
| + CheckBuffer();
|
| + *reinterpret_cast<int32_t*>(pc_) = x;
|
| + pc_ += sizeof(int32_t);
|
| +}
|
| +
|
| +
|
| +void Assembler::emit_thumb(InstrThumb x) {
|
| + EnsureThumbMode();
|
| + *reinterpret_cast<InstrThumb*>(pc_) = x;
|
| + pc_ += kInstrThumbSize;
|
| +}
|
| +
|
| Address Assembler::target_address_address_at(Address pc) {
|
| - Instr instr = Memory::int32_at(pc);
|
| - // Verify that the instruction at pc is a ldr<cond> <Rd>, [pc +/- offset_12].
|
| + Address target_pc = pc;
|
| + InstrArm instr = Memory::int32_at(target_pc);
|
| + // If we have a bx instruction, the instruction before the bx is
|
| + // what we need to patch.
|
| + static const int32_t kBxInstMask = 0x0ffffff0;
|
| + static const int32_t kBxInstPattern = 0x012fff10;
|
| + if ((instr & kBxInstMask) == kBxInstPattern) {
|
| + target_pc -= kInstrArmSize;
|
| + instr = Memory::int32_at(target_pc);
|
| + }
|
| + // Verify that the instruction to patch is a
|
| + // ldr<cond> <Rd>, [pc +/- offset_12].
|
| ASSERT((instr & 0x0f7f0000) == 0x051f0000);
|
| 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 + 8;
|
| + return target_pc + offset + 8;
|
| }
|
|
|
|
|
|
|