aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
diff options
context:
space:
mode:
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>2011-04-04 17:18:19 +0000
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>2011-04-04 17:18:19 +0000
commitac79e4c82f201c30a06c2cd05baebd20f5b49888 (patch)
tree7e7b27fc8910e9f11013439d325c37a5763f5833 /lib/Target/ARM/AsmParser/ARMAsmParser.cpp
parent74a26fe099e27c60493b7493e47b1ad53ac333cd (diff)
downloadexternal_llvm-ac79e4c82f201c30a06c2cd05baebd20f5b49888.tar.gz
external_llvm-ac79e4c82f201c30a06c2cd05baebd20f5b49888.tar.bz2
external_llvm-ac79e4c82f201c30a06c2cd05baebd20f5b49888.zip
- Implement asm parsing support for LDRSBT, LDRHT, LDRSHT and STRHT
also fix the encoding of the later. - Add a new encoding bit to describe the index mode used in AM3. - Teach printAddrMode3Operand to check by the addressing mode which index mode to print. - Testcases. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128832 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM/AsmParser/ARMAsmParser.cpp')
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp111
1 files changed, 111 insertions, 0 deletions
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 23d612505d..05b2b46f18 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -98,12 +98,18 @@ class ARMAsmParser : public TargetAsmParser {
SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy tryParseMemMode2Operand(
SmallVectorImpl<MCParsedAsmOperand*>&);
+ OperandMatchResultTy tryParseMemMode3Operand(
+ SmallVectorImpl<MCParsedAsmOperand*>&);
// Asm Match Converter Methods
bool CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &);
bool CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool CvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool CvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &);
public:
ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
@@ -371,6 +377,30 @@ public:
return true;
}
+ bool isMemMode3() const {
+ if (getMemAddrMode() != ARMII::AddrMode3)
+ return false;
+
+ if (getMemOffsetIsReg()) {
+ if (getMemOffsetRegShifted())
+ return false; // No shift with offset reg allowed
+ return true;
+ }
+
+ if (getMemNegative() &&
+ !(getMemPostindexed() || getMemPreindexed()))
+ return false;
+
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
+ if (!CE) return false;
+ int64_t Value = CE->getValue();
+
+ // The offset must be in the range 0-255 (imm8).
+ if (Value > 255 || Value < -255)
+ return false;
+
+ return true;
+ }
bool isMemMode5() const {
if (!isMemory() || getMemOffsetIsReg() || getMemWriteback() ||
getMemNegative())
@@ -539,6 +569,37 @@ public:
-Offset, ARM_AM::no_shift, IdxMode)));
}
+ void addMemMode3Operands(MCInst &Inst, unsigned N) const {
+ assert(isMemMode3() && "Invalid mode or number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum()));
+ unsigned IdxMode = (getMemPreindexed() | getMemPostindexed() << 1);
+
+ if (getMemOffsetIsReg()) {
+ Inst.addOperand(MCOperand::CreateReg(getMemOffsetRegNum()));
+
+ ARM_AM::AddrOpc AMOpc = getMemNegative() ? ARM_AM::sub : ARM_AM::add;
+ Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(AMOpc, 0,
+ IdxMode)));
+ return;
+ }
+
+ // Create a operand placeholder to always yield the same number of operands.
+ Inst.addOperand(MCOperand::CreateReg(0));
+
+ // FIXME: #-0 is encoded differently than #0. Does the parser preserve
+ // the difference?
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
+ assert(CE && "Non-constant mode 3 offset operand!");
+ int64_t Offset = CE->getValue();
+
+ if (Offset >= 0)
+ Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(ARM_AM::add,
+ Offset, IdxMode)));
+ else
+ Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(ARM_AM::sub,
+ -Offset, IdxMode)));
+ }
+
void addMemMode5Operands(MCInst &Inst, unsigned N) const {
assert(N == 2 && isMemMode5() && "Invalid number of operands!");
@@ -1219,6 +1280,17 @@ tryParseMemMode2Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_Success;
}
+/// tryParseMemMode3Operand - Try to parse memory addressing mode 3 operand.
+ARMAsmParser::OperandMatchResultTy ARMAsmParser::
+tryParseMemMode3Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ assert(Parser.getTok().is(AsmToken::LBrac) && "Token is not a \"[\"");
+
+ if (ParseMemory(Operands, ARMII::AddrMode3))
+ return MatchOperand_NoMatch;
+
+ return MatchOperand_Success;
+}
+
/// CvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
/// when they refer multiple MIOperands inside a single one.
@@ -1249,6 +1321,36 @@ CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
return true;
}
+/// CvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
+/// Needed here because the Asm Gen Matcher can't handle properly tied operands
+/// when they refer multiple MIOperands inside a single one.
+bool ARMAsmParser::
+CvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
+
+ // Create a writeback register dummy placeholder.
+ Inst.addOperand(MCOperand::CreateImm(0));
+
+ ((ARMOperand*)Operands[3])->addMemMode3Operands(Inst, 3);
+ ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
+ return true;
+}
+
+/// CvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
+/// Needed here because the Asm Gen Matcher can't handle properly tied operands
+/// when they refer multiple MIOperands inside a single one.
+bool ARMAsmParser::
+CvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ // Create a writeback register dummy placeholder.
+ Inst.addOperand(MCOperand::CreateImm(0));
+ ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
+ ((ARMOperand*)Operands[3])->addMemMode3Operands(Inst, 3);
+ ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
+ return true;
+}
+
/// Parse an ARM memory expression, return false if successful else return true
/// or an error. The first token must be a '[' when called.
///
@@ -1310,6 +1412,10 @@ ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
const AsmToken &ExclaimTok = Parser.getTok();
if (ExclaimTok.is(AsmToken::Exclaim)) {
+ // None of addrmode3 instruction uses "!"
+ if (AddrMode == ARMII::AddrMode3)
+ return true;
+
WBOp = ARMOperand::CreateToken(ExclaimTok.getString(),
ExclaimTok.getLoc());
Writeback = true;
@@ -1350,6 +1456,11 @@ ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
if (!OffsetIsReg) {
if (!Offset)
Offset = MCConstantExpr::Create(0, getContext());
+ } else {
+ if (AddrMode == ARMII::AddrMode3 && OffsetRegShifted) {
+ Error(E, "shift amount not supported");
+ return true;
+ }
}
Operands.push_back(ARMOperand::CreateMem(AddrMode, BaseRegNum, OffsetIsReg,