Commit 4431e0c5 authored by danno@chromium.org's avatar danno@chromium.org

Put more constants in movw/movt instructions

R=ulan@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12759 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 230bec12
...@@ -819,6 +819,17 @@ bool Operand::must_output_reloc_info(const Assembler* assembler) const { ...@@ -819,6 +819,17 @@ bool Operand::must_output_reloc_info(const Assembler* assembler) const {
} }
static bool use_movw_movt(const Operand& x, const Assembler* assembler) {
if (Assembler::use_immediate_embedded_pointer_loads(assembler)) {
return true;
}
if (x.must_output_reloc_info(assembler)) {
return false;
}
return CpuFeatures::IsSupported(ARMv7);
}
bool Operand::is_single_instruction(const Assembler* assembler, bool Operand::is_single_instruction(const Assembler* assembler,
Instr instr) const { Instr instr) const {
if (rm_.is_valid()) return true; if (rm_.is_valid()) return true;
...@@ -829,23 +840,7 @@ bool Operand::is_single_instruction(const Assembler* assembler, ...@@ -829,23 +840,7 @@ bool Operand::is_single_instruction(const Assembler* assembler,
// constant pool is required. For a mov instruction not setting the // constant pool is required. For a mov instruction not setting the
// condition code additional instruction conventions can be used. // condition code additional instruction conventions can be used.
if ((instr & ~kCondMask) == 13*B21) { // mov, S not set if ((instr & ~kCondMask) == 13*B21) { // mov, S not set
#ifdef USE_BLX return !use_movw_movt(*this, assembler);
// When using BLX, there are two things that must be true for the address
// load to be longer than a single instruction. First, immediate loads
// using movw/movt must be supported (and fast) on the target ARM
// architecture. Second, the reloc mode must be something other than NONE,
// since NONE is a used whenever the constant pool cannot be used for
// technical reasons, e.g. back-patching calls site in optimized code with
// a call to a lazy deopt routine.
return !Assembler::allow_immediate_constant_pool_loads(assembler) &&
rmode_ != RelocInfo::NONE;
#else
// It's not possible to use immediate loads to the pc to do a call, (the
// pc would be inconsistent half-way through the load), so loading the
// destination address without USE_BLX is always a single instruction of
// the form ldr pc, [pc + #xxx].
return true;
#endif
} else { } else {
// If this is not a mov or mvn instruction there will always an additional // If this is not a mov or mvn instruction there will always an additional
// instructions - either mov or ldr. The mov might actually be two // instructions - either mov or ldr. The mov might actually be two
...@@ -866,26 +861,21 @@ void Assembler::move_32_bit_immediate(Condition cond, ...@@ -866,26 +861,21 @@ void Assembler::move_32_bit_immediate(Condition cond,
SBit s, SBit s,
const Operand& x) { const Operand& x) {
if (rd.code() != pc.code() && s == LeaveCC) { if (rd.code() != pc.code() && s == LeaveCC) {
// Candidate for immediate load. if (use_movw_movt(x, this)) {
if (x.must_output_reloc_info(this)) { if (x.must_output_reloc_info(this)) {
if (!Assembler::allow_immediate_constant_pool_loads(this)) { RecordRelocInfo(x.rmode_, x.imm32_, DONT_USE_CONSTANT_POOL);
RecordRelocInfo(x.rmode_, x.imm32_, USE_CONSTANT_POOL); // Make sure the movw/movt doesn't get separated.
ldr(rd, MemOperand(pc, 0), cond); BlockConstPoolFor(2);
return;
} }
RecordRelocInfo(x.rmode_, x.imm32_, DONT_USE_CONSTANT_POOL); emit(cond | 0x30*B20 | rd.code()*B12 |
// Make sure the movw/movt doesn't get separated. EncodeMovwImmediate(x.imm32_ & 0xffff));
BlockConstPoolFor(2); movt(rd, static_cast<uint32_t>(x.imm32_) >> 16, cond);
return;
} }
// Emit a real movw/movt pair.
emit(cond | 0x30*B20 | rd.code()*B12 |
EncodeMovwImmediate(x.imm32_ & 0xffff));
movt(rd, static_cast<uint32_t>(x.imm32_) >> 16, cond);
} else {
RecordRelocInfo(x.rmode_, x.imm32_, USE_CONSTANT_POOL);
ldr(rd, MemOperand(pc, 0), cond);
} }
RecordRelocInfo(x.rmode_, x.imm32_, USE_CONSTANT_POOL);
ldr(rd, MemOperand(pc, 0), cond);
} }
...@@ -916,8 +906,7 @@ void Assembler::addrmod1(Instr instr, ...@@ -916,8 +906,7 @@ void Assembler::addrmod1(Instr instr,
(instr & kMovMvnMask) != kMovMvnPattern) { (instr & kMovMvnMask) != kMovMvnPattern) {
mov(ip, x, LeaveCC, cond); mov(ip, x, LeaveCC, cond);
} else { } else {
move_32_bit_immediate(cond, ip, move_32_bit_immediate(cond, ip, LeaveCC, x);
static_cast<SBit>(instr & (1 << 20)), x);
} }
addrmod1(instr, rn, rd, Operand(ip)); addrmod1(instr, rn, rd, Operand(ip));
} }
......
...@@ -1187,10 +1187,18 @@ class Assembler : public AssemblerBase { ...@@ -1187,10 +1187,18 @@ class Assembler : public AssemblerBase {
bool predictable_code_size() const { return predictable_code_size_; } bool predictable_code_size() const { return predictable_code_size_; }
static bool allow_immediate_constant_pool_loads( static bool use_immediate_embedded_pointer_loads(
const Assembler* assembler) { const Assembler* assembler) {
#ifdef USE_BLX
return CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) && return CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) &&
(assembler == NULL || !assembler->predictable_code_size()); (assembler == NULL || !assembler->predictable_code_size());
#else
// If not using BLX, all loads from the constant pool cannot be immediate,
// because the ldr pc, [pc + #xxxx] used for calls must be a single
// instruction and cannot be easily distinguished out of context from
// other loads that could use movw/movt.
return false;
#endif
} }
// Check the code size generated from label to here. // Check the code size generated from label to here.
......
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