summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
diff options
context:
space:
mode:
authorMihai Popa <mihail.popa@gmail.com>2013-07-22 15:49:36 +0000
committerMihai Popa <mihail.popa@gmail.com>2013-07-22 15:49:36 +0000
commit8a9da5b00cf79882b8b272a3933e79dd4a478b19 (patch)
treeff34a92524cf1ee564882f4bc1168b76e9ff1be0 /llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
parent623c3d84898c81e4525ff0b9715233abd7c3bc14 (diff)
downloadbcm5719-llvm-8a9da5b00cf79882b8b272a3933e79dd4a478b19.tar.gz
bcm5719-llvm-8a9da5b00cf79882b8b272a3933e79dd4a478b19.zip
This adds range checking for "ldr Rn, [pc, #imm]" Thumb
instructions. With this patch: 1. ldr.n is recognized as mnemonic for the short encoding 2. ldr.w is recognized as menmonic for the long encoding 3. ldr will map to either short or long encodings depending on the size of the offset llvm-svn: 186831
Diffstat (limited to 'llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp')
-rw-r--r--llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp40
1 files changed, 40 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index fc1faffd0bb..6d885a0d918 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -609,6 +609,26 @@ public:
}
return false;
}
+ // checks whether this operand is a memory operand computed as an offset
+ // applied to PC. the offset may have 8 bits of magnitude and is represented
+ // with two bits of shift. textually it may be either [pc, #imm], #imm or
+ // relocable expression...
+ bool isThumbMemPC() const {
+ int64_t Val = 0;
+ if (isImm()) {
+ if (isa<MCSymbolRefExpr>(Imm.Val)) return true;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val);
+ if (!CE) return false;
+ Val = CE->getValue();
+ }
+ else if (isMem()) {
+ if(!Memory.OffsetImm || Memory.OffsetRegNum) return false;
+ if(Memory.BaseRegNum != ARM::PC) return false;
+ Val = Memory.OffsetImm->getValue();
+ }
+ else return false;
+ return ((Val % 4) == 0) && (Val >= -1020) && (Val <= 1020);
+ }
bool isFPImm() const {
if (!isImm()) return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
@@ -1698,6 +1718,26 @@ public:
Inst.addOperand(MCOperand::CreateExpr(SR));
}
+ void addThumbMemPCOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ if (isImm()) {
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (CE) {
+ Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
+ return;
+ }
+
+ const MCSymbolRefExpr *SR = dyn_cast<MCSymbolRefExpr>(Imm.Val);
+ assert(SR && "Unknown value type!");
+ Inst.addOperand(MCOperand::CreateExpr(SR));
+ return;
+ }
+
+ assert(isMem() && "Unknown value type!");
+ assert(isa<MCConstantExpr>(Memory.OffsetImm) && "Unknown value type!");
+ Inst.addOperand(MCOperand::CreateImm(Memory.OffsetImm->getValue()));
+ }
+
void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
// The operand is actually a so_imm, but we have its bitwise
OpenPOWER on IntegriCloud