diff options
author | Bill Wendling <isanbard@gmail.com> | 2010-11-03 01:49:29 +0000 |
---|---|---|
committer | Bill Wendling <isanbard@gmail.com> | 2010-11-03 01:49:29 +0000 |
commit | e84eb99cbb5dbb0f8c9397a1a730246c1188ca30 (patch) | |
tree | 4d027d5daa2a3db28cab108b4a771900f3b704f7 /llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | |
parent | 68fb004616a5410033b2ad8d2b42fcd8977e6874 (diff) | |
download | bcm5719-llvm-e84eb99cbb5dbb0f8c9397a1a730246c1188ca30.tar.gz bcm5719-llvm-e84eb99cbb5dbb0f8c9397a1a730246c1188ca30.zip |
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.
llvm-svn: 118144
Diffstat (limited to 'llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp')
-rw-r--r-- | llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 4552374bcc7..f5dc38bcfed 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/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; |