From 1d9d5e93d12d83c5bffb6039bf37580da32357f5 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Wed, 10 Aug 2011 21:56:18 +0000 Subject: [PATCH] ARM LDRD(register) assembly parsing and encoding. Add support for literal encoding of #-0 along the way. llvm-svn: 137254 --- llvm/lib/Target/ARM/ARMInstrInfo.td | 5 +- .../lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 77 ++++++++++++++++++- llvm/test/MC/ARM/arm-memory-instructions.s | 20 +++++ 3 files changed, 99 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td index 0aaf67692a93..3b77cdbdff16 100644 --- a/llvm/lib/Target/ARM/ARMInstrInfo.td +++ b/llvm/lib/Target/ARM/ARMInstrInfo.td @@ -722,7 +722,10 @@ def addrmode3 : Operand, // FIXME: split into imm vs. reg versions. // FIXME: parser method to handle +/- register. -def AM3OffsetAsmOperand : AsmOperandClass { let Name = "AM3Offset"; } +def AM3OffsetAsmOperand : AsmOperandClass { + let Name = "AM3Offset"; + let ParserMethod = "parseAM3Offset"; +} def am3offset : Operand, ComplexPattern { diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index fcc8a6a7fd65..72ab7ea595df 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -114,6 +114,7 @@ class ARMAsmParser : public MCTargetAsmParser { OperandMatchResultTy parseRotImm(SmallVectorImpl&); OperandMatchResultTy parseBitfield(SmallVectorImpl&); OperandMatchResultTy parsePostIdxReg(SmallVectorImpl&); + OperandMatchResultTy parseAM3Offset(SmallVectorImpl&); // Asm Match Converter Methods bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode, @@ -557,7 +558,8 @@ public: const MCConstantExpr *CE = dyn_cast(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 &Operands) { return MatchOperand_Success; } +ARMAsmParser::OperandMatchResultTy ARMAsmParser:: +parseAM3Offset(SmallVectorImpl &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(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. diff --git a/llvm/test/MC/ARM/arm-memory-instructions.s b/llvm/test/MC/ARM/arm-memory-instructions.s index a216a1178063..6a1c566c231d 100644 --- a/llvm/test/MC/ARM/arm-memory-instructions.s +++ b/llvm/test/MC/ARM/arm-memory-instructions.s @@ -114,8 +114,28 @@ _func: ldrd r7, r8, [r2, #15] ldrd r1, r2, [r9, #32]! ldrd r6, r7, [r1], #8 + ldrd r1, r2, [r8], #0 + ldrd r1, r2, [r8], #+0 + ldrd r1, r2, [r8], #-0 @ CHECK: ldrd r3, r4, [r5] @ encoding: [0xd0,0x30,0xc5,0xe1] @ CHECK: ldrd r7, r8, [r2, #15] @ encoding: [0xdf,0x70,0xc2,0xe1] @ CHECK: ldrd r1, r2, [r9, #32]! @ encoding: [0xd0,0x12,0xe9,0xe1] @ CHECK: ldrd r6, r7, [r1], #8 @ encoding: [0xd8,0x60,0xc1,0xe0] +@ CHECK: ldrd r1, r2, [r8], #0 @ encoding: [0xd0,0x10,0xc8,0xe0] +@ CHECK: ldrd r1, r2, [r8], #0 @ encoding: [0xd0,0x10,0xc8,0xe0] +@ CHECK: ldrd r1, r2, [r8], #-0 @ encoding: [0xd0,0x10,0x48,0xe0] + + +@------------------------------------------------------------------------------ +@ LDRD (register) +@------------------------------------------------------------------------------ + ldrd r3, r4, [r1, r3] + ldrd r4, r5, [r7, r2]! + ldrd r1, r2, [r8], r12 + ldrd r1, r2, [r8], -r12 + + ldrd r3, r4, [r1, r3] @ encoding: [0xd3,0x30,0x81,0xe1] + ldrd r4, r5, [r7, r2]! @ encoding: [0xd2,0x40,0xa7,0xe1] + ldrd r1, r2, [r8], r12 @ encoding: [0xdc,0x10,0x88,0xe0] + ldrd r1, r2, [r8], -r12 @ encoding: [0xdc,0x10,0x08,0xe0]