diff options
| author | Jim Grosbach <grosbach@apple.com> | 2011-07-25 22:20:28 +0000 |
|---|---|---|
| committer | Jim Grosbach <grosbach@apple.com> | 2011-07-25 22:20:28 +0000 |
| commit | 3a9cbeed73722c6a99d56a866b51c967ab906ce0 (patch) | |
| tree | 7a0540c94cd947ce1a5f61d6c21d76d1092d9cfc /llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | |
| parent | 77d24d374a735aaa052c1674fd1b82f80c726a14 (diff) | |
| download | llvm-3a9cbeed73722c6a99d56a866b51c967ab906ce0.zip llvm-3a9cbeed73722c6a99d56a866b51c967ab906ce0.tar.gz llvm-3a9cbeed73722c6a99d56a866b51c967ab906ce0.tar.bz2 | |
ARM assembly parsing and encoding for SSAT instruction.
Fix the Rn register encoding for both SSAT and USAT. Update the parsing of the
shift operand to correctly handle the allowed shift types and immediate ranges
and issue meaningful diagnostics when an illegal value or shift type is
specified. Add aliases to parse an ommitted shift operand (default value of
'lsl #0').
Add tests for diagnostics and proper encoding.
llvm-svn: 135990
Diffstat (limited to 'llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp')
| -rw-r--r-- | llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 98 |
1 files changed, 84 insertions, 14 deletions
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 6883fcb..02ed547 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -127,6 +127,7 @@ class ARMAsmParser : public TargetAsmParser { return parsePKHImm(O, "asr", 1, 32); } OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&); + OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&); // Asm Match Converter Methods bool CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode, @@ -179,7 +180,7 @@ class ARMOperand : public MCParsedAsmOperand { SPRRegisterList, ShiftedRegister, ShiftedImmediate, - Shifter, + ShifterImmediate, Token } Kind; @@ -239,9 +240,9 @@ class ARMOperand : public MCParsedAsmOperand { } Mem; struct { - ARM_AM::ShiftOpc ShiftTy; + bool isASR; unsigned Imm; - } Shift; + } ShifterImm; struct { ARM_AM::ShiftOpc ShiftTy; unsigned SrcReg; @@ -296,8 +297,8 @@ public: case ProcIFlags: IFlags = o.IFlags; break; - case Shifter: - Shift = o.Shift; + case ShifterImmediate: + ShifterImm = o.ShifterImm; break; case ShiftedRegister: RegShiftedReg = o.RegShiftedReg; @@ -505,7 +506,7 @@ public: bool isToken() const { return Kind == Token; } bool isMemBarrierOpt() const { return Kind == MemBarrierOpt; } bool isMemory() const { return Kind == Memory; } - bool isShifter() const { return Kind == Shifter; } + bool isShifterImm() const { return Kind == ShifterImmediate; } bool isRegShiftedReg() const { return Kind == ShiftedRegister; } bool isRegShiftedImm() const { return Kind == ShiftedImmediate; } bool isMemMode2() const { @@ -656,10 +657,10 @@ public: } - void addShifterOperands(MCInst &Inst, unsigned N) const { + void addShifterImmOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm( - ARM_AM::getSORegOpc(Shift.ShiftTy, 0))); + Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) | + ShifterImm.Imm)); } void addRegListOperands(MCInst &Inst, unsigned N) const { @@ -962,10 +963,11 @@ public: return Op; } - static ARMOperand *CreateShifter(ARM_AM::ShiftOpc ShTy, + static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm, SMLoc S, SMLoc E) { - ARMOperand *Op = new ARMOperand(Shifter); - Op->Shift.ShiftTy = ShTy; + ARMOperand *Op = new ARMOperand(ShifterImmediate); + Op->ShifterImm.isASR = isASR; + Op->ShifterImm.Imm = Imm; Op->StartLoc = S; Op->EndLoc = E; return Op; @@ -1127,8 +1129,9 @@ void ARMOperand::print(raw_ostream &OS) const { case Register: OS << "<register " << getReg() << ">"; break; - case Shifter: - OS << "<shifter " << ARM_AM::getShiftOpcStr(Shift.ShiftTy) << ">"; + case ShifterImmediate: + OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl") + << " #" << ShifterImm.Imm << ">"; break; case ShiftedRegister: OS << "<so_reg_reg " @@ -1705,6 +1708,73 @@ parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { return MatchOperand_Success; } +/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT +/// instructions. Legal values are: +/// lsl #n 'n' in [0,31] +/// asr #n 'n' in [1,32] +/// n == 32 encoded as n == 0. +ARMAsmParser::OperandMatchResultTy ARMAsmParser:: +parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { + const AsmToken &Tok = Parser.getTok(); + SMLoc S = Tok.getLoc(); + if (Tok.isNot(AsmToken::Identifier)) { + Error(S, "shift operator 'asr' or 'lsl' expected"); + return MatchOperand_ParseFail; + } + StringRef ShiftName = Tok.getString(); + bool isASR; + if (ShiftName == "lsl" || ShiftName == "LSL") + isASR = false; + else if (ShiftName == "asr" || ShiftName == "ASR") + isASR = true; + else { + Error(S, "shift operator 'asr' or 'lsl' expected"); + return MatchOperand_ParseFail; + } + Parser.Lex(); // Eat the operator. + + // A '#' and a shift amount. + if (Parser.getTok().isNot(AsmToken::Hash)) { + Error(Parser.getTok().getLoc(), "'#' expected"); + return MatchOperand_ParseFail; + } + Parser.Lex(); // Eat hash token. + + const MCExpr *ShiftAmount; + SMLoc E = Parser.getTok().getLoc(); + if (getParser().ParseExpression(ShiftAmount)) { + Error(E, "malformed shift expression"); + return MatchOperand_ParseFail; + } + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount); + if (!CE) { + Error(E, "shift amount must be an immediate"); + return MatchOperand_ParseFail; + } + + int64_t Val = CE->getValue(); + if (isASR) { + // Shift amount must be in [1,32] + if (Val < 1 || Val > 32) { + Error(E, "'asr' shift amount must be in range [1,32]"); + return MatchOperand_ParseFail; + } + // asr #32 encoded as asr #0. + if (Val == 32) Val = 0; + } else { + // Shift amount must be in [1,32] + if (Val < 0 || Val > 31) { + Error(E, "'lsr' shift amount must be in range [0,31]"); + return MatchOperand_ParseFail; + } + } + + E = Parser.getTok().getLoc(); + Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, 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. |
