aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2010-11-03 01:49:29 +0000
committerBill Wendling <isanbard@gmail.com>2010-11-03 01:49:29 +0000
commit92b5a2eb1646b3c1173a5ff3c0073f24ed5ee6a4 (patch)
tree534c8e3e743a503fd2abdb4a63599fb3e4b979dc /lib/Target/ARM/AsmParser/ARMAsmParser.cpp
parent394d6298bcf89a75b51c8314a6705f6984e46b49 (diff)
The MC code couldn't handle ARM LDR instructions with negative offsets:
vldr.64 d1, [r0, #-32] The problem was with how the addressing mode 5 encodes the offsets. This change makes sure that the way offsets are handled in addressing mode 5 is consistent throughout the MC code. It involves re-refactoring the "getAddrModeImmOpValue" method into an "Imm12" and "addressing mode 5" version. But not to worry! The majority of the duplicated code has been unified. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118144 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM/AsmParser/ARMAsmParser.cpp')
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp16
1 files changed, 13 insertions, 3 deletions
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 4552374bcc..f5dc38bcfe 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "ARM.h"
+#include "ARMAddressingModes.h"
#include "ARMSubtarget.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
@@ -260,16 +261,25 @@ public:
Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
assert(!Mem.OffsetIsReg && "invalid mode 5 operand");
+
// FIXME: #-0 is encoded differently than #0. Does the parser preserve
// the difference?
if (Mem.Offset) {
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset);
- assert(CE && "non-constant mode 5 offset operand!");
+ assert(CE && "Non-constant mode 5 offset operand!");
+
// The MCInst offset operand doesn't include the low two bits (like
// the instruction encoding).
- Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
- } else
+ int64_t Offset = CE->getValue() / 4;
+ if (Offset >= 0)
+ Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::add,
+ Offset)));
+ else
+ Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::sub,
+ -Offset)));
+ } else {
Inst.addOperand(MCOperand::CreateImm(0));
+ }
}
virtual void dump(raw_ostream &OS) const;