Reviewers: ulan,
Description:
Fix ARM dissambler test problems with movw/movt.
[email protected]
Please review this at https://codereview.chromium.org/11198061/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files:
M src/arm/assembler-arm.h
M src/arm/assembler-arm.cc
Index: src/arm/assembler-arm.cc
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index
cc3d5b11a323801f69ecdbc630b37a54a932c74e..9be62a404bd2935864095744d1d4fa8a985a937b
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<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);
}
@@ -910,14 +900,17 @@ void Assembler::addrmod1(Instr instr,
if ((instr & ~kCondMask) == 13*B21) { // mov, S not set
move_32_bit_immediate(cond, rd, 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.
- if (!x.must_output_reloc_info(this) &&
- (instr & kMovMvnMask) != kMovMvnPattern) {
- mov(ip, x, LeaveCC, cond);
+ if ((instr & kMovMvnMask) == kMovMvnPattern) {
+ // 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 {
- move_32_bit_immediate(cond, ip,
- static_cast<SBit>(instr & (1 << 20)), x);
+ // 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));
}
Index: src/arm/assembler-arm.h
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index
bee35af15eed4fe96f2e0800cdb0b61945c259b4..dfcce6011414c363b40db8e96bda4b2208876478
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.
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev