From 188b47b2143be22f0b1edb82ed6d427e516434cf Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Wed, 11 Aug 2010 06:37:20 +0000 Subject: [PATCH] MC/ARM: Add basic support for handling predication by parsing it out of the mnemonic into a separate operand form. llvm-svn: 110794 --- .../lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 45 ++++++++++++++++++- llvm/test/MC/AsmParser/ARM/arm_instructions.s | 8 ++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 llvm/test/MC/AsmParser/ARM/arm_instructions.s diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index b87d45826ad6..abaf704fa5e5 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -22,6 +22,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" using namespace llvm; @@ -221,8 +222,10 @@ public: } void addCondCodeOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); + assert(N == 2 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode()))); + // FIXME: What belongs here? + Inst.addOperand(MCOperand::CreateReg(0)); } void addRegOperands(MCInst &Inst, unsigned N) const { @@ -237,6 +240,15 @@ public: virtual void dump(raw_ostream &OS) const; + static void CreateCondCode(OwningPtr &Op, ARMCC::CondCodes CC, + SMLoc S) { + Op.reset(new ARMOperand); + Op->Kind = CondCode; + Op->CC.Val = CC; + Op->StartLoc = S; + Op->EndLoc = S; + } + static void CreateToken(OwningPtr &Op, StringRef Str, SMLoc S) { Op.reset(new ARMOperand); @@ -656,9 +668,40 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc, size_t Start = 0, Next = Name.find('.'); StringRef Head = Name.slice(Start, Next); + // Determine the predicate, if any. + // + // FIXME: We need a way to check whether a prefix supports predication, + // otherwise we will end up with an ambiguity for instructions that happen to + // end with a predicate name. + unsigned CC = StringSwitch(Head.substr(Head.size()-2)) + .Case("eq", ARMCC::EQ) + .Case("ne", ARMCC::NE) + .Case("hs", ARMCC::HS) + .Case("lo", ARMCC::LO) + .Case("mi", ARMCC::MI) + .Case("pl", ARMCC::PL) + .Case("vs", ARMCC::VS) + .Case("vc", ARMCC::VC) + .Case("hi", ARMCC::HI) + .Case("ls", ARMCC::LS) + .Case("ge", ARMCC::GE) + .Case("lt", ARMCC::LT) + .Case("gt", ARMCC::GT) + .Case("le", ARMCC::LE) + .Case("al", ARMCC::AL) + .Default(~0U); + if (CC != ~0U) { + Head = Head.slice(0, Head.size() - 2); + } else + CC = ARMCC::AL; + ARMOperand::CreateToken(Op, Head, NameLoc); Operands.push_back(Op.take()); + ARMOperand::CreateCondCode(Op, ARMCC::CondCodes(CC), NameLoc); + Operands.push_back(Op.take()); + + // Add the remaining tokens in the mnemonic. while (Next != StringRef::npos) { Start = Next; Next = Name.find('.', Start + 1); diff --git a/llvm/test/MC/AsmParser/ARM/arm_instructions.s b/llvm/test/MC/AsmParser/ARM/arm_instructions.s new file mode 100644 index 000000000000..8632cb0cefd8 --- /dev/null +++ b/llvm/test/MC/AsmParser/ARM/arm_instructions.s @@ -0,0 +1,8 @@ +@ RUN: llvm-mc -triple arm-unknown-unknown %s | FileCheck %s + +@ CHECK: nop + nop + +@ CHECK: nopeq + nopeq +