diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc index cc3d5b11a32..0860bd2ffb5 100644 --- a/src/arm/assembler-arm.cc +++ b/src/arm/assembler-arm.cc @@ -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, Instr instr) const { if (rm_.is_valid()) return true; @@ -829,23 +840,7 @@ bool Operand::is_single_instruction(const Assembler* assembler, // constant pool is required. For a mov instruction not setting the // condition code additional instruction conventions can be used. if ((instr & ~kCondMask) == 13*B21) { // mov, S not set -#ifdef USE_BLX - // 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 + return !use_movw_movt(*this, assembler); } else { // 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 @@ -866,26 +861,21 @@ void Assembler::move_32_bit_immediate(Condition cond, SBit s, const Operand& x) { if (rd.code() != pc.code() && s == LeaveCC) { - // Candidate for immediate load. - if (x.must_output_reloc_info(this)) { - if (!Assembler::allow_immediate_constant_pool_loads(this)) { - RecordRelocInfo(x.rmode_, x.imm32_, USE_CONSTANT_POOL); - ldr(rd, MemOperand(pc, 0), cond); - return; + if (use_movw_movt(x, this)) { + if (x.must_output_reloc_info(this)) { + RecordRelocInfo(x.rmode_, x.imm32_, DONT_USE_CONSTANT_POOL); + // Make sure the movw/movt doesn't get separated. + BlockConstPoolFor(2); } - RecordRelocInfo(x.rmode_, x.imm32_, DONT_USE_CONSTANT_POOL); - // Make sure the movw/movt doesn't get separated. - BlockConstPoolFor(2); + emit(cond | 0x30*B20 | rd.code()*B12 | + EncodeMovwImmediate(x.imm32_ & 0xffff)); + movt(rd, static_cast(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(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, (instr & kMovMvnMask) != kMovMvnPattern) { mov(ip, x, LeaveCC, cond); } else { - move_32_bit_immediate(cond, ip, - static_cast(instr & (1 << 20)), x); + move_32_bit_immediate(cond, ip, LeaveCC, x); } addrmod1(instr, rn, rd, Operand(ip)); } diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h index bee35af15ee..dfcce601141 100644 --- a/src/arm/assembler-arm.h +++ b/src/arm/assembler-arm.h @@ -1187,10 +1187,18 @@ class Assembler : public AssemblerBase { 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) { +#ifdef USE_BLX return CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) && (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.