Commit fadc74ec authored by rmcilroy@chromium.org's avatar rmcilroy@chromium.org

Clean up ARM mov 32bit immediate code in preparation for out of line constant pool.

R=rodolph.perfetta@arm.com, ulan@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19823 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 5d473db1
...@@ -1059,14 +1059,19 @@ bool Operand::must_output_reloc_info(const Assembler* assembler) const { ...@@ -1059,14 +1059,19 @@ bool Operand::must_output_reloc_info(const Assembler* assembler) const {
} }
static bool use_movw_movt(const Operand& x, const Assembler* assembler) { static bool use_mov_immediate_load(const Operand& x,
if (Assembler::use_immediate_embedded_pointer_loads(assembler)) { const Assembler* assembler) {
if (CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) &&
(assembler == NULL || !assembler->predictable_code_size())) {
// Prefer movw / movt to constant pool if it is more efficient on the CPU.
return true; return true;
} } else if (x.must_output_reloc_info(assembler)) {
if (x.must_output_reloc_info(assembler)) { // Prefer constant pool if data is likely to be patched.
return false; return false;
} else {
// Otherwise, use immediate load if movw / movt is available.
return CpuFeatures::IsSupported(ARMv7);
} }
return CpuFeatures::IsSupported(ARMv7);
} }
...@@ -1080,7 +1085,7 @@ bool Operand::is_single_instruction(const Assembler* assembler, ...@@ -1080,7 +1085,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
return !use_movw_movt(*this, assembler); return !use_mov_immediate_load(*this, assembler);
} 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
...@@ -1096,12 +1101,11 @@ bool Operand::is_single_instruction(const Assembler* assembler, ...@@ -1096,12 +1101,11 @@ bool Operand::is_single_instruction(const Assembler* assembler,
} }
void Assembler::move_32_bit_immediate(Condition cond, void Assembler::move_32_bit_immediate(Register rd,
Register rd, const Operand& x,
SBit s, Condition cond) {
const Operand& x) { if (rd.code() != pc.code()) {
if (rd.code() != pc.code() && s == LeaveCC) { if (use_mov_immediate_load(x, this)) {
if (use_movw_movt(x, this)) {
if (x.must_output_reloc_info(this)) { if (x.must_output_reloc_info(this)) {
RecordRelocInfo(x.rmode_, x.imm32_, DONT_USE_CONSTANT_POOL); RecordRelocInfo(x.rmode_, x.imm32_, DONT_USE_CONSTANT_POOL);
// Make sure the movw/movt doesn't get separated. // Make sure the movw/movt doesn't get separated.
...@@ -1138,20 +1142,9 @@ void Assembler::addrmod1(Instr instr, ...@@ -1138,20 +1142,9 @@ void Assembler::addrmod1(Instr instr,
CHECK(!rn.is(ip)); // rn should never be ip, or will be trashed CHECK(!rn.is(ip)); // rn should never be ip, or will be trashed
Condition cond = Instruction::ConditionField(instr); Condition cond = Instruction::ConditionField(instr);
if ((instr & ~kCondMask) == 13*B21) { // mov, S not set if ((instr & ~kCondMask) == 13*B21) { // mov, S not set
move_32_bit_immediate(cond, rd, LeaveCC, x); move_32_bit_immediate(rd, x, cond);
} else { } else {
if ((instr & kMovMvnMask) == kMovMvnPattern) { mov(ip, x, LeaveCC, cond);
// Moves need to use a constant pool entry.
RecordRelocInfo(x.rmode_, x.imm32_, USE_CONSTANT_POOL);
ldr(ip, MemOperand(pc, 0), cond);
} else if (x.must_output_reloc_info(this)) {
// Otherwise, use most efficient form of fetching from constant pool.
move_32_bit_immediate(cond, ip, LeaveCC, x);
} else {
// If this is not a mov or mvn instruction we may still be able to
// avoid a constant pool entry by using mvn or movw.
mov(ip, x, LeaveCC, cond);
}
addrmod1(instr, rn, rd, Operand(ip)); addrmod1(instr, rn, rd, Operand(ip));
} }
return; return;
...@@ -1819,8 +1812,7 @@ void Assembler::msr(SRegisterFieldMask fields, const Operand& src, ...@@ -1819,8 +1812,7 @@ void Assembler::msr(SRegisterFieldMask fields, const Operand& src,
if (src.must_output_reloc_info(this) || if (src.must_output_reloc_info(this) ||
!fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) { !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) {
// Immediate operand cannot be encoded, load it first to register ip. // Immediate operand cannot be encoded, load it first to register ip.
RecordRelocInfo(src.rmode_, src.imm32_); move_32_bit_immediate(ip, src);
ldr(ip, MemOperand(pc, 0), cond);
msr(fields, Operand(ip), cond); msr(fields, Operand(ip), cond);
return; return;
} }
......
...@@ -1292,12 +1292,6 @@ class Assembler : public AssemblerBase { ...@@ -1292,12 +1292,6 @@ class Assembler : public AssemblerBase {
// Jump unconditionally to given label. // Jump unconditionally to given label.
void jmp(Label* L) { b(L, al); } void jmp(Label* L) { b(L, al); }
static bool use_immediate_embedded_pointer_loads(
const Assembler* assembler) {
return CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) &&
(assembler == NULL || !assembler->predictable_code_size());
}
// Check the code size generated from label to here. // Check the code size generated from label to here.
int SizeOfCodeGeneratedSince(Label* label) { int SizeOfCodeGeneratedSince(Label* label) {
return pc_offset() - label->pos(); return pc_offset() - label->pos();
...@@ -1565,10 +1559,9 @@ class Assembler : public AssemblerBase { ...@@ -1565,10 +1559,9 @@ class Assembler : public AssemblerBase {
inline void emit(Instr x); inline void emit(Instr x);
// 32-bit immediate values // 32-bit immediate values
void move_32_bit_immediate(Condition cond, void move_32_bit_immediate(Register rd,
Register rd, const Operand& x,
SBit s, Condition cond = al);
const Operand& x);
// Instruction generation // Instruction generation
void addrmod1(Instr instr, Register rn, Register rd, const Operand& x); void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
......
...@@ -272,10 +272,10 @@ TEST(Type0) { ...@@ -272,10 +272,10 @@ TEST(Type0) {
// We only disassemble one instruction so the eor instruction is not here. // We only disassemble one instruction so the eor instruction is not here.
COMPARE(eor(r5, r4, Operand(0x1234), LeaveCC, ne), COMPARE(eor(r5, r4, Operand(0x1234), LeaveCC, ne),
"1301c234 movwne ip, #4660"); "1301c234 movwne ip, #4660");
// Movw can't do setcc so we don't get that here. Mov immediate with setcc // Movw can't do setcc, so first move to ip, then the following instruction
// is pretty strange anyway. // moves to r5. Mov immediate with setcc is pretty strange anyway.
COMPARE(mov(r5, Operand(0x01234), SetCC, ne), COMPARE(mov(r5, Operand(0x01234), SetCC, ne),
"159fc000 ldrne ip, [pc, #+0]"); "1301c234 movwne ip, #4660");
// Emit a literal pool now, otherwise this could be dumped later, in the // Emit a literal pool now, otherwise this could be dumped later, in the
// middle of a different test. // middle of a different test.
EMIT_PENDING_LITERALS(); EMIT_PENDING_LITERALS();
......
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