diff options
| author | Jim Grosbach <grosbach@apple.com> | 2011-08-10 21:56:18 +0000 |
|---|---|---|
| committer | Jim Grosbach <grosbach@apple.com> | 2011-08-10 21:56:18 +0000 |
| commit | 251bf25e7ee9702fed2a66deeb404ce473f7bac1 (patch) | |
| tree | f3aa2365d7de113573bf8c4e02d3e9ad1ecd1fb9 /lib/Target/ARM/AsmParser/ARMAsmParser.cpp | |
| parent | b549bcfe6c19dbb24162c75bbcc06d4a5fa90cb8 (diff) | |
ARM LDRD(register) assembly parsing and encoding.
Add support for literal encoding of #-0 along the way.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137254 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM/AsmParser/ARMAsmParser.cpp')
| -rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 77 |
1 files changed, 75 insertions, 2 deletions
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index fcc8a6a7fd..72ab7ea595 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -114,6 +114,7 @@ class ARMAsmParser : public MCTargetAsmParser { OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&); OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&); OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&); + OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&); // Asm Match Converter Methods bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode, @@ -557,7 +558,8 @@ public: const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); if (!CE) return false; int64_t Val = CE->getValue(); - return Val > -256 && Val < 256; + // Special case, #-0 is INT32_MIN. + return (Val > -256 && Val < 256) || Val == INT32_MIN; } bool isAddrMode5() const { if (Kind != Memory) @@ -865,6 +867,7 @@ public: ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0); Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum)); Inst.addOperand(MCOperand::CreateImm(Val)); + return; } // Constant offset. @@ -874,7 +877,7 @@ public: // Special case for #-0 if (Val == INT32_MIN) Val = 0; if (Val < 0) Val = -Val; - Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift); + Val = ARM_AM::getAM3Opc(AddSub, Val); Inst.addOperand(MCOperand::CreateReg(0)); Inst.addOperand(MCOperand::CreateImm(Val)); } @@ -2007,6 +2010,76 @@ parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { return MatchOperand_Success; } +ARMAsmParser::OperandMatchResultTy ARMAsmParser:: +parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { + // Check for a post-index addressing register operand. Specifically: + // am3offset := '+' register + // | '-' register + // | register + // | # imm + // | # + imm + // | # - imm + + // This method must return MatchOperand_NoMatch without consuming any tokens + // in the case where there is no match, as other alternatives take other + // parse methods. + AsmToken Tok = Parser.getTok(); + SMLoc S = Tok.getLoc(); + + // Do immediates first, as we always parse those if we have a '#'. + if (Parser.getTok().is(AsmToken::Hash)) { + Parser.Lex(); // Eat the '#'. + // Explicitly look for a '-', as we need to encode negative zero + // differently. + bool isNegative = Parser.getTok().is(AsmToken::Minus); + const MCExpr *Offset; + if (getParser().ParseExpression(Offset)) + return MatchOperand_ParseFail; + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset); + if (!CE) { + Error(S, "constant expression expected"); + return MatchOperand_ParseFail; + } + SMLoc E = Tok.getLoc(); + // Negative zero is encoded as the flag value INT32_MIN. + int32_t Val = CE->getValue(); + if (isNegative && Val == 0) + Val = INT32_MIN; + + Operands.push_back( + ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E)); + + return MatchOperand_Success; + } + + + bool haveEaten = false; + bool isAdd = true; + int Reg = -1; + if (Tok.is(AsmToken::Plus)) { + Parser.Lex(); // Eat the '+' token. + haveEaten = true; + } else if (Tok.is(AsmToken::Minus)) { + Parser.Lex(); // Eat the '-' token. + isAdd = false; + haveEaten = true; + } + if (Parser.getTok().is(AsmToken::Identifier)) + Reg = tryParseRegister(); + if (Reg == -1) { + if (!haveEaten) + return MatchOperand_NoMatch; + Error(Parser.getTok().getLoc(), "register expected"); + return MatchOperand_ParseFail; + } + SMLoc E = Parser.getTok().getLoc(); + + Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift, + 0, S, E)); + + 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. |
