Commit 1b080a76 authored by rmcilroy@chromium.org's avatar rmcilroy@chromium.org

[Arm] Various cleanups to the Arm assembler backend.

A couple of cleanups to the Arm backend to enable support of extended
OOL constant pools in a following CL.

 - Remove instruction pattern extern const's and replace their use with IsXXX()
   functions.
 - Do calculation of the target address of a load from constant pool in one
   place.
 - A couple of other small cleanups.

R=ulan@chromium.org

Review URL: https://codereview.chromium.org/317653003

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21932 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent b0d3b668
......@@ -119,21 +119,14 @@ Address RelocInfo::target_address_address() {
return reinterpret_cast<Address>(pc_);
} else {
ASSERT(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc_)));
return Assembler::target_pointer_address_at(pc_);
return constant_pool_entry_address();
}
}
Address RelocInfo::constant_pool_entry_address() {
ASSERT(IsInConstantPool());
if (FLAG_enable_ool_constant_pool) {
ASSERT(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(pc_)));
return Assembler::target_constant_pool_address_at(pc_,
host_->constant_pool());
} else {
ASSERT(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc_)));
return Assembler::target_pointer_address_at(pc_);
}
return Assembler::constant_pool_entry_address(pc_, host_->constant_pool());
}
......@@ -314,8 +307,8 @@ bool RelocInfo::IsPatchedReturnSequence() {
// A patched return sequence is:
// ldr ip, [pc, #0]
// blx ip
return ((current_instr & kLdrPCMask) == kLdrPCPattern)
&& ((next_instr & kBlxRegMask) == kBlxRegPattern);
return Assembler::IsLdrPcImmediateOffset(current_instr) &&
Assembler::IsBlxReg(next_instr);
}
......@@ -428,42 +421,6 @@ void Assembler::emit(Instr x) {
}
Address Assembler::target_pointer_address_at(Address pc) {
Instr instr = Memory::int32_at(pc);
return pc + GetLdrRegisterImmediateOffset(instr) + kPcLoadDelta;
}
Address Assembler::target_constant_pool_address_at(
Address pc, ConstantPoolArray* constant_pool) {
ASSERT(constant_pool != NULL);
ASSERT(IsLdrPpImmediateOffset(Memory::int32_at(pc)));
Instr instr = Memory::int32_at(pc);
return reinterpret_cast<Address>(constant_pool) +
GetLdrRegisterImmediateOffset(instr);
}
Address Assembler::target_address_at(Address pc,
ConstantPoolArray* constant_pool) {
if (IsMovW(Memory::int32_at(pc))) {
ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize)));
Instruction* instr = Instruction::At(pc);
Instruction* next_instr = Instruction::At(pc + kInstrSize);
return reinterpret_cast<Address>(
(next_instr->ImmedMovwMovtValue() << 16) |
instr->ImmedMovwMovtValue());
} else if (FLAG_enable_ool_constant_pool) {
ASSERT(IsLdrPpImmediateOffset(Memory::int32_at(pc)));
return Memory::Address_at(
target_constant_pool_address_at(pc, constant_pool));
} else {
ASSERT(IsLdrPcImmediateOffset(Memory::int32_at(pc)));
return Memory::Address_at(target_pointer_address_at(pc));
}
}
Address Assembler::target_address_from_return_address(Address pc) {
// Returns the address of the call target from the return address that will
// be returned to after a call.
......@@ -523,11 +480,63 @@ static Instr PatchMovwImmediate(Instr instruction, uint32_t immediate) {
}
static bool IsConstantPoolLoad(Address pc) {
return !Assembler::IsMovW(Memory::int32_at(pc));
}
Address Assembler::constant_pool_entry_address(
Address pc, ConstantPoolArray* constant_pool) {
if (FLAG_enable_ool_constant_pool) {
ASSERT(constant_pool != NULL);
ASSERT(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(pc)));
return reinterpret_cast<Address>(constant_pool) +
GetLdrRegisterImmediateOffset(Memory::int32_at(pc));
} else {
ASSERT(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc)));
Instr instr = Memory::int32_at(pc);
return pc + GetLdrRegisterImmediateOffset(instr) + kPcLoadDelta;
}
}
Address Assembler::target_address_at(Address pc,
ConstantPoolArray* constant_pool) {
if (IsConstantPoolLoad(pc)) {
// This is a constant pool lookup. Return the value in the constant pool.
return Memory::Address_at(constant_pool_entry_address(pc, constant_pool));
} else {
// This is an movw_movt immediate load. Return the immediate.
ASSERT(IsMovW(Memory::int32_at(pc)) &&
IsMovT(Memory::int32_at(pc + kInstrSize)));
Instruction* movw_instr = Instruction::At(pc);
Instruction* movt_instr = Instruction::At(pc + kInstrSize);
return reinterpret_cast<Address>(
(movt_instr->ImmedMovwMovtValue() << 16) |
movw_instr->ImmedMovwMovtValue());
}
}
void Assembler::set_target_address_at(Address pc,
ConstantPoolArray* constant_pool,
Address target,
ICacheFlushMode icache_flush_mode) {
if (IsMovW(Memory::int32_at(pc))) {
if (IsConstantPoolLoad(pc)) {
// This is a constant pool lookup. Update the entry in the constant pool.
Memory::Address_at(constant_pool_entry_address(pc, constant_pool)) = target;
// Intuitively, we would think it is necessary to always flush the
// instruction cache after patching a target address in the code as follows:
// CPU::FlushICache(pc, sizeof(target));
// However, on ARM, no instruction is actually patched in the case
// of embedded constants of the form:
// ldr ip, [pp, #...]
// since the instruction accessing this address in the constant pool remains
// unchanged.
} else {
// This is an movw_movt immediate load. Patch the immediate embedded in the
// instructions.
ASSERT(IsMovW(Memory::int32_at(pc)));
ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize)));
uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc);
uint32_t immediate = reinterpret_cast<uint32_t>(target);
......@@ -538,21 +547,6 @@ void Assembler::set_target_address_at(Address pc,
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
CPU::FlushICache(pc, 2 * kInstrSize);
}
} else if (FLAG_enable_ool_constant_pool) {
ASSERT(IsLdrPpImmediateOffset(Memory::int32_at(pc)));
Memory::Address_at(
target_constant_pool_address_at(pc, constant_pool)) = target;
} else {
ASSERT(IsLdrPcImmediateOffset(Memory::int32_at(pc)));
Memory::Address_at(target_pointer_address_at(pc)) = target;
// Intuitively, we would think it is necessary to always flush the
// instruction cache after patching a target address in the code as follows:
// CPU::FlushICache(pc, sizeof(target));
// However, on ARM, no instruction is actually patched in the case
// of embedded constants of the form:
// ldr ip, [pc, #...]
// since the instruction accessing this address in the constant pool remains
// unchanged.
}
}
......
......@@ -418,11 +418,11 @@ const Instr kPopRegPattern =
// mov lr, pc
const Instr kMovLrPc = al | MOV | kRegister_pc_Code | kRegister_lr_Code * B12;
// ldr rd, [pc, #offset]
const Instr kLdrPCMask = 15 * B24 | 7 * B20 | 15 * B16;
const Instr kLdrPCPattern = 5 * B24 | L | kRegister_pc_Code * B16;
const Instr kLdrPCImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
const Instr kLdrPCImmedPattern = 5 * B24 | L | kRegister_pc_Code * B16;
// ldr rd, [pp, #offset]
const Instr kLdrPpMask = 15 * B24 | 7 * B20 | 15 * B16;
const Instr kLdrPpPattern = 5 * B24 | L | kRegister_r8_Code * B16;
const Instr kLdrPpImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
const Instr kLdrPpImmedPattern = 5 * B24 | L | kRegister_r8_Code * B16;
// vldr dd, [pc, #offset]
const Instr kVldrDPCMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8;
const Instr kVldrDPCPattern = 13 * B24 | L | kRegister_pc_Code * B16 | 11 * B8;
......@@ -640,6 +640,15 @@ Register Assembler::GetRm(Instr instr) {
}
Instr Assembler::GetConsantPoolLoadPattern() {
if (FLAG_enable_ool_constant_pool) {
return kLdrPpImmedPattern;
} else {
return kLdrPCImmedPattern;
}
}
bool Assembler::IsPush(Instr instr) {
return ((instr & ~kRdMask) == kPushRegPattern);
}
......@@ -673,14 +682,14 @@ bool Assembler::IsLdrRegFpNegOffset(Instr instr) {
bool Assembler::IsLdrPcImmediateOffset(Instr instr) {
// Check the instruction is indeed a
// ldr<cond> <Rd>, [pc +/- offset_12].
return (instr & kLdrPCMask) == kLdrPCPattern;
return (instr & kLdrPCImmedMask) == kLdrPCImmedPattern;
}
bool Assembler::IsLdrPpImmediateOffset(Instr instr) {
// Check the instruction is indeed a
// ldr<cond> <Rd>, [pp +/- offset_12].
return (instr & kLdrPpMask) == kLdrPpPattern;
return (instr & kLdrPpImmedMask) == kLdrPpImmedPattern;
}
......@@ -698,6 +707,20 @@ bool Assembler::IsVldrDPpImmediateOffset(Instr instr) {
}
bool Assembler::IsBlxReg(Instr instr) {
// Check the instruction is indeed a
// blxcc <Rm>
return (instr & kBlxRegMask) == kBlxRegPattern;
}
bool Assembler::IsBlxIp(Instr instr) {
// Check the instruction is indeed a
// blx ip
return instr == kBlxIp;
}
bool Assembler::IsTstImmediate(Instr instr) {
return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) ==
(I | TST | S);
......
......@@ -672,32 +672,6 @@ class ConstantPoolBuilder BASE_EMBEDDED {
int count_of_32bit_;
};
extern const Instr kMovLrPc;
extern const Instr kLdrPCMask;
extern const Instr kLdrPCPattern;
extern const Instr kLdrPpMask;
extern const Instr kLdrPpPattern;
extern const Instr kBlxRegMask;
extern const Instr kBlxRegPattern;
extern const Instr kBlxIp;
extern const Instr kMovMvnMask;
extern const Instr kMovMvnPattern;
extern const Instr kMovMvnFlip;
extern const Instr kMovLeaveCCMask;
extern const Instr kMovLeaveCCPattern;
extern const Instr kMovwMask;
extern const Instr kMovwPattern;
extern const Instr kMovwLeaveCCFlip;
extern const Instr kCmpCmnMask;
extern const Instr kCmpCmnPattern;
extern const Instr kCmpCmnFlip;
extern const Instr kAddSubFlip;
extern const Instr kAndBicFlip;
struct VmovIndex {
unsigned char index;
};
......@@ -751,11 +725,7 @@ class Assembler : public AssemblerBase {
// Return the address in the constant pool of the code target address used by
// the branch/call instruction at pc, or the object in a mov.
INLINE(static Address target_pointer_address_at(Address pc));
// Return the address in the constant pool of the code target address used by
// the branch/call instruction at pc, or the object in a mov.
INLINE(static Address target_constant_pool_address_at(
INLINE(static Address constant_pool_entry_address(
Address pc, ConstantPoolArray* constant_pool));
// Read/Modify the code target address in the branch/call instruction at pc.
......@@ -1390,6 +1360,7 @@ class Assembler : public AssemblerBase {
static int GetBranchOffset(Instr instr);
static bool IsLdrRegisterImmediate(Instr instr);
static bool IsVldrDRegisterImmediate(Instr instr);
static Instr GetConsantPoolLoadPattern();
static bool IsLdrPpImmediateOffset(Instr instr);
static bool IsVldrDPpImmediateOffset(Instr instr);
static int GetLdrRegisterImmediateOffset(Instr instr);
......@@ -1411,6 +1382,8 @@ class Assembler : public AssemblerBase {
static bool IsLdrRegFpNegOffset(Instr instr);
static bool IsLdrPcImmediateOffset(Instr instr);
static bool IsVldrDPcImmediateOffset(Instr instr);
static bool IsBlxReg(Instr instr);
static bool IsBlxIp(Instr instr);
static bool IsTstImmediate(Instr instr);
static bool IsCmpRegister(Instr instr);
static bool IsCmpImmediate(Instr instr);
......
......@@ -405,64 +405,6 @@ enum Hint { no_hint };
inline Hint NegateHint(Hint ignored) { return no_hint; }
// -----------------------------------------------------------------------------
// Specific instructions, constants, and masks.
// These constants are declared in assembler-arm.cc, as they use named registers
// and other constants.
// add(sp, sp, 4) instruction (aka Pop())
extern const Instr kPopInstruction;
// str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r))
// register r is not encoded.
extern const Instr kPushRegPattern;
// ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r))
// register r is not encoded.
extern const Instr kPopRegPattern;
// mov lr, pc
extern const Instr kMovLrPc;
// ldr rd, [pc, #offset]
extern const Instr kLdrPCMask;
extern const Instr kLdrPCPattern;
// vldr dd, [pc, #offset]
extern const Instr kVldrDPCMask;
extern const Instr kVldrDPCPattern;
// blxcc rm
extern const Instr kBlxRegMask;
extern const Instr kBlxRegPattern;
extern const Instr kMovMvnMask;
extern const Instr kMovMvnPattern;
extern const Instr kMovMvnFlip;
extern const Instr kMovLeaveCCMask;
extern const Instr kMovLeaveCCPattern;
extern const Instr kMovwMask;
extern const Instr kMovwPattern;
extern const Instr kMovwLeaveCCFlip;
extern const Instr kCmpCmnMask;
extern const Instr kCmpCmnPattern;
extern const Instr kCmpCmnFlip;
extern const Instr kAddSubFlip;
extern const Instr kAndBicFlip;
// A mask for the Rd register for push, pop, ldr, str instructions.
extern const Instr kLdrRegFpOffsetPattern;
extern const Instr kStrRegFpOffsetPattern;
extern const Instr kLdrRegFpNegOffsetPattern;
extern const Instr kStrRegFpNegOffsetPattern;
extern const Instr kLdrStrInstrTypeMask;
extern const Instr kLdrStrInstrArgumentMask;
extern const Instr kLdrStrOffsetMask;
// -----------------------------------------------------------------------------
// Instruction abstraction.
......
......@@ -4753,9 +4753,8 @@ void BackEdgeTable::PatchAt(Code* unoptimized_code,
Address pc,
BackEdgeState target_state,
Code* replacement_code) {
static const int kInstrSize = Assembler::kInstrSize;
Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc);
Address branch_address = pc_immediate_load_address - kInstrSize;
Address branch_address = pc_immediate_load_address - Assembler::kInstrSize;
CodePatcher patcher(branch_address, 1);
switch (target_state) {
case INTERRUPT:
......@@ -4770,7 +4769,7 @@ void BackEdgeTable::PatchAt(Code* unoptimized_code,
// Calculate branch offet to the ok-label - this is the difference between
// the branch address and |pc| (which points at <blx ip>) plus one instr.
int branch_offset = pc + kInstrSize - branch_address;
int branch_offset = pc + Assembler::kInstrSize - branch_address;
patcher.masm()->b(branch_offset, pl);
break;
}
......@@ -4800,11 +4799,10 @@ BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
Isolate* isolate,
Code* unoptimized_code,
Address pc) {
static const int kInstrSize = Assembler::kInstrSize;
ASSERT(Memory::int32_at(pc - kInstrSize) == kBlxIp);
ASSERT(Assembler::IsBlxIp(Memory::int32_at(pc - Assembler::kInstrSize)));
Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc);
Address branch_address = pc_immediate_load_address - kInstrSize;
Address branch_address = pc_immediate_load_address - Assembler::kInstrSize;
Address interrupt_address = Assembler::target_address_at(
pc_immediate_load_address, unoptimized_code);
......
......@@ -3630,15 +3630,9 @@ void MacroAssembler::GetRelocatedValueLocation(Register ldr_location,
ldr(result, MemOperand(ldr_location));
if (emit_debug_code()) {
// Check that the instruction is a ldr reg, [<pc or pp> + offset] .
if (FLAG_enable_ool_constant_pool) {
and_(result, result, Operand(kLdrPpPattern));
cmp(result, Operand(kLdrPpPattern));
Check(eq, kTheInstructionToPatchShouldBeALoadFromPp);
} else {
and_(result, result, Operand(kLdrPCPattern));
cmp(result, Operand(kLdrPCPattern));
Check(eq, kTheInstructionToPatchShouldBeALoadFromPc);
}
and_(result, result, Operand(GetConsantPoolLoadPattern()));
cmp(result, Operand(GetConsantPoolLoadPattern()));
Check(eq, kTheInstructionToPatchShouldBeALoadFromConstantPool);
// Result was clobbered. Restore it.
ldr(result, MemOperand(ldr_location));
}
......
......@@ -1236,10 +1236,8 @@ template <class C> inline bool Is(Object* obj);
"The current stack pointer is below csp") \
V(kTheInstructionShouldBeALui, "The instruction should be a lui") \
V(kTheInstructionShouldBeAnOri, "The instruction should be an ori") \
V(kTheInstructionToPatchShouldBeALoadFromPc, \
"The instruction to patch should be a load from pc") \
V(kTheInstructionToPatchShouldBeALoadFromPp, \
"The instruction to patch should be a load from pp") \
V(kTheInstructionToPatchShouldBeALoadFromConstantPool, \
"The instruction to patch should be a load from the constant pool") \
V(kTheInstructionToPatchShouldBeAnLdrLiteral, \
"The instruction to patch should be a ldr literal") \
V(kTheInstructionToPatchShouldBeALui, \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment