xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- HexagonAsmParser.cpp - Parse Hexagon asm to MCInst instructions----===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "HexagonTargetStreamer.h"
100b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCChecker.h"
110b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCELFStreamer.h"
120b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCExpr.h"
130b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCInstrInfo.h"
140b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCTargetDesc.h"
150b57cec5SDimitry Andric #include "MCTargetDesc/HexagonShuffler.h"
160b57cec5SDimitry Andric #include "TargetInfo/HexagonTargetInfo.h"
170b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
180b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
190b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
200b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
210b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
220b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCDirectives.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCELFStreamer.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
300b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParser.h"
310b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParserExtension.h"
320b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
330b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
340b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
350b57cec5SDimitry Andric #include "llvm/MC/MCSectionELF.h"
360b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
370b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
380b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
390b57cec5SDimitry Andric #include "llvm/MC/MCValue.h"
40349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
410b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
420b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
430b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
440b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
450b57cec5SDimitry Andric #include "llvm/Support/Format.h"
46*0fca6ea1SDimitry Andric #include "llvm/Support/HexagonAttributes.h"
470b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
480b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h"
490b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h"
500b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
510b57cec5SDimitry Andric #include <algorithm>
520b57cec5SDimitry Andric #include <cassert>
530b57cec5SDimitry Andric #include <cctype>
540b57cec5SDimitry Andric #include <cstddef>
550b57cec5SDimitry Andric #include <cstdint>
560b57cec5SDimitry Andric #include <memory>
570b57cec5SDimitry Andric #include <string>
580b57cec5SDimitry Andric #include <utility>
590b57cec5SDimitry Andric 
60fe6060f1SDimitry Andric #define DEBUG_TYPE "mcasmparser"
61fe6060f1SDimitry Andric 
620b57cec5SDimitry Andric using namespace llvm;
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric static cl::opt<bool> WarnMissingParenthesis(
650b57cec5SDimitry Andric     "mwarn-missing-parenthesis",
660b57cec5SDimitry Andric     cl::desc("Warn for missing parenthesis around predicate registers"),
670b57cec5SDimitry Andric     cl::init(true));
680b57cec5SDimitry Andric static cl::opt<bool> ErrorMissingParenthesis(
690b57cec5SDimitry Andric     "merror-missing-parenthesis",
700b57cec5SDimitry Andric     cl::desc("Error for missing parenthesis around predicate registers"),
710b57cec5SDimitry Andric     cl::init(false));
720b57cec5SDimitry Andric static cl::opt<bool> WarnSignedMismatch(
730b57cec5SDimitry Andric     "mwarn-sign-mismatch",
740b57cec5SDimitry Andric     cl::desc("Warn for mismatching a signed and unsigned value"),
751ac55f4cSDimitry Andric     cl::init(false));
760b57cec5SDimitry Andric static cl::opt<bool> WarnNoncontigiousRegister(
770b57cec5SDimitry Andric     "mwarn-noncontigious-register",
780b57cec5SDimitry Andric     cl::desc("Warn for register names that arent contigious"), cl::init(true));
790b57cec5SDimitry Andric static cl::opt<bool> ErrorNoncontigiousRegister(
800b57cec5SDimitry Andric     "merror-noncontigious-register",
810b57cec5SDimitry Andric     cl::desc("Error for register names that aren't contigious"),
820b57cec5SDimitry Andric     cl::init(false));
83*0fca6ea1SDimitry Andric static cl::opt<bool> AddBuildAttributes("hexagon-add-build-attributes");
840b57cec5SDimitry Andric namespace {
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric struct HexagonOperand;
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric class HexagonAsmParser : public MCTargetAsmParser {
890b57cec5SDimitry Andric 
getTargetStreamer()900b57cec5SDimitry Andric   HexagonTargetStreamer &getTargetStreamer() {
910b57cec5SDimitry Andric     MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer();
920b57cec5SDimitry Andric     return static_cast<HexagonTargetStreamer &>(TS);
930b57cec5SDimitry Andric   }
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   MCAsmParser &Parser;
960b57cec5SDimitry Andric   MCInst MCB;
970b57cec5SDimitry Andric   bool InBrackets;
980b57cec5SDimitry Andric 
getParser() const990b57cec5SDimitry Andric   MCAsmParser &getParser() const { return Parser; }
getAssembler() const1000b57cec5SDimitry Andric   MCAssembler *getAssembler() const {
1010b57cec5SDimitry Andric     MCAssembler *Assembler = nullptr;
1020b57cec5SDimitry Andric     // FIXME: need better way to detect AsmStreamer (upstream removed getKind())
1030b57cec5SDimitry Andric     if (!Parser.getStreamer().hasRawTextSupport()) {
1040b57cec5SDimitry Andric       MCELFStreamer *MES = static_cast<MCELFStreamer *>(&Parser.getStreamer());
1050b57cec5SDimitry Andric       Assembler = &MES->getAssembler();
1060b57cec5SDimitry Andric     }
1070b57cec5SDimitry Andric     return Assembler;
1080b57cec5SDimitry Andric   }
1090b57cec5SDimitry Andric 
getLexer() const1100b57cec5SDimitry Andric   MCAsmLexer &getLexer() const { return Parser.getLexer(); }
1110b57cec5SDimitry Andric 
equalIsAsmAssignment()1120b57cec5SDimitry Andric   bool equalIsAsmAssignment() override { return false; }
1130b57cec5SDimitry Andric   bool isLabel(AsmToken &Token) override;
1140b57cec5SDimitry Andric 
Warning(SMLoc L,const Twine & Msg)1150b57cec5SDimitry Andric   void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Error(SMLoc L,const Twine & Msg)1160b57cec5SDimitry Andric   bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
1170b57cec5SDimitry Andric   bool ParseDirectiveFalign(unsigned Size, SMLoc L);
1180b57cec5SDimitry Andric 
1195f757f3fSDimitry Andric   bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
1205f757f3fSDimitry Andric   ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1215ffd83dbSDimitry Andric                                SMLoc &EndLoc) override;
1220b57cec5SDimitry Andric   bool ParseDirectiveSubsection(SMLoc L);
1230b57cec5SDimitry Andric   bool ParseDirectiveComm(bool IsLocal, SMLoc L);
124*0fca6ea1SDimitry Andric 
125*0fca6ea1SDimitry Andric   bool parseDirectiveAttribute(SMLoc L);
126*0fca6ea1SDimitry Andric 
1270b57cec5SDimitry Andric   bool RegisterMatchesArch(unsigned MatchNum) const;
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   bool matchBundleOptions();
1300b57cec5SDimitry Andric   bool handleNoncontigiousRegister(bool Contigious, SMLoc &Loc);
1310b57cec5SDimitry Andric   bool finishBundle(SMLoc IDLoc, MCStreamer &Out);
1320b57cec5SDimitry Andric   void canonicalizeImmediates(MCInst &MCI);
1330b57cec5SDimitry Andric   bool matchOneInstruction(MCInst &MCB, SMLoc IDLoc,
1340b57cec5SDimitry Andric                            OperandVector &InstOperands, uint64_t &ErrorInfo,
1350b57cec5SDimitry Andric                            bool MatchingInlineAsm);
1360b57cec5SDimitry Andric   void eatToEndOfPacket();
1370b57cec5SDimitry Andric   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1380b57cec5SDimitry Andric                                OperandVector &Operands, MCStreamer &Out,
1390b57cec5SDimitry Andric                                uint64_t &ErrorInfo,
1400b57cec5SDimitry Andric                                bool MatchingInlineAsm) override;
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
1430b57cec5SDimitry Andric                                       unsigned Kind) override;
1440b57cec5SDimitry Andric   bool OutOfRange(SMLoc IDLoc, long long Val, long long Max);
1450b57cec5SDimitry Andric   int processInstruction(MCInst &Inst, OperandVector const &Operands,
1460b57cec5SDimitry Andric                          SMLoc IDLoc);
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   unsigned matchRegister(StringRef Name);
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric /// @name Auto-generated Match Functions
1510b57cec5SDimitry Andric /// {
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric #define GET_ASSEMBLER_HEADER
1540b57cec5SDimitry Andric #include "HexagonGenAsmMatcher.inc"
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   /// }
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric public:
HexagonAsmParser(const MCSubtargetInfo & _STI,MCAsmParser & _Parser,const MCInstrInfo & MII,const MCTargetOptions & Options)1590b57cec5SDimitry Andric   HexagonAsmParser(const MCSubtargetInfo &_STI, MCAsmParser &_Parser,
1600b57cec5SDimitry Andric                    const MCInstrInfo &MII, const MCTargetOptions &Options)
1610b57cec5SDimitry Andric     : MCTargetAsmParser(Options, _STI, MII), Parser(_Parser),
1620b57cec5SDimitry Andric       InBrackets(false) {
1630b57cec5SDimitry Andric     MCB.setOpcode(Hexagon::BUNDLE);
1640b57cec5SDimitry Andric     setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric     Parser.addAliasForDirective(".half", ".2byte");
1670b57cec5SDimitry Andric     Parser.addAliasForDirective(".hword", ".2byte");
1680b57cec5SDimitry Andric     Parser.addAliasForDirective(".word", ".4byte");
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric     MCAsmParserExtension::Initialize(_Parser);
171*0fca6ea1SDimitry Andric 
172*0fca6ea1SDimitry Andric     if (AddBuildAttributes)
173*0fca6ea1SDimitry Andric       getTargetStreamer().emitTargetAttributes(*STI);
1740b57cec5SDimitry Andric   }
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric   bool splitIdentifier(OperandVector &Operands);
1770b57cec5SDimitry Andric   bool parseOperand(OperandVector &Operands);
1780b57cec5SDimitry Andric   bool parseInstruction(OperandVector &Operands);
1790b57cec5SDimitry Andric   bool implicitExpressionLocation(OperandVector &Operands);
1800b57cec5SDimitry Andric   bool parseExpressionOrOperand(OperandVector &Operands);
1810b57cec5SDimitry Andric   bool parseExpression(MCExpr const *&Expr);
1820b57cec5SDimitry Andric 
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)1830b57cec5SDimitry Andric   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
1840b57cec5SDimitry Andric                         SMLoc NameLoc, OperandVector &Operands) override {
1850b57cec5SDimitry Andric     llvm_unreachable("Unimplemented");
1860b57cec5SDimitry Andric   }
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, AsmToken ID,
1890b57cec5SDimitry Andric                         OperandVector &Operands) override;
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   bool ParseDirective(AsmToken DirectiveID) override;
1920b57cec5SDimitry Andric };
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric /// HexagonOperand - Instances of this class represent a parsed Hexagon machine
1950b57cec5SDimitry Andric /// instruction.
1960b57cec5SDimitry Andric struct HexagonOperand : public MCParsedAsmOperand {
1970b57cec5SDimitry Andric   enum KindTy { Token, Immediate, Register } Kind;
1980b57cec5SDimitry Andric   MCContext &Context;
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric   SMLoc StartLoc, EndLoc;
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric   struct TokTy {
2030b57cec5SDimitry Andric     const char *Data;
2040b57cec5SDimitry Andric     unsigned Length;
2050b57cec5SDimitry Andric   };
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   struct RegTy {
2080b57cec5SDimitry Andric     unsigned RegNum;
2090b57cec5SDimitry Andric   };
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   struct ImmTy {
2120b57cec5SDimitry Andric     const MCExpr *Val;
2130b57cec5SDimitry Andric   };
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   union {
2160b57cec5SDimitry Andric     struct TokTy Tok;
2170b57cec5SDimitry Andric     struct RegTy Reg;
2180b57cec5SDimitry Andric     struct ImmTy Imm;
2190b57cec5SDimitry Andric   };
2200b57cec5SDimitry Andric 
HexagonOperand__anon5fe924b40111::HexagonOperand22104eeddc0SDimitry Andric   HexagonOperand(KindTy K, MCContext &Context) : Kind(K), Context(Context) {}
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric public:
HexagonOperand__anon5fe924b40111::HexagonOperand2240b57cec5SDimitry Andric   HexagonOperand(const HexagonOperand &o)
2250b57cec5SDimitry Andric       : MCParsedAsmOperand(), Context(o.Context) {
2260b57cec5SDimitry Andric     Kind = o.Kind;
2270b57cec5SDimitry Andric     StartLoc = o.StartLoc;
2280b57cec5SDimitry Andric     EndLoc = o.EndLoc;
2290b57cec5SDimitry Andric     switch (Kind) {
2300b57cec5SDimitry Andric     case Register:
2310b57cec5SDimitry Andric       Reg = o.Reg;
2320b57cec5SDimitry Andric       break;
2330b57cec5SDimitry Andric     case Immediate:
2340b57cec5SDimitry Andric       Imm = o.Imm;
2350b57cec5SDimitry Andric       break;
2360b57cec5SDimitry Andric     case Token:
2370b57cec5SDimitry Andric       Tok = o.Tok;
2380b57cec5SDimitry Andric       break;
2390b57cec5SDimitry Andric     }
2400b57cec5SDimitry Andric   }
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric   /// getStartLoc - Get the location of the first token of this operand.
getStartLoc__anon5fe924b40111::HexagonOperand2430b57cec5SDimitry Andric   SMLoc getStartLoc() const override { return StartLoc; }
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric   /// getEndLoc - Get the location of the last token of this operand.
getEndLoc__anon5fe924b40111::HexagonOperand2460b57cec5SDimitry Andric   SMLoc getEndLoc() const override { return EndLoc; }
2470b57cec5SDimitry Andric 
getReg__anon5fe924b40111::HexagonOperand248*0fca6ea1SDimitry Andric   MCRegister getReg() const override {
2490b57cec5SDimitry Andric     assert(Kind == Register && "Invalid access!");
2500b57cec5SDimitry Andric     return Reg.RegNum;
2510b57cec5SDimitry Andric   }
2520b57cec5SDimitry Andric 
getImm__anon5fe924b40111::HexagonOperand2530b57cec5SDimitry Andric   const MCExpr *getImm() const {
2540b57cec5SDimitry Andric     assert(Kind == Immediate && "Invalid access!");
2550b57cec5SDimitry Andric     return Imm.Val;
2560b57cec5SDimitry Andric   }
2570b57cec5SDimitry Andric 
isToken__anon5fe924b40111::HexagonOperand2580b57cec5SDimitry Andric   bool isToken() const override { return Kind == Token; }
isImm__anon5fe924b40111::HexagonOperand2590b57cec5SDimitry Andric   bool isImm() const override { return Kind == Immediate; }
isMem__anon5fe924b40111::HexagonOperand2600b57cec5SDimitry Andric   bool isMem() const override { llvm_unreachable("No isMem"); }
isReg__anon5fe924b40111::HexagonOperand2610b57cec5SDimitry Andric   bool isReg() const override { return Kind == Register; }
2620b57cec5SDimitry Andric 
CheckImmRange__anon5fe924b40111::HexagonOperand2630b57cec5SDimitry Andric   bool CheckImmRange(int immBits, int zeroBits, bool isSigned,
2640b57cec5SDimitry Andric                      bool isRelocatable, bool Extendable) const {
2650b57cec5SDimitry Andric     if (Kind == Immediate) {
2660b57cec5SDimitry Andric       const MCExpr *myMCExpr = &HexagonMCInstrInfo::getExpr(*getImm());
2670b57cec5SDimitry Andric       if (HexagonMCInstrInfo::mustExtend(*Imm.Val) && !Extendable)
2680b57cec5SDimitry Andric         return false;
2690b57cec5SDimitry Andric       int64_t Res;
2700b57cec5SDimitry Andric       if (myMCExpr->evaluateAsAbsolute(Res)) {
2710b57cec5SDimitry Andric         int bits = immBits + zeroBits;
2720b57cec5SDimitry Andric         // Field bit range is zerobits + bits
2730b57cec5SDimitry Andric         // zeroBits must be 0
2740b57cec5SDimitry Andric         if (Res & ((1 << zeroBits) - 1))
2750b57cec5SDimitry Andric           return false;
2760b57cec5SDimitry Andric         if (isSigned) {
2770b57cec5SDimitry Andric           if (Res < (1LL << (bits - 1)) && Res >= -(1LL << (bits - 1)))
2780b57cec5SDimitry Andric             return true;
2790b57cec5SDimitry Andric         } else {
2800b57cec5SDimitry Andric           if (bits == 64)
2810b57cec5SDimitry Andric             return true;
2820b57cec5SDimitry Andric           if (Res >= 0)
2830b57cec5SDimitry Andric             return ((uint64_t)Res < (uint64_t)(1ULL << bits));
2840b57cec5SDimitry Andric           else {
2850b57cec5SDimitry Andric             const int64_t high_bit_set = 1ULL << 63;
2860b57cec5SDimitry Andric             const uint64_t mask = (high_bit_set >> (63 - bits));
2870b57cec5SDimitry Andric             return (((uint64_t)Res & mask) == mask);
2880b57cec5SDimitry Andric           }
2890b57cec5SDimitry Andric         }
2900b57cec5SDimitry Andric       } else if (myMCExpr->getKind() == MCExpr::SymbolRef && isRelocatable)
2910b57cec5SDimitry Andric         return true;
2920b57cec5SDimitry Andric       else if (myMCExpr->getKind() == MCExpr::Binary ||
2930b57cec5SDimitry Andric                myMCExpr->getKind() == MCExpr::Unary)
2940b57cec5SDimitry Andric         return true;
2950b57cec5SDimitry Andric     }
2960b57cec5SDimitry Andric     return false;
2970b57cec5SDimitry Andric   }
2980b57cec5SDimitry Andric 
isa30_2Imm__anon5fe924b40111::HexagonOperand2990b57cec5SDimitry Andric   bool isa30_2Imm() const { return CheckImmRange(30, 2, true, true, true); }
isb30_2Imm__anon5fe924b40111::HexagonOperand3000b57cec5SDimitry Andric   bool isb30_2Imm() const { return CheckImmRange(30, 2, true, true, true); }
isb15_2Imm__anon5fe924b40111::HexagonOperand3010b57cec5SDimitry Andric   bool isb15_2Imm() const { return CheckImmRange(15, 2, true, true, false); }
isb13_2Imm__anon5fe924b40111::HexagonOperand3020b57cec5SDimitry Andric   bool isb13_2Imm() const { return CheckImmRange(13, 2, true, true, false); }
3030b57cec5SDimitry Andric 
ism32_0Imm__anon5fe924b40111::HexagonOperand3040b57cec5SDimitry Andric   bool ism32_0Imm() const { return true; }
3050b57cec5SDimitry Andric 
isf32Imm__anon5fe924b40111::HexagonOperand3060b57cec5SDimitry Andric   bool isf32Imm() const { return false; }
isf64Imm__anon5fe924b40111::HexagonOperand3070b57cec5SDimitry Andric   bool isf64Imm() const { return false; }
iss32_0Imm__anon5fe924b40111::HexagonOperand3080b57cec5SDimitry Andric   bool iss32_0Imm() const { return true; }
iss31_1Imm__anon5fe924b40111::HexagonOperand3090b57cec5SDimitry Andric   bool iss31_1Imm() const { return true; }
iss30_2Imm__anon5fe924b40111::HexagonOperand3100b57cec5SDimitry Andric   bool iss30_2Imm() const { return true; }
iss29_3Imm__anon5fe924b40111::HexagonOperand3110b57cec5SDimitry Andric   bool iss29_3Imm() const { return true; }
iss27_2Imm__anon5fe924b40111::HexagonOperand3120b57cec5SDimitry Andric   bool iss27_2Imm() const { return CheckImmRange(27, 2, true, true, false); }
iss10_0Imm__anon5fe924b40111::HexagonOperand3135ffd83dbSDimitry Andric   bool iss10_0Imm() const { return CheckImmRange(10, 0, true, false, false); }
iss10_6Imm__anon5fe924b40111::HexagonOperand3145ffd83dbSDimitry Andric   bool iss10_6Imm() const { return CheckImmRange(10, 6, true, false, false); }
iss9_0Imm__anon5fe924b40111::HexagonOperand3150b57cec5SDimitry Andric   bool iss9_0Imm() const { return CheckImmRange(9, 0, true, false, false); }
iss8_0Imm__anon5fe924b40111::HexagonOperand3160b57cec5SDimitry Andric   bool iss8_0Imm() const { return CheckImmRange(8, 0, true, false, false); }
iss8_0Imm64__anon5fe924b40111::HexagonOperand3170b57cec5SDimitry Andric   bool iss8_0Imm64() const { return CheckImmRange(8, 0, true, true, false); }
iss7_0Imm__anon5fe924b40111::HexagonOperand3180b57cec5SDimitry Andric   bool iss7_0Imm() const { return CheckImmRange(7, 0, true, false, false); }
iss6_0Imm__anon5fe924b40111::HexagonOperand3190b57cec5SDimitry Andric   bool iss6_0Imm() const { return CheckImmRange(6, 0, true, false, false); }
iss6_3Imm__anon5fe924b40111::HexagonOperand3200b57cec5SDimitry Andric   bool iss6_3Imm() const { return CheckImmRange(6, 3, true, false, false); }
iss4_0Imm__anon5fe924b40111::HexagonOperand3210b57cec5SDimitry Andric   bool iss4_0Imm() const { return CheckImmRange(4, 0, true, false, false); }
iss4_1Imm__anon5fe924b40111::HexagonOperand3220b57cec5SDimitry Andric   bool iss4_1Imm() const { return CheckImmRange(4, 1, true, false, false); }
iss4_2Imm__anon5fe924b40111::HexagonOperand3230b57cec5SDimitry Andric   bool iss4_2Imm() const { return CheckImmRange(4, 2, true, false, false); }
iss4_3Imm__anon5fe924b40111::HexagonOperand3240b57cec5SDimitry Andric   bool iss4_3Imm() const { return CheckImmRange(4, 3, true, false, false); }
iss3_0Imm__anon5fe924b40111::HexagonOperand3250b57cec5SDimitry Andric   bool iss3_0Imm() const { return CheckImmRange(3, 0, true, false, false); }
3260b57cec5SDimitry Andric 
isu64_0Imm__anon5fe924b40111::HexagonOperand3270b57cec5SDimitry Andric   bool isu64_0Imm() const { return CheckImmRange(64, 0, false, true, true); }
isu32_0Imm__anon5fe924b40111::HexagonOperand3280b57cec5SDimitry Andric   bool isu32_0Imm() const { return true; }
isu31_1Imm__anon5fe924b40111::HexagonOperand3290b57cec5SDimitry Andric   bool isu31_1Imm() const { return true; }
isu30_2Imm__anon5fe924b40111::HexagonOperand3300b57cec5SDimitry Andric   bool isu30_2Imm() const { return true; }
isu29_3Imm__anon5fe924b40111::HexagonOperand3310b57cec5SDimitry Andric   bool isu29_3Imm() const { return true; }
isu26_6Imm__anon5fe924b40111::HexagonOperand3320b57cec5SDimitry Andric   bool isu26_6Imm() const { return CheckImmRange(26, 6, false, true, false); }
isu16_0Imm__anon5fe924b40111::HexagonOperand3330b57cec5SDimitry Andric   bool isu16_0Imm() const { return CheckImmRange(16, 0, false, true, false); }
isu16_1Imm__anon5fe924b40111::HexagonOperand3340b57cec5SDimitry Andric   bool isu16_1Imm() const { return CheckImmRange(16, 1, false, true, false); }
isu16_2Imm__anon5fe924b40111::HexagonOperand3350b57cec5SDimitry Andric   bool isu16_2Imm() const { return CheckImmRange(16, 2, false, true, false); }
isu16_3Imm__anon5fe924b40111::HexagonOperand3360b57cec5SDimitry Andric   bool isu16_3Imm() const { return CheckImmRange(16, 3, false, true, false); }
isu11_3Imm__anon5fe924b40111::HexagonOperand3370b57cec5SDimitry Andric   bool isu11_3Imm() const { return CheckImmRange(11, 3, false, false, false); }
isu10_0Imm__anon5fe924b40111::HexagonOperand3380b57cec5SDimitry Andric   bool isu10_0Imm() const { return CheckImmRange(10, 0, false, false, false); }
isu9_0Imm__anon5fe924b40111::HexagonOperand3390b57cec5SDimitry Andric   bool isu9_0Imm() const { return CheckImmRange(9, 0, false, false, false); }
isu8_0Imm__anon5fe924b40111::HexagonOperand3400b57cec5SDimitry Andric   bool isu8_0Imm() const { return CheckImmRange(8, 0, false, false, false); }
isu7_0Imm__anon5fe924b40111::HexagonOperand3410b57cec5SDimitry Andric   bool isu7_0Imm() const { return CheckImmRange(7, 0, false, false, false); }
isu6_0Imm__anon5fe924b40111::HexagonOperand3420b57cec5SDimitry Andric   bool isu6_0Imm() const { return CheckImmRange(6, 0, false, false, false); }
isu6_1Imm__anon5fe924b40111::HexagonOperand3430b57cec5SDimitry Andric   bool isu6_1Imm() const { return CheckImmRange(6, 1, false, false, false); }
isu6_2Imm__anon5fe924b40111::HexagonOperand3440b57cec5SDimitry Andric   bool isu6_2Imm() const { return CheckImmRange(6, 2, false, false, false); }
isu6_3Imm__anon5fe924b40111::HexagonOperand3450b57cec5SDimitry Andric   bool isu6_3Imm() const { return CheckImmRange(6, 3, false, false, false); }
isu5_0Imm__anon5fe924b40111::HexagonOperand3460b57cec5SDimitry Andric   bool isu5_0Imm() const { return CheckImmRange(5, 0, false, false, false); }
isu5_2Imm__anon5fe924b40111::HexagonOperand3470b57cec5SDimitry Andric   bool isu5_2Imm() const { return CheckImmRange(5, 2, false, false, false); }
isu5_3Imm__anon5fe924b40111::HexagonOperand3480b57cec5SDimitry Andric   bool isu5_3Imm() const { return CheckImmRange(5, 3, false, false, false); }
isu4_0Imm__anon5fe924b40111::HexagonOperand3490b57cec5SDimitry Andric   bool isu4_0Imm() const { return CheckImmRange(4, 0, false, false, false); }
isu4_2Imm__anon5fe924b40111::HexagonOperand3500b57cec5SDimitry Andric   bool isu4_2Imm() const { return CheckImmRange(4, 2, false, false, false); }
isu3_0Imm__anon5fe924b40111::HexagonOperand3510b57cec5SDimitry Andric   bool isu3_0Imm() const { return CheckImmRange(3, 0, false, false, false); }
isu3_1Imm__anon5fe924b40111::HexagonOperand3520b57cec5SDimitry Andric   bool isu3_1Imm() const { return CheckImmRange(3, 1, false, false, false); }
isu2_0Imm__anon5fe924b40111::HexagonOperand3530b57cec5SDimitry Andric   bool isu2_0Imm() const { return CheckImmRange(2, 0, false, false, false); }
isu1_0Imm__anon5fe924b40111::HexagonOperand3540b57cec5SDimitry Andric   bool isu1_0Imm() const { return CheckImmRange(1, 0, false, false, false); }
3550b57cec5SDimitry Andric 
isn1Const__anon5fe924b40111::HexagonOperand3560b57cec5SDimitry Andric   bool isn1Const() const {
3570b57cec5SDimitry Andric     if (!isImm())
3580b57cec5SDimitry Andric       return false;
3590b57cec5SDimitry Andric     int64_t Value;
3600b57cec5SDimitry Andric     if (!getImm()->evaluateAsAbsolute(Value))
3610b57cec5SDimitry Andric       return false;
3620b57cec5SDimitry Andric     return Value == -1;
3630b57cec5SDimitry Andric   }
issgp10Const__anon5fe924b40111::HexagonOperand364bdd1243dSDimitry Andric   bool issgp10Const() const {
365bdd1243dSDimitry Andric     if (!isReg())
366bdd1243dSDimitry Andric       return false;
367bdd1243dSDimitry Andric     return getReg() == Hexagon::SGP1_0;
368bdd1243dSDimitry Andric   }
iss11_0Imm__anon5fe924b40111::HexagonOperand3690b57cec5SDimitry Andric   bool iss11_0Imm() const {
3700b57cec5SDimitry Andric     return CheckImmRange(11 + 26, 0, true, true, true);
3710b57cec5SDimitry Andric   }
iss11_1Imm__anon5fe924b40111::HexagonOperand3720b57cec5SDimitry Andric   bool iss11_1Imm() const {
3730b57cec5SDimitry Andric     return CheckImmRange(11 + 26, 1, true, true, true);
3740b57cec5SDimitry Andric   }
iss11_2Imm__anon5fe924b40111::HexagonOperand3750b57cec5SDimitry Andric   bool iss11_2Imm() const {
3760b57cec5SDimitry Andric     return CheckImmRange(11 + 26, 2, true, true, true);
3770b57cec5SDimitry Andric   }
iss11_3Imm__anon5fe924b40111::HexagonOperand3780b57cec5SDimitry Andric   bool iss11_3Imm() const {
3790b57cec5SDimitry Andric     return CheckImmRange(11 + 26, 3, true, true, true);
3800b57cec5SDimitry Andric   }
isu32_0MustExt__anon5fe924b40111::HexagonOperand3810b57cec5SDimitry Andric   bool isu32_0MustExt() const { return isImm(); }
3820b57cec5SDimitry Andric 
addRegOperands__anon5fe924b40111::HexagonOperand3830b57cec5SDimitry Andric   void addRegOperands(MCInst &Inst, unsigned N) const {
3840b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
3850b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getReg()));
3860b57cec5SDimitry Andric   }
3870b57cec5SDimitry Andric 
addImmOperands__anon5fe924b40111::HexagonOperand3880b57cec5SDimitry Andric   void addImmOperands(MCInst &Inst, unsigned N) const {
3890b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
3900b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createExpr(getImm()));
3910b57cec5SDimitry Andric   }
3920b57cec5SDimitry Andric 
addSignedImmOperands__anon5fe924b40111::HexagonOperand3930b57cec5SDimitry Andric   void addSignedImmOperands(MCInst &Inst, unsigned N) const {
3940b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
3950b57cec5SDimitry Andric     HexagonMCExpr *Expr =
3960b57cec5SDimitry Andric         const_cast<HexagonMCExpr *>(cast<HexagonMCExpr>(getImm()));
3970b57cec5SDimitry Andric     int64_t Value;
3980b57cec5SDimitry Andric     if (!Expr->evaluateAsAbsolute(Value)) {
3990b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createExpr(Expr));
4000b57cec5SDimitry Andric       return;
4010b57cec5SDimitry Andric     }
4020b57cec5SDimitry Andric     int64_t Extended = SignExtend64(Value, 32);
4030b57cec5SDimitry Andric     HexagonMCExpr *NewExpr = HexagonMCExpr::create(
4040b57cec5SDimitry Andric         MCConstantExpr::create(Extended, Context), Context);
4050b57cec5SDimitry Andric     if ((Extended < 0) != (Value < 0))
4060b57cec5SDimitry Andric       NewExpr->setSignMismatch();
4070b57cec5SDimitry Andric     NewExpr->setMustExtend(Expr->mustExtend());
4080b57cec5SDimitry Andric     NewExpr->setMustNotExtend(Expr->mustNotExtend());
4090b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createExpr(NewExpr));
4100b57cec5SDimitry Andric   }
4110b57cec5SDimitry Andric 
addn1ConstOperands__anon5fe924b40111::HexagonOperand4120b57cec5SDimitry Andric   void addn1ConstOperands(MCInst &Inst, unsigned N) const {
4130b57cec5SDimitry Andric     addImmOperands(Inst, N);
4140b57cec5SDimitry Andric   }
addsgp10ConstOperands__anon5fe924b40111::HexagonOperand415bdd1243dSDimitry Andric   void addsgp10ConstOperands(MCInst &Inst, unsigned N) const {
416bdd1243dSDimitry Andric     addRegOperands(Inst, N);
417bdd1243dSDimitry Andric   }
4180b57cec5SDimitry Andric 
getToken__anon5fe924b40111::HexagonOperand4190b57cec5SDimitry Andric   StringRef getToken() const {
4200b57cec5SDimitry Andric     assert(Kind == Token && "Invalid access!");
4210b57cec5SDimitry Andric     return StringRef(Tok.Data, Tok.Length);
4220b57cec5SDimitry Andric   }
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric   void print(raw_ostream &OS) const override;
4250b57cec5SDimitry Andric 
CreateToken__anon5fe924b40111::HexagonOperand4260b57cec5SDimitry Andric   static std::unique_ptr<HexagonOperand> CreateToken(MCContext &Context,
4270b57cec5SDimitry Andric                                                      StringRef Str, SMLoc S) {
4280b57cec5SDimitry Andric     HexagonOperand *Op = new HexagonOperand(Token, Context);
4290b57cec5SDimitry Andric     Op->Tok.Data = Str.data();
4300b57cec5SDimitry Andric     Op->Tok.Length = Str.size();
4310b57cec5SDimitry Andric     Op->StartLoc = S;
4320b57cec5SDimitry Andric     Op->EndLoc = S;
4330b57cec5SDimitry Andric     return std::unique_ptr<HexagonOperand>(Op);
4340b57cec5SDimitry Andric   }
4350b57cec5SDimitry Andric 
4360b57cec5SDimitry Andric   static std::unique_ptr<HexagonOperand>
CreateReg__anon5fe924b40111::HexagonOperand4370b57cec5SDimitry Andric   CreateReg(MCContext &Context, unsigned RegNum, SMLoc S, SMLoc E) {
4380b57cec5SDimitry Andric     HexagonOperand *Op = new HexagonOperand(Register, Context);
4390b57cec5SDimitry Andric     Op->Reg.RegNum = RegNum;
4400b57cec5SDimitry Andric     Op->StartLoc = S;
4410b57cec5SDimitry Andric     Op->EndLoc = E;
4420b57cec5SDimitry Andric     return std::unique_ptr<HexagonOperand>(Op);
4430b57cec5SDimitry Andric   }
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric   static std::unique_ptr<HexagonOperand>
CreateImm__anon5fe924b40111::HexagonOperand4460b57cec5SDimitry Andric   CreateImm(MCContext &Context, const MCExpr *Val, SMLoc S, SMLoc E) {
4470b57cec5SDimitry Andric     HexagonOperand *Op = new HexagonOperand(Immediate, Context);
4480b57cec5SDimitry Andric     Op->Imm.Val = Val;
4490b57cec5SDimitry Andric     Op->StartLoc = S;
4500b57cec5SDimitry Andric     Op->EndLoc = E;
4510b57cec5SDimitry Andric     return std::unique_ptr<HexagonOperand>(Op);
4520b57cec5SDimitry Andric   }
4530b57cec5SDimitry Andric };
4540b57cec5SDimitry Andric 
4550b57cec5SDimitry Andric } // end anonymous namespace
4560b57cec5SDimitry Andric 
print(raw_ostream & OS) const4570b57cec5SDimitry Andric void HexagonOperand::print(raw_ostream &OS) const {
4580b57cec5SDimitry Andric   switch (Kind) {
4590b57cec5SDimitry Andric   case Immediate:
4600b57cec5SDimitry Andric     getImm()->print(OS, nullptr);
4610b57cec5SDimitry Andric     break;
4620b57cec5SDimitry Andric   case Register:
4630b57cec5SDimitry Andric     OS << "<register R";
4640b57cec5SDimitry Andric     OS << getReg() << ">";
4650b57cec5SDimitry Andric     break;
4660b57cec5SDimitry Andric   case Token:
4670b57cec5SDimitry Andric     OS << "'" << getToken() << "'";
4680b57cec5SDimitry Andric     break;
4690b57cec5SDimitry Andric   }
4700b57cec5SDimitry Andric }
4710b57cec5SDimitry Andric 
finishBundle(SMLoc IDLoc,MCStreamer & Out)4720b57cec5SDimitry Andric bool HexagonAsmParser::finishBundle(SMLoc IDLoc, MCStreamer &Out) {
4730b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Bundle:");
4740b57cec5SDimitry Andric   LLVM_DEBUG(MCB.dump_pretty(dbgs()));
4750b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "--\n");
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric   MCB.setLoc(IDLoc);
4785ffd83dbSDimitry Andric 
4790b57cec5SDimitry Andric   // Check the bundle for errors.
4800b57cec5SDimitry Andric   const MCRegisterInfo *RI = getContext().getRegisterInfo();
4815ffd83dbSDimitry Andric   MCSubtargetInfo const &STI = getSTI();
4820b57cec5SDimitry Andric 
4835ffd83dbSDimitry Andric   MCInst OrigBundle = MCB;
4845ffd83dbSDimitry Andric   HexagonMCChecker Check(getContext(), MII, STI, MCB, *RI, true);
4855ffd83dbSDimitry Andric 
4865ffd83dbSDimitry Andric   bool CheckOk = HexagonMCInstrInfo::canonicalizePacket(
4875ffd83dbSDimitry Andric       MII, STI, getContext(), MCB, &Check, true);
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric   if (CheckOk) {
4900b57cec5SDimitry Andric     if (HexagonMCInstrInfo::bundleSize(MCB) == 0) {
4910b57cec5SDimitry Andric       assert(!HexagonMCInstrInfo::isInnerLoop(MCB));
4920b57cec5SDimitry Andric       assert(!HexagonMCInstrInfo::isOuterLoop(MCB));
4930b57cec5SDimitry Andric       // Empty packets are valid yet aren't emitted
4940b57cec5SDimitry Andric       return false;
4950b57cec5SDimitry Andric     }
4965ffd83dbSDimitry Andric 
4975ffd83dbSDimitry Andric     assert(HexagonMCInstrInfo::isBundle(MCB));
4985ffd83dbSDimitry Andric 
4995ffd83dbSDimitry Andric     Out.emitInstruction(MCB, STI);
5005ffd83dbSDimitry Andric   } else
5010b57cec5SDimitry Andric     return true; // Error
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric   return false; // No error
5040b57cec5SDimitry Andric }
5050b57cec5SDimitry Andric 
matchBundleOptions()5060b57cec5SDimitry Andric bool HexagonAsmParser::matchBundleOptions() {
5070b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
5080b57cec5SDimitry Andric   while (true) {
5090b57cec5SDimitry Andric     if (!Parser.getTok().is(AsmToken::Colon))
5100b57cec5SDimitry Andric       return false;
5110b57cec5SDimitry Andric     Lex();
5120b57cec5SDimitry Andric     char const *MemNoShuffMsg =
5130b57cec5SDimitry Andric         "invalid instruction packet: mem_noshuf specifier not "
5140b57cec5SDimitry Andric         "supported with this architecture";
5150b57cec5SDimitry Andric     StringRef Option = Parser.getTok().getString();
5160b57cec5SDimitry Andric     auto IDLoc = Parser.getTok().getLoc();
517fe6060f1SDimitry Andric     if (Option.compare_insensitive("endloop01") == 0) {
5180b57cec5SDimitry Andric       HexagonMCInstrInfo::setInnerLoop(MCB);
5190b57cec5SDimitry Andric       HexagonMCInstrInfo::setOuterLoop(MCB);
520fe6060f1SDimitry Andric     } else if (Option.compare_insensitive("endloop0") == 0) {
5210b57cec5SDimitry Andric       HexagonMCInstrInfo::setInnerLoop(MCB);
522fe6060f1SDimitry Andric     } else if (Option.compare_insensitive("endloop1") == 0) {
5230b57cec5SDimitry Andric       HexagonMCInstrInfo::setOuterLoop(MCB);
524fe6060f1SDimitry Andric     } else if (Option.compare_insensitive("mem_noshuf") == 0) {
52506c3fb27SDimitry Andric       if (getSTI().hasFeature(Hexagon::FeatureMemNoShuf))
5260b57cec5SDimitry Andric         HexagonMCInstrInfo::setMemReorderDisabled(MCB);
5270b57cec5SDimitry Andric       else
5280b57cec5SDimitry Andric         return getParser().Error(IDLoc, MemNoShuffMsg);
529fe6060f1SDimitry Andric     } else if (Option.compare_insensitive("mem_no_order") == 0) {
5305ffd83dbSDimitry Andric       // Nothing.
5310b57cec5SDimitry Andric     } else
5320b57cec5SDimitry Andric       return getParser().Error(IDLoc, llvm::Twine("'") + Option +
5330b57cec5SDimitry Andric                                           "' is not a valid bundle option");
5340b57cec5SDimitry Andric     Lex();
5350b57cec5SDimitry Andric   }
5360b57cec5SDimitry Andric }
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric // For instruction aliases, immediates are generated rather than
5390b57cec5SDimitry Andric // MCConstantExpr.  Convert them for uniform MCExpr.
5400b57cec5SDimitry Andric // Also check for signed/unsigned mismatches and warn
canonicalizeImmediates(MCInst & MCI)5410b57cec5SDimitry Andric void HexagonAsmParser::canonicalizeImmediates(MCInst &MCI) {
5420b57cec5SDimitry Andric   MCInst NewInst;
5430b57cec5SDimitry Andric   NewInst.setOpcode(MCI.getOpcode());
5440b57cec5SDimitry Andric   for (MCOperand &I : MCI)
5450b57cec5SDimitry Andric     if (I.isImm()) {
5460b57cec5SDimitry Andric       int64_t Value(I.getImm());
5470b57cec5SDimitry Andric       NewInst.addOperand(MCOperand::createExpr(HexagonMCExpr::create(
5480b57cec5SDimitry Andric           MCConstantExpr::create(Value, getContext()), getContext())));
5490b57cec5SDimitry Andric     } else {
5500b57cec5SDimitry Andric       if (I.isExpr() && cast<HexagonMCExpr>(I.getExpr())->signMismatch() &&
5510b57cec5SDimitry Andric           WarnSignedMismatch)
5520b57cec5SDimitry Andric         Warning(MCI.getLoc(), "Signed/Unsigned mismatch");
5530b57cec5SDimitry Andric       NewInst.addOperand(I);
5540b57cec5SDimitry Andric     }
5550b57cec5SDimitry Andric   MCI = NewInst;
5560b57cec5SDimitry Andric }
5570b57cec5SDimitry Andric 
matchOneInstruction(MCInst & MCI,SMLoc IDLoc,OperandVector & InstOperands,uint64_t & ErrorInfo,bool MatchingInlineAsm)5580b57cec5SDimitry Andric bool HexagonAsmParser::matchOneInstruction(MCInst &MCI, SMLoc IDLoc,
5590b57cec5SDimitry Andric                                            OperandVector &InstOperands,
5600b57cec5SDimitry Andric                                            uint64_t &ErrorInfo,
5610b57cec5SDimitry Andric                                            bool MatchingInlineAsm) {
5620b57cec5SDimitry Andric   // Perform matching with tablegen asmmatcher generated function
5630b57cec5SDimitry Andric   int result =
5640b57cec5SDimitry Andric       MatchInstructionImpl(InstOperands, MCI, ErrorInfo, MatchingInlineAsm);
5650b57cec5SDimitry Andric   if (result == Match_Success) {
5660b57cec5SDimitry Andric     MCI.setLoc(IDLoc);
5670b57cec5SDimitry Andric     canonicalizeImmediates(MCI);
5680b57cec5SDimitry Andric     result = processInstruction(MCI, InstOperands, IDLoc);
5690b57cec5SDimitry Andric 
5700b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Insn:");
5710b57cec5SDimitry Andric     LLVM_DEBUG(MCI.dump_pretty(dbgs()));
5720b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "\n\n");
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric     MCI.setLoc(IDLoc);
5750b57cec5SDimitry Andric   }
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric   // Create instruction operand for bundle instruction
5780b57cec5SDimitry Andric   //   Break this into a separate function Code here is less readable
5790b57cec5SDimitry Andric   //   Think about how to get an instruction error to report correctly.
5800b57cec5SDimitry Andric   //   SMLoc will return the "{"
5810b57cec5SDimitry Andric   switch (result) {
5820b57cec5SDimitry Andric   default:
5830b57cec5SDimitry Andric     break;
5840b57cec5SDimitry Andric   case Match_Success:
5850b57cec5SDimitry Andric     return false;
5860b57cec5SDimitry Andric   case Match_MissingFeature:
5870b57cec5SDimitry Andric     return Error(IDLoc, "invalid instruction");
5880b57cec5SDimitry Andric   case Match_MnemonicFail:
5890b57cec5SDimitry Andric     return Error(IDLoc, "unrecognized instruction");
5900b57cec5SDimitry Andric   case Match_InvalidOperand:
591bdd1243dSDimitry Andric     [[fallthrough]];
5920b57cec5SDimitry Andric   case Match_InvalidTiedOperand:
5930b57cec5SDimitry Andric     SMLoc ErrorLoc = IDLoc;
5940b57cec5SDimitry Andric     if (ErrorInfo != ~0U) {
5950b57cec5SDimitry Andric       if (ErrorInfo >= InstOperands.size())
5960b57cec5SDimitry Andric         return Error(IDLoc, "too few operands for instruction");
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric       ErrorLoc = (static_cast<HexagonOperand *>(InstOperands[ErrorInfo].get()))
5990b57cec5SDimitry Andric                      ->getStartLoc();
6000b57cec5SDimitry Andric       if (ErrorLoc == SMLoc())
6010b57cec5SDimitry Andric         ErrorLoc = IDLoc;
6020b57cec5SDimitry Andric     }
6030b57cec5SDimitry Andric     return Error(ErrorLoc, "invalid operand for instruction");
6040b57cec5SDimitry Andric   }
6050b57cec5SDimitry Andric   llvm_unreachable("Implement any new match types added!");
6060b57cec5SDimitry Andric }
6070b57cec5SDimitry Andric 
eatToEndOfPacket()6080b57cec5SDimitry Andric void HexagonAsmParser::eatToEndOfPacket() {
6090b57cec5SDimitry Andric   assert(InBrackets);
6100b57cec5SDimitry Andric   MCAsmLexer &Lexer = getLexer();
6110b57cec5SDimitry Andric   while (!Lexer.is(AsmToken::RCurly))
6120b57cec5SDimitry Andric     Lexer.Lex();
6130b57cec5SDimitry Andric   Lexer.Lex();
6140b57cec5SDimitry Andric   InBrackets = false;
6150b57cec5SDimitry Andric }
6160b57cec5SDimitry Andric 
MatchAndEmitInstruction(SMLoc IDLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)6170b57cec5SDimitry Andric bool HexagonAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
6180b57cec5SDimitry Andric                                                OperandVector &Operands,
6190b57cec5SDimitry Andric                                                MCStreamer &Out,
6200b57cec5SDimitry Andric                                                uint64_t &ErrorInfo,
6210b57cec5SDimitry Andric                                                bool MatchingInlineAsm) {
6220b57cec5SDimitry Andric   if (!InBrackets) {
6230b57cec5SDimitry Andric     MCB.clear();
6240b57cec5SDimitry Andric     MCB.addOperand(MCOperand::createImm(0));
6250b57cec5SDimitry Andric   }
6260b57cec5SDimitry Andric   HexagonOperand &FirstOperand = static_cast<HexagonOperand &>(*Operands[0]);
6270b57cec5SDimitry Andric   if (FirstOperand.isToken() && FirstOperand.getToken() == "{") {
6280b57cec5SDimitry Andric     assert(Operands.size() == 1 && "Brackets should be by themselves");
6290b57cec5SDimitry Andric     if (InBrackets) {
6300b57cec5SDimitry Andric       getParser().Error(IDLoc, "Already in a packet");
6310b57cec5SDimitry Andric       InBrackets = false;
6320b57cec5SDimitry Andric       return true;
6330b57cec5SDimitry Andric     }
6340b57cec5SDimitry Andric     InBrackets = true;
6350b57cec5SDimitry Andric     return false;
6360b57cec5SDimitry Andric   }
6370b57cec5SDimitry Andric   if (FirstOperand.isToken() && FirstOperand.getToken() == "}") {
6380b57cec5SDimitry Andric     assert(Operands.size() == 1 && "Brackets should be by themselves");
6390b57cec5SDimitry Andric     if (!InBrackets) {
6400b57cec5SDimitry Andric       getParser().Error(IDLoc, "Not in a packet");
6410b57cec5SDimitry Andric       return true;
6420b57cec5SDimitry Andric     }
6430b57cec5SDimitry Andric     InBrackets = false;
6440b57cec5SDimitry Andric     if (matchBundleOptions())
6450b57cec5SDimitry Andric       return true;
6460b57cec5SDimitry Andric     return finishBundle(IDLoc, Out);
6470b57cec5SDimitry Andric   }
648e8d8bef9SDimitry Andric   MCInst *SubInst = getParser().getContext().createMCInst();
6490b57cec5SDimitry Andric   if (matchOneInstruction(*SubInst, IDLoc, Operands, ErrorInfo,
6500b57cec5SDimitry Andric                           MatchingInlineAsm)) {
6510b57cec5SDimitry Andric     if (InBrackets)
6520b57cec5SDimitry Andric       eatToEndOfPacket();
6530b57cec5SDimitry Andric     return true;
6540b57cec5SDimitry Andric   }
6550b57cec5SDimitry Andric   HexagonMCInstrInfo::extendIfNeeded(
6560b57cec5SDimitry Andric       getParser().getContext(), MII, MCB, *SubInst);
6570b57cec5SDimitry Andric   MCB.addOperand(MCOperand::createInst(SubInst));
6580b57cec5SDimitry Andric   if (!InBrackets)
6590b57cec5SDimitry Andric     return finishBundle(IDLoc, Out);
6600b57cec5SDimitry Andric   return false;
6610b57cec5SDimitry Andric }
662*0fca6ea1SDimitry Andric /// parseDirectiveAttribute
663*0fca6ea1SDimitry Andric ///  ::= .attribute int, int
664*0fca6ea1SDimitry Andric ///  ::= .attribute Tag_name, int
parseDirectiveAttribute(SMLoc L)665*0fca6ea1SDimitry Andric bool HexagonAsmParser::parseDirectiveAttribute(SMLoc L) {
666*0fca6ea1SDimitry Andric   MCAsmParser &Parser = getParser();
667*0fca6ea1SDimitry Andric   int64_t Tag;
668*0fca6ea1SDimitry Andric   SMLoc TagLoc = Parser.getTok().getLoc();
669*0fca6ea1SDimitry Andric   if (Parser.getTok().is(AsmToken::Identifier)) {
670*0fca6ea1SDimitry Andric     StringRef Name = Parser.getTok().getIdentifier();
671*0fca6ea1SDimitry Andric     std::optional<unsigned> Ret = ELFAttrs::attrTypeFromString(
672*0fca6ea1SDimitry Andric         Name, HexagonAttrs::getHexagonAttributeTags());
673*0fca6ea1SDimitry Andric     if (!Ret)
674*0fca6ea1SDimitry Andric       return Error(TagLoc, "attribute name not recognized: " + Name);
675*0fca6ea1SDimitry Andric     Tag = *Ret;
676*0fca6ea1SDimitry Andric     Parser.Lex();
677*0fca6ea1SDimitry Andric   } else {
678*0fca6ea1SDimitry Andric     const MCExpr *AttrExpr;
679*0fca6ea1SDimitry Andric 
680*0fca6ea1SDimitry Andric     TagLoc = Parser.getTok().getLoc();
681*0fca6ea1SDimitry Andric     if (Parser.parseExpression(AttrExpr))
682*0fca6ea1SDimitry Andric       return true;
683*0fca6ea1SDimitry Andric 
684*0fca6ea1SDimitry Andric     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
685*0fca6ea1SDimitry Andric     if (check(!CE, TagLoc, "expected numeric constant"))
686*0fca6ea1SDimitry Andric       return true;
687*0fca6ea1SDimitry Andric 
688*0fca6ea1SDimitry Andric     Tag = CE->getValue();
689*0fca6ea1SDimitry Andric   }
690*0fca6ea1SDimitry Andric 
691*0fca6ea1SDimitry Andric   if (Parser.parseComma())
692*0fca6ea1SDimitry Andric     return true;
693*0fca6ea1SDimitry Andric 
694*0fca6ea1SDimitry Andric   // We currently only have integer values.
695*0fca6ea1SDimitry Andric   int64_t IntegerValue = 0;
696*0fca6ea1SDimitry Andric   SMLoc ValueExprLoc = Parser.getTok().getLoc();
697*0fca6ea1SDimitry Andric   const MCExpr *ValueExpr;
698*0fca6ea1SDimitry Andric   if (Parser.parseExpression(ValueExpr))
699*0fca6ea1SDimitry Andric     return true;
700*0fca6ea1SDimitry Andric 
701*0fca6ea1SDimitry Andric   const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
702*0fca6ea1SDimitry Andric   if (!CE)
703*0fca6ea1SDimitry Andric     return Error(ValueExprLoc, "expected numeric constant");
704*0fca6ea1SDimitry Andric   IntegerValue = CE->getValue();
705*0fca6ea1SDimitry Andric 
706*0fca6ea1SDimitry Andric   if (Parser.parseEOL())
707*0fca6ea1SDimitry Andric     return true;
708*0fca6ea1SDimitry Andric 
709*0fca6ea1SDimitry Andric   getTargetStreamer().emitAttribute(Tag, IntegerValue);
710*0fca6ea1SDimitry Andric   return false;
711*0fca6ea1SDimitry Andric }
7120b57cec5SDimitry Andric 
7130b57cec5SDimitry Andric /// ParseDirective parses the Hexagon specific directives
ParseDirective(AsmToken DirectiveID)7140b57cec5SDimitry Andric bool HexagonAsmParser::ParseDirective(AsmToken DirectiveID) {
7150b57cec5SDimitry Andric   StringRef IDVal = DirectiveID.getIdentifier();
7160b57cec5SDimitry Andric   if (IDVal.lower() == ".falign")
7170b57cec5SDimitry Andric     return ParseDirectiveFalign(256, DirectiveID.getLoc());
7180b57cec5SDimitry Andric   if ((IDVal.lower() == ".lcomm") || (IDVal.lower() == ".lcommon"))
7190b57cec5SDimitry Andric     return ParseDirectiveComm(true, DirectiveID.getLoc());
7200b57cec5SDimitry Andric   if ((IDVal.lower() == ".comm") || (IDVal.lower() == ".common"))
7210b57cec5SDimitry Andric     return ParseDirectiveComm(false, DirectiveID.getLoc());
7220b57cec5SDimitry Andric   if (IDVal.lower() == ".subsection")
7230b57cec5SDimitry Andric     return ParseDirectiveSubsection(DirectiveID.getLoc());
724*0fca6ea1SDimitry Andric   if (IDVal == ".attribute")
725*0fca6ea1SDimitry Andric     return parseDirectiveAttribute(DirectiveID.getLoc());
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric   return true;
7280b57cec5SDimitry Andric }
ParseDirectiveSubsection(SMLoc L)7290b57cec5SDimitry Andric bool HexagonAsmParser::ParseDirectiveSubsection(SMLoc L) {
7300b57cec5SDimitry Andric   const MCExpr *Subsection = nullptr;
7310b57cec5SDimitry Andric   int64_t Res;
7320b57cec5SDimitry Andric 
7330b57cec5SDimitry Andric   assert((getLexer().isNot(AsmToken::EndOfStatement)) &&
7340b57cec5SDimitry Andric          "Invalid subsection directive");
7350b57cec5SDimitry Andric   getParser().parseExpression(Subsection);
7360b57cec5SDimitry Andric 
7370b57cec5SDimitry Andric   if (!Subsection->evaluateAsAbsolute(Res))
7380b57cec5SDimitry Andric     return Error(L, "Cannot evaluate subsection number");
7390b57cec5SDimitry Andric 
7400b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
7410b57cec5SDimitry Andric     return TokError("unexpected token in directive");
7420b57cec5SDimitry Andric 
7430b57cec5SDimitry Andric   // 0-8192 is the hard-coded range in MCObjectStreamper.cpp, this keeps the
7440b57cec5SDimitry Andric   // negative subsections together and in the same order but at the opposite
7450b57cec5SDimitry Andric   // end of the section.  Only legacy hexagon-gcc created assembly code
7460b57cec5SDimitry Andric   // used negative subsections.
7470b57cec5SDimitry Andric   if ((Res < 0) && (Res > -8193))
748*0fca6ea1SDimitry Andric     Res += 8192;
749*0fca6ea1SDimitry Andric   getStreamer().switchSection(getStreamer().getCurrentSectionOnly(), Res);
7500b57cec5SDimitry Andric   return false;
7510b57cec5SDimitry Andric }
7520b57cec5SDimitry Andric 
7530b57cec5SDimitry Andric ///  ::= .falign [expression]
ParseDirectiveFalign(unsigned Size,SMLoc L)7540b57cec5SDimitry Andric bool HexagonAsmParser::ParseDirectiveFalign(unsigned Size, SMLoc L) {
7550b57cec5SDimitry Andric 
7560b57cec5SDimitry Andric   int64_t MaxBytesToFill = 15;
7570b57cec5SDimitry Andric 
7580b57cec5SDimitry Andric   // if there is an argument
7590b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
7600b57cec5SDimitry Andric     const MCExpr *Value;
7610b57cec5SDimitry Andric     SMLoc ExprLoc = L;
7620b57cec5SDimitry Andric 
7630b57cec5SDimitry Andric     // Make sure we have a number (false is returned if expression is a number)
7640b57cec5SDimitry Andric     if (!getParser().parseExpression(Value)) {
7650b57cec5SDimitry Andric       // Make sure this is a number that is in range
7668bcb0991SDimitry Andric       auto *MCE = cast<MCConstantExpr>(Value);
7670b57cec5SDimitry Andric       uint64_t IntValue = MCE->getValue();
7680b57cec5SDimitry Andric       if (!isUIntN(Size, IntValue) && !isIntN(Size, IntValue))
7690b57cec5SDimitry Andric         return Error(ExprLoc, "literal value out of range (256) for falign");
7700b57cec5SDimitry Andric       MaxBytesToFill = IntValue;
7710b57cec5SDimitry Andric       Lex();
7720b57cec5SDimitry Andric     } else {
7730b57cec5SDimitry Andric       return Error(ExprLoc, "not a valid expression for falign directive");
7740b57cec5SDimitry Andric     }
7750b57cec5SDimitry Andric   }
7760b57cec5SDimitry Andric 
7770b57cec5SDimitry Andric   getTargetStreamer().emitFAlign(16, MaxBytesToFill);
7780b57cec5SDimitry Andric   Lex();
7790b57cec5SDimitry Andric 
7800b57cec5SDimitry Andric   return false;
7810b57cec5SDimitry Andric }
7820b57cec5SDimitry Andric 
7830b57cec5SDimitry Andric // This is largely a copy of AsmParser's ParseDirectiveComm extended to
7840b57cec5SDimitry Andric // accept a 3rd argument, AccessAlignment which indicates the smallest
7850b57cec5SDimitry Andric // memory access made to the symbol, expressed in bytes.  If no
7860b57cec5SDimitry Andric // AccessAlignment is specified it defaults to the Alignment Value.
7870b57cec5SDimitry Andric // Hexagon's .lcomm:
7880b57cec5SDimitry Andric //   .lcomm Symbol, Length, Alignment, AccessAlignment
ParseDirectiveComm(bool IsLocal,SMLoc Loc)7890b57cec5SDimitry Andric bool HexagonAsmParser::ParseDirectiveComm(bool IsLocal, SMLoc Loc) {
7900b57cec5SDimitry Andric   // FIXME: need better way to detect if AsmStreamer (upstream removed
7910b57cec5SDimitry Andric   // getKind())
7920b57cec5SDimitry Andric   if (getStreamer().hasRawTextSupport())
7930b57cec5SDimitry Andric     return true; // Only object file output requires special treatment.
7940b57cec5SDimitry Andric 
7950b57cec5SDimitry Andric   StringRef Name;
7960b57cec5SDimitry Andric   if (getParser().parseIdentifier(Name))
7970b57cec5SDimitry Andric     return TokError("expected identifier in directive");
7980b57cec5SDimitry Andric   // Handle the identifier as the key symbol.
7990b57cec5SDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
8000b57cec5SDimitry Andric 
8010b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::Comma))
8020b57cec5SDimitry Andric     return TokError("unexpected token in directive");
8030b57cec5SDimitry Andric   Lex();
8040b57cec5SDimitry Andric 
8050b57cec5SDimitry Andric   int64_t Size;
8060b57cec5SDimitry Andric   SMLoc SizeLoc = getLexer().getLoc();
8070b57cec5SDimitry Andric   if (getParser().parseAbsoluteExpression(Size))
8080b57cec5SDimitry Andric     return true;
8090b57cec5SDimitry Andric 
8100b57cec5SDimitry Andric   int64_t ByteAlignment = 1;
8110b57cec5SDimitry Andric   SMLoc ByteAlignmentLoc;
8120b57cec5SDimitry Andric   if (getLexer().is(AsmToken::Comma)) {
8130b57cec5SDimitry Andric     Lex();
8140b57cec5SDimitry Andric     ByteAlignmentLoc = getLexer().getLoc();
8150b57cec5SDimitry Andric     if (getParser().parseAbsoluteExpression(ByteAlignment))
8160b57cec5SDimitry Andric       return true;
8170b57cec5SDimitry Andric     if (!isPowerOf2_64(ByteAlignment))
8180b57cec5SDimitry Andric       return Error(ByteAlignmentLoc, "alignment must be a power of 2");
8190b57cec5SDimitry Andric   }
8200b57cec5SDimitry Andric 
8210b57cec5SDimitry Andric   int64_t AccessAlignment = 0;
8220b57cec5SDimitry Andric   if (getLexer().is(AsmToken::Comma)) {
8230b57cec5SDimitry Andric     // The optional access argument specifies the size of the smallest memory
8240b57cec5SDimitry Andric     //   access to be made to the symbol, expressed in bytes.
8250b57cec5SDimitry Andric     SMLoc AccessAlignmentLoc;
8260b57cec5SDimitry Andric     Lex();
8270b57cec5SDimitry Andric     AccessAlignmentLoc = getLexer().getLoc();
8280b57cec5SDimitry Andric     if (getParser().parseAbsoluteExpression(AccessAlignment))
8290b57cec5SDimitry Andric       return true;
8300b57cec5SDimitry Andric 
8310b57cec5SDimitry Andric     if (!isPowerOf2_64(AccessAlignment))
8320b57cec5SDimitry Andric       return Error(AccessAlignmentLoc, "access alignment must be a power of 2");
8330b57cec5SDimitry Andric   }
8340b57cec5SDimitry Andric 
8350b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
8360b57cec5SDimitry Andric     return TokError("unexpected token in '.comm' or '.lcomm' directive");
8370b57cec5SDimitry Andric 
8380b57cec5SDimitry Andric   Lex();
8390b57cec5SDimitry Andric 
8400b57cec5SDimitry Andric   // NOTE: a size of zero for a .comm should create a undefined symbol
8410b57cec5SDimitry Andric   // but a size of .lcomm creates a bss symbol of size zero.
8420b57cec5SDimitry Andric   if (Size < 0)
8430b57cec5SDimitry Andric     return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
8440b57cec5SDimitry Andric                           "be less than zero");
8450b57cec5SDimitry Andric 
8460b57cec5SDimitry Andric   // NOTE: The alignment in the directive is a power of 2 value, the assembler
8470b57cec5SDimitry Andric   // may internally end up wanting an alignment in bytes.
8480b57cec5SDimitry Andric   // FIXME: Diagnose overflow.
8490b57cec5SDimitry Andric   if (ByteAlignment < 0)
8500b57cec5SDimitry Andric     return Error(ByteAlignmentLoc, "invalid '.comm' or '.lcomm' directive "
8510b57cec5SDimitry Andric                                    "alignment, can't be less than zero");
8520b57cec5SDimitry Andric 
8530b57cec5SDimitry Andric   if (!Sym->isUndefined())
8540b57cec5SDimitry Andric     return Error(Loc, "invalid symbol redefinition");
8550b57cec5SDimitry Andric 
8560b57cec5SDimitry Andric   HexagonMCELFStreamer &HexagonELFStreamer =
8570b57cec5SDimitry Andric       static_cast<HexagonMCELFStreamer &>(getStreamer());
8580b57cec5SDimitry Andric   if (IsLocal) {
859bdd1243dSDimitry Andric     HexagonELFStreamer.HexagonMCEmitLocalCommonSymbol(
860bdd1243dSDimitry Andric         Sym, Size, Align(ByteAlignment), AccessAlignment);
8610b57cec5SDimitry Andric     return false;
8620b57cec5SDimitry Andric   }
8630b57cec5SDimitry Andric 
864bdd1243dSDimitry Andric   HexagonELFStreamer.HexagonMCEmitCommonSymbol(Sym, Size, Align(ByteAlignment),
8650b57cec5SDimitry Andric                                                AccessAlignment);
8660b57cec5SDimitry Andric   return false;
8670b57cec5SDimitry Andric }
8680b57cec5SDimitry Andric 
8690b57cec5SDimitry Andric // validate register against architecture
RegisterMatchesArch(unsigned MatchNum) const8700b57cec5SDimitry Andric bool HexagonAsmParser::RegisterMatchesArch(unsigned MatchNum) const {
8710b57cec5SDimitry Andric   if (HexagonMCRegisterClasses[Hexagon::V62RegsRegClassID].contains(MatchNum))
87206c3fb27SDimitry Andric     if (!getSTI().hasFeature(Hexagon::ArchV62))
8730b57cec5SDimitry Andric       return false;
8740b57cec5SDimitry Andric   return true;
8750b57cec5SDimitry Andric }
8760b57cec5SDimitry Andric 
877480093f4SDimitry Andric // extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeHexagonAsmLexer();
8780b57cec5SDimitry Andric 
8790b57cec5SDimitry Andric /// Force static initialization.
LLVMInitializeHexagonAsmParser()880480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeHexagonAsmParser() {
8810b57cec5SDimitry Andric   RegisterMCAsmParser<HexagonAsmParser> X(getTheHexagonTarget());
8820b57cec5SDimitry Andric }
8830b57cec5SDimitry Andric 
8840b57cec5SDimitry Andric #define GET_MATCHER_IMPLEMENTATION
8850b57cec5SDimitry Andric #define GET_REGISTER_MATCHER
8860b57cec5SDimitry Andric #include "HexagonGenAsmMatcher.inc"
8870b57cec5SDimitry Andric 
previousEqual(OperandVector & Operands,size_t Index,StringRef String)8880b57cec5SDimitry Andric static bool previousEqual(OperandVector &Operands, size_t Index,
8890b57cec5SDimitry Andric                           StringRef String) {
8900b57cec5SDimitry Andric   if (Index >= Operands.size())
8910b57cec5SDimitry Andric     return false;
8920b57cec5SDimitry Andric   MCParsedAsmOperand &Operand = *Operands[Operands.size() - Index - 1];
8930b57cec5SDimitry Andric   if (!Operand.isToken())
8940b57cec5SDimitry Andric     return false;
895fe6060f1SDimitry Andric   return static_cast<HexagonOperand &>(Operand).getToken().equals_insensitive(
896fe6060f1SDimitry Andric       String);
8970b57cec5SDimitry Andric }
8980b57cec5SDimitry Andric 
previousIsLoop(OperandVector & Operands,size_t Index)8990b57cec5SDimitry Andric static bool previousIsLoop(OperandVector &Operands, size_t Index) {
9000b57cec5SDimitry Andric   return previousEqual(Operands, Index, "loop0") ||
9010b57cec5SDimitry Andric          previousEqual(Operands, Index, "loop1") ||
9020b57cec5SDimitry Andric          previousEqual(Operands, Index, "sp1loop0") ||
9030b57cec5SDimitry Andric          previousEqual(Operands, Index, "sp2loop0") ||
9040b57cec5SDimitry Andric          previousEqual(Operands, Index, "sp3loop0");
9050b57cec5SDimitry Andric }
9060b57cec5SDimitry Andric 
splitIdentifier(OperandVector & Operands)9070b57cec5SDimitry Andric bool HexagonAsmParser::splitIdentifier(OperandVector &Operands) {
9080b57cec5SDimitry Andric   AsmToken const &Token = getParser().getTok();
9090b57cec5SDimitry Andric   StringRef String = Token.getString();
9100b57cec5SDimitry Andric   SMLoc Loc = Token.getLoc();
9110b57cec5SDimitry Andric   Lex();
9120b57cec5SDimitry Andric   do {
9130b57cec5SDimitry Andric     std::pair<StringRef, StringRef> HeadTail = String.split('.');
9140b57cec5SDimitry Andric     if (!HeadTail.first.empty())
9150b57cec5SDimitry Andric       Operands.push_back(
9160b57cec5SDimitry Andric           HexagonOperand::CreateToken(getContext(), HeadTail.first, Loc));
9170b57cec5SDimitry Andric     if (!HeadTail.second.empty())
9180b57cec5SDimitry Andric       Operands.push_back(HexagonOperand::CreateToken(
9190b57cec5SDimitry Andric           getContext(), String.substr(HeadTail.first.size(), 1), Loc));
9200b57cec5SDimitry Andric     String = HeadTail.second;
9210b57cec5SDimitry Andric   } while (!String.empty());
9220b57cec5SDimitry Andric   return false;
9230b57cec5SDimitry Andric }
9240b57cec5SDimitry Andric 
parseOperand(OperandVector & Operands)9250b57cec5SDimitry Andric bool HexagonAsmParser::parseOperand(OperandVector &Operands) {
926bdd1243dSDimitry Andric   MCRegister Register;
9270b57cec5SDimitry Andric   SMLoc Begin;
9280b57cec5SDimitry Andric   SMLoc End;
9290b57cec5SDimitry Andric   MCAsmLexer &Lexer = getLexer();
930bdd1243dSDimitry Andric   if (!parseRegister(Register, Begin, End)) {
9310b57cec5SDimitry Andric     if (!ErrorMissingParenthesis)
9320b57cec5SDimitry Andric       switch (Register) {
9330b57cec5SDimitry Andric       default:
9340b57cec5SDimitry Andric         break;
9350b57cec5SDimitry Andric       case Hexagon::P0:
9360b57cec5SDimitry Andric       case Hexagon::P1:
9370b57cec5SDimitry Andric       case Hexagon::P2:
9380b57cec5SDimitry Andric       case Hexagon::P3:
9390b57cec5SDimitry Andric         if (previousEqual(Operands, 0, "if")) {
9400b57cec5SDimitry Andric           if (WarnMissingParenthesis)
9410b57cec5SDimitry Andric             Warning(Begin, "Missing parenthesis around predicate register");
9420b57cec5SDimitry Andric           static char const *LParen = "(";
9430b57cec5SDimitry Andric           static char const *RParen = ")";
9440b57cec5SDimitry Andric           Operands.push_back(
9450b57cec5SDimitry Andric               HexagonOperand::CreateToken(getContext(), LParen, Begin));
9460b57cec5SDimitry Andric           Operands.push_back(
9470b57cec5SDimitry Andric               HexagonOperand::CreateReg(getContext(), Register, Begin, End));
9480b57cec5SDimitry Andric           const AsmToken &MaybeDotNew = Lexer.getTok();
9490b57cec5SDimitry Andric           if (MaybeDotNew.is(AsmToken::TokenKind::Identifier) &&
950fe6060f1SDimitry Andric               MaybeDotNew.getString().equals_insensitive(".new"))
9510b57cec5SDimitry Andric             splitIdentifier(Operands);
9520b57cec5SDimitry Andric           Operands.push_back(
9530b57cec5SDimitry Andric               HexagonOperand::CreateToken(getContext(), RParen, Begin));
9540b57cec5SDimitry Andric           return false;
9550b57cec5SDimitry Andric         }
9560b57cec5SDimitry Andric         if (previousEqual(Operands, 0, "!") &&
9570b57cec5SDimitry Andric             previousEqual(Operands, 1, "if")) {
9580b57cec5SDimitry Andric           if (WarnMissingParenthesis)
9590b57cec5SDimitry Andric             Warning(Begin, "Missing parenthesis around predicate register");
9600b57cec5SDimitry Andric           static char const *LParen = "(";
9610b57cec5SDimitry Andric           static char const *RParen = ")";
9620b57cec5SDimitry Andric           Operands.insert(Operands.end() - 1, HexagonOperand::CreateToken(
9630b57cec5SDimitry Andric                                                   getContext(), LParen, Begin));
9640b57cec5SDimitry Andric           Operands.push_back(
9650b57cec5SDimitry Andric               HexagonOperand::CreateReg(getContext(), Register, Begin, End));
9660b57cec5SDimitry Andric           const AsmToken &MaybeDotNew = Lexer.getTok();
9670b57cec5SDimitry Andric           if (MaybeDotNew.is(AsmToken::TokenKind::Identifier) &&
968fe6060f1SDimitry Andric               MaybeDotNew.getString().equals_insensitive(".new"))
9690b57cec5SDimitry Andric             splitIdentifier(Operands);
9700b57cec5SDimitry Andric           Operands.push_back(
9710b57cec5SDimitry Andric               HexagonOperand::CreateToken(getContext(), RParen, Begin));
9720b57cec5SDimitry Andric           return false;
9730b57cec5SDimitry Andric         }
9740b57cec5SDimitry Andric         break;
9750b57cec5SDimitry Andric       }
9760b57cec5SDimitry Andric     Operands.push_back(
9770b57cec5SDimitry Andric         HexagonOperand::CreateReg(getContext(), Register, Begin, End));
9780b57cec5SDimitry Andric     return false;
9790b57cec5SDimitry Andric   }
9800b57cec5SDimitry Andric   return splitIdentifier(Operands);
9810b57cec5SDimitry Andric }
9820b57cec5SDimitry Andric 
isLabel(AsmToken & Token)9830b57cec5SDimitry Andric bool HexagonAsmParser::isLabel(AsmToken &Token) {
9840b57cec5SDimitry Andric   MCAsmLexer &Lexer = getLexer();
9850b57cec5SDimitry Andric   AsmToken const &Second = Lexer.getTok();
9860b57cec5SDimitry Andric   AsmToken Third = Lexer.peekTok();
9870b57cec5SDimitry Andric   StringRef String = Token.getString();
9880b57cec5SDimitry Andric   if (Token.is(AsmToken::TokenKind::LCurly) ||
9890b57cec5SDimitry Andric       Token.is(AsmToken::TokenKind::RCurly))
9900b57cec5SDimitry Andric     return false;
9910b57cec5SDimitry Andric   // special case for parsing vwhist256:sat
9920b57cec5SDimitry Andric   if (String.lower() == "vwhist256" && Second.is(AsmToken::Colon) &&
9930b57cec5SDimitry Andric       Third.getString().lower() == "sat")
9940b57cec5SDimitry Andric     return false;
9950b57cec5SDimitry Andric   if (!Token.is(AsmToken::TokenKind::Identifier))
9960b57cec5SDimitry Andric     return true;
9970b57cec5SDimitry Andric   if (!matchRegister(String.lower()))
9980b57cec5SDimitry Andric     return true;
9990b57cec5SDimitry Andric   assert(Second.is(AsmToken::Colon));
10000b57cec5SDimitry Andric   StringRef Raw(String.data(), Third.getString().data() - String.data() +
10010b57cec5SDimitry Andric                                    Third.getString().size());
10025ffd83dbSDimitry Andric   std::string Collapsed = std::string(Raw);
1003e8d8bef9SDimitry Andric   llvm::erase_if(Collapsed, isSpace);
10040b57cec5SDimitry Andric   StringRef Whole = Collapsed;
10050b57cec5SDimitry Andric   std::pair<StringRef, StringRef> DotSplit = Whole.split('.');
10060b57cec5SDimitry Andric   if (!matchRegister(DotSplit.first.lower()))
10070b57cec5SDimitry Andric     return true;
10080b57cec5SDimitry Andric   return false;
10090b57cec5SDimitry Andric }
10100b57cec5SDimitry Andric 
handleNoncontigiousRegister(bool Contigious,SMLoc & Loc)10110b57cec5SDimitry Andric bool HexagonAsmParser::handleNoncontigiousRegister(bool Contigious,
10120b57cec5SDimitry Andric                                                    SMLoc &Loc) {
10130b57cec5SDimitry Andric   if (!Contigious && ErrorNoncontigiousRegister) {
10140b57cec5SDimitry Andric     Error(Loc, "Register name is not contigious");
10150b57cec5SDimitry Andric     return true;
10160b57cec5SDimitry Andric   }
10170b57cec5SDimitry Andric   if (!Contigious && WarnNoncontigiousRegister)
10180b57cec5SDimitry Andric     Warning(Loc, "Register name is not contigious");
10190b57cec5SDimitry Andric   return false;
10200b57cec5SDimitry Andric }
10210b57cec5SDimitry Andric 
parseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)10225f757f3fSDimitry Andric bool HexagonAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
10230b57cec5SDimitry Andric                                      SMLoc &EndLoc) {
10245f757f3fSDimitry Andric   return !tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
10255ffd83dbSDimitry Andric }
10265ffd83dbSDimitry Andric 
tryParseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)10275f757f3fSDimitry Andric ParseStatus HexagonAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
10285ffd83dbSDimitry Andric                                                SMLoc &EndLoc) {
10290b57cec5SDimitry Andric   MCAsmLexer &Lexer = getLexer();
10300b57cec5SDimitry Andric   StartLoc = getLexer().getLoc();
10310b57cec5SDimitry Andric   SmallVector<AsmToken, 5> Lookahead;
10320b57cec5SDimitry Andric   StringRef RawString(Lexer.getTok().getString().data(), 0);
10330b57cec5SDimitry Andric   bool Again = Lexer.is(AsmToken::Identifier);
10340b57cec5SDimitry Andric   bool NeededWorkaround = false;
10350b57cec5SDimitry Andric   while (Again) {
10360b57cec5SDimitry Andric     AsmToken const &Token = Lexer.getTok();
10370b57cec5SDimitry Andric     RawString = StringRef(RawString.data(), Token.getString().data() -
10380b57cec5SDimitry Andric                                                 RawString.data() +
10390b57cec5SDimitry Andric                                                 Token.getString().size());
10400b57cec5SDimitry Andric     Lookahead.push_back(Token);
10410b57cec5SDimitry Andric     Lexer.Lex();
10420b57cec5SDimitry Andric     bool Contigious = Lexer.getTok().getString().data() ==
10430b57cec5SDimitry Andric                       Lookahead.back().getString().data() +
10440b57cec5SDimitry Andric                           Lookahead.back().getString().size();
10450b57cec5SDimitry Andric     bool Type = Lexer.is(AsmToken::Identifier) || Lexer.is(AsmToken::Dot) ||
10460b57cec5SDimitry Andric                 Lexer.is(AsmToken::Integer) || Lexer.is(AsmToken::Real) ||
10470b57cec5SDimitry Andric                 Lexer.is(AsmToken::Colon);
10480b57cec5SDimitry Andric     bool Workaround =
10490b57cec5SDimitry Andric         Lexer.is(AsmToken::Colon) || Lookahead.back().is(AsmToken::Colon);
10500b57cec5SDimitry Andric     Again = (Contigious && Type) || (Workaround && Type);
10510b57cec5SDimitry Andric     NeededWorkaround = NeededWorkaround || (Again && !(Contigious && Type));
10520b57cec5SDimitry Andric   }
10535ffd83dbSDimitry Andric   std::string Collapsed = std::string(RawString);
1054e8d8bef9SDimitry Andric   llvm::erase_if(Collapsed, isSpace);
10550b57cec5SDimitry Andric   StringRef FullString = Collapsed;
10560b57cec5SDimitry Andric   std::pair<StringRef, StringRef> DotSplit = FullString.split('.');
10570b57cec5SDimitry Andric   unsigned DotReg = matchRegister(DotSplit.first.lower());
10580b57cec5SDimitry Andric   if (DotReg != Hexagon::NoRegister && RegisterMatchesArch(DotReg)) {
10590b57cec5SDimitry Andric     if (DotSplit.second.empty()) {
10605f757f3fSDimitry Andric       Reg = DotReg;
10610b57cec5SDimitry Andric       EndLoc = Lexer.getLoc();
10620b57cec5SDimitry Andric       if (handleNoncontigiousRegister(!NeededWorkaround, StartLoc))
10635f757f3fSDimitry Andric         return ParseStatus::NoMatch;
10645f757f3fSDimitry Andric       return ParseStatus::Success;
10650b57cec5SDimitry Andric     } else {
10665f757f3fSDimitry Andric       Reg = DotReg;
10670b57cec5SDimitry Andric       size_t First = RawString.find('.');
10680b57cec5SDimitry Andric       StringRef DotString (RawString.data() + First, RawString.size() - First);
10690b57cec5SDimitry Andric       Lexer.UnLex(AsmToken(AsmToken::Identifier, DotString));
10700b57cec5SDimitry Andric       EndLoc = Lexer.getLoc();
10710b57cec5SDimitry Andric       if (handleNoncontigiousRegister(!NeededWorkaround, StartLoc))
10725f757f3fSDimitry Andric         return ParseStatus::NoMatch;
10735f757f3fSDimitry Andric       return ParseStatus::Success;
10740b57cec5SDimitry Andric     }
10750b57cec5SDimitry Andric   }
10760b57cec5SDimitry Andric   std::pair<StringRef, StringRef> ColonSplit = StringRef(FullString).split(':');
10770b57cec5SDimitry Andric   unsigned ColonReg = matchRegister(ColonSplit.first.lower());
10780b57cec5SDimitry Andric   if (ColonReg != Hexagon::NoRegister && RegisterMatchesArch(DotReg)) {
10790b57cec5SDimitry Andric     do {
10805ffd83dbSDimitry Andric       Lexer.UnLex(Lookahead.pop_back_val());
10810b57cec5SDimitry Andric     } while (!Lookahead.empty() && !Lexer.is(AsmToken::Colon));
10825f757f3fSDimitry Andric     Reg = ColonReg;
10830b57cec5SDimitry Andric     EndLoc = Lexer.getLoc();
10840b57cec5SDimitry Andric     if (handleNoncontigiousRegister(!NeededWorkaround, StartLoc))
10855f757f3fSDimitry Andric       return ParseStatus::NoMatch;
10865f757f3fSDimitry Andric     return ParseStatus::Success;
10870b57cec5SDimitry Andric   }
10880b57cec5SDimitry Andric   while (!Lookahead.empty()) {
10895ffd83dbSDimitry Andric     Lexer.UnLex(Lookahead.pop_back_val());
10900b57cec5SDimitry Andric   }
10915f757f3fSDimitry Andric   return ParseStatus::NoMatch;
10920b57cec5SDimitry Andric }
10930b57cec5SDimitry Andric 
implicitExpressionLocation(OperandVector & Operands)10940b57cec5SDimitry Andric bool HexagonAsmParser::implicitExpressionLocation(OperandVector &Operands) {
10950b57cec5SDimitry Andric   if (previousEqual(Operands, 0, "call"))
10960b57cec5SDimitry Andric     return true;
10970b57cec5SDimitry Andric   if (previousEqual(Operands, 0, "jump"))
10980b57cec5SDimitry Andric     if (!getLexer().getTok().is(AsmToken::Colon))
10990b57cec5SDimitry Andric       return true;
11000b57cec5SDimitry Andric   if (previousEqual(Operands, 0, "(") && previousIsLoop(Operands, 1))
11010b57cec5SDimitry Andric     return true;
11020b57cec5SDimitry Andric   if (previousEqual(Operands, 1, ":") && previousEqual(Operands, 2, "jump") &&
11030b57cec5SDimitry Andric       (previousEqual(Operands, 0, "nt") || previousEqual(Operands, 0, "t")))
11040b57cec5SDimitry Andric     return true;
11050b57cec5SDimitry Andric   return false;
11060b57cec5SDimitry Andric }
11070b57cec5SDimitry Andric 
parseExpression(MCExpr const * & Expr)11080b57cec5SDimitry Andric bool HexagonAsmParser::parseExpression(MCExpr const *&Expr) {
11090b57cec5SDimitry Andric   SmallVector<AsmToken, 4> Tokens;
11100b57cec5SDimitry Andric   MCAsmLexer &Lexer = getLexer();
11110b57cec5SDimitry Andric   bool Done = false;
11120b57cec5SDimitry Andric   static char const *Comma = ",";
11130b57cec5SDimitry Andric   do {
11140b57cec5SDimitry Andric     Tokens.emplace_back(Lexer.getTok());
11150b57cec5SDimitry Andric     Lex();
11160b57cec5SDimitry Andric     switch (Tokens.back().getKind()) {
11170b57cec5SDimitry Andric     case AsmToken::TokenKind::Hash:
11180b57cec5SDimitry Andric       if (Tokens.size() > 1)
11190b57cec5SDimitry Andric         if ((Tokens.end() - 2)->getKind() == AsmToken::TokenKind::Plus) {
11200b57cec5SDimitry Andric           Tokens.insert(Tokens.end() - 2,
11210b57cec5SDimitry Andric                         AsmToken(AsmToken::TokenKind::Comma, Comma));
11220b57cec5SDimitry Andric           Done = true;
11230b57cec5SDimitry Andric         }
11240b57cec5SDimitry Andric       break;
11250b57cec5SDimitry Andric     case AsmToken::TokenKind::RCurly:
11260b57cec5SDimitry Andric     case AsmToken::TokenKind::EndOfStatement:
11270b57cec5SDimitry Andric     case AsmToken::TokenKind::Eof:
11280b57cec5SDimitry Andric       Done = true;
11290b57cec5SDimitry Andric       break;
11300b57cec5SDimitry Andric     default:
11310b57cec5SDimitry Andric       break;
11320b57cec5SDimitry Andric     }
11330b57cec5SDimitry Andric   } while (!Done);
11340b57cec5SDimitry Andric   while (!Tokens.empty()) {
11350b57cec5SDimitry Andric     Lexer.UnLex(Tokens.back());
11360b57cec5SDimitry Andric     Tokens.pop_back();
11370b57cec5SDimitry Andric   }
11380b57cec5SDimitry Andric   SMLoc Loc = Lexer.getLoc();
11390b57cec5SDimitry Andric   return getParser().parseExpression(Expr, Loc);
11400b57cec5SDimitry Andric }
11410b57cec5SDimitry Andric 
parseExpressionOrOperand(OperandVector & Operands)11420b57cec5SDimitry Andric bool HexagonAsmParser::parseExpressionOrOperand(OperandVector &Operands) {
11430b57cec5SDimitry Andric   if (implicitExpressionLocation(Operands)) {
11440b57cec5SDimitry Andric     MCAsmParser &Parser = getParser();
11450b57cec5SDimitry Andric     SMLoc Loc = Parser.getLexer().getLoc();
11460b57cec5SDimitry Andric     MCExpr const *Expr = nullptr;
11470b57cec5SDimitry Andric     bool Error = parseExpression(Expr);
11480b57cec5SDimitry Andric     Expr = HexagonMCExpr::create(Expr, getContext());
11490b57cec5SDimitry Andric     if (!Error)
11500b57cec5SDimitry Andric       Operands.push_back(
11510b57cec5SDimitry Andric           HexagonOperand::CreateImm(getContext(), Expr, Loc, Loc));
11520b57cec5SDimitry Andric     return Error;
11530b57cec5SDimitry Andric   }
11540b57cec5SDimitry Andric   return parseOperand(Operands);
11550b57cec5SDimitry Andric }
11560b57cec5SDimitry Andric 
11570b57cec5SDimitry Andric /// Parse an instruction.
parseInstruction(OperandVector & Operands)11580b57cec5SDimitry Andric bool HexagonAsmParser::parseInstruction(OperandVector &Operands) {
11590b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
11600b57cec5SDimitry Andric   MCAsmLexer &Lexer = getLexer();
11610b57cec5SDimitry Andric   while (true) {
11620b57cec5SDimitry Andric     AsmToken const &Token = Parser.getTok();
11630b57cec5SDimitry Andric     switch (Token.getKind()) {
11640b57cec5SDimitry Andric     case AsmToken::Eof:
11650b57cec5SDimitry Andric     case AsmToken::EndOfStatement: {
11660b57cec5SDimitry Andric       Lex();
11670b57cec5SDimitry Andric       return false;
11680b57cec5SDimitry Andric     }
11690b57cec5SDimitry Andric     case AsmToken::LCurly: {
11700b57cec5SDimitry Andric       if (!Operands.empty())
11710b57cec5SDimitry Andric         return true;
11720b57cec5SDimitry Andric       Operands.push_back(HexagonOperand::CreateToken(
11730b57cec5SDimitry Andric           getContext(), Token.getString(), Token.getLoc()));
11740b57cec5SDimitry Andric       Lex();
11750b57cec5SDimitry Andric       return false;
11760b57cec5SDimitry Andric     }
11770b57cec5SDimitry Andric     case AsmToken::RCurly: {
11780b57cec5SDimitry Andric       if (Operands.empty()) {
11790b57cec5SDimitry Andric         Operands.push_back(HexagonOperand::CreateToken(
11800b57cec5SDimitry Andric             getContext(), Token.getString(), Token.getLoc()));
11810b57cec5SDimitry Andric         Lex();
11820b57cec5SDimitry Andric       }
11830b57cec5SDimitry Andric       return false;
11840b57cec5SDimitry Andric     }
11850b57cec5SDimitry Andric     case AsmToken::Comma: {
11860b57cec5SDimitry Andric       Lex();
11870b57cec5SDimitry Andric       continue;
11880b57cec5SDimitry Andric     }
11890b57cec5SDimitry Andric     case AsmToken::EqualEqual:
11900b57cec5SDimitry Andric     case AsmToken::ExclaimEqual:
11910b57cec5SDimitry Andric     case AsmToken::GreaterEqual:
11920b57cec5SDimitry Andric     case AsmToken::GreaterGreater:
11930b57cec5SDimitry Andric     case AsmToken::LessEqual:
11940b57cec5SDimitry Andric     case AsmToken::LessLess: {
11950b57cec5SDimitry Andric       Operands.push_back(HexagonOperand::CreateToken(
11960b57cec5SDimitry Andric           getContext(), Token.getString().substr(0, 1), Token.getLoc()));
11970b57cec5SDimitry Andric       Operands.push_back(HexagonOperand::CreateToken(
11980b57cec5SDimitry Andric           getContext(), Token.getString().substr(1, 1), Token.getLoc()));
11990b57cec5SDimitry Andric       Lex();
12000b57cec5SDimitry Andric       continue;
12010b57cec5SDimitry Andric     }
12020b57cec5SDimitry Andric     case AsmToken::Hash: {
12030b57cec5SDimitry Andric       bool MustNotExtend = false;
12040b57cec5SDimitry Andric       bool ImplicitExpression = implicitExpressionLocation(Operands);
12050b57cec5SDimitry Andric       SMLoc ExprLoc = Lexer.getLoc();
12060b57cec5SDimitry Andric       if (!ImplicitExpression)
12070b57cec5SDimitry Andric         Operands.push_back(HexagonOperand::CreateToken(
12080b57cec5SDimitry Andric             getContext(), Token.getString(), Token.getLoc()));
12090b57cec5SDimitry Andric       Lex();
12100b57cec5SDimitry Andric       bool MustExtend = false;
12110b57cec5SDimitry Andric       bool HiOnly = false;
12120b57cec5SDimitry Andric       bool LoOnly = false;
12130b57cec5SDimitry Andric       if (Lexer.is(AsmToken::Hash)) {
12140b57cec5SDimitry Andric         Lex();
12150b57cec5SDimitry Andric         MustExtend = true;
12160b57cec5SDimitry Andric       } else if (ImplicitExpression)
12170b57cec5SDimitry Andric         MustNotExtend = true;
12180b57cec5SDimitry Andric       AsmToken const &Token = Parser.getTok();
12190b57cec5SDimitry Andric       if (Token.is(AsmToken::Identifier)) {
12200b57cec5SDimitry Andric         StringRef String = Token.getString();
12210b57cec5SDimitry Andric         if (String.lower() == "hi") {
12220b57cec5SDimitry Andric           HiOnly = true;
12230b57cec5SDimitry Andric         } else if (String.lower() == "lo") {
12240b57cec5SDimitry Andric           LoOnly = true;
12250b57cec5SDimitry Andric         }
12260b57cec5SDimitry Andric         if (HiOnly || LoOnly) {
12270b57cec5SDimitry Andric           AsmToken LParen = Lexer.peekTok();
12280b57cec5SDimitry Andric           if (!LParen.is(AsmToken::LParen)) {
12290b57cec5SDimitry Andric             HiOnly = false;
12300b57cec5SDimitry Andric             LoOnly = false;
12310b57cec5SDimitry Andric           } else {
12320b57cec5SDimitry Andric             Lex();
12330b57cec5SDimitry Andric           }
12340b57cec5SDimitry Andric         }
12350b57cec5SDimitry Andric       }
12360b57cec5SDimitry Andric       MCExpr const *Expr = nullptr;
12370b57cec5SDimitry Andric       if (parseExpression(Expr))
12380b57cec5SDimitry Andric         return true;
12390b57cec5SDimitry Andric       int64_t Value;
12400b57cec5SDimitry Andric       MCContext &Context = Parser.getContext();
12410b57cec5SDimitry Andric       assert(Expr != nullptr);
12420b57cec5SDimitry Andric       if (Expr->evaluateAsAbsolute(Value)) {
12430b57cec5SDimitry Andric         if (HiOnly)
12440b57cec5SDimitry Andric           Expr = MCBinaryExpr::createLShr(
12450b57cec5SDimitry Andric               Expr, MCConstantExpr::create(16, Context), Context);
12460b57cec5SDimitry Andric         if (HiOnly || LoOnly)
12470b57cec5SDimitry Andric           Expr = MCBinaryExpr::createAnd(
12480b57cec5SDimitry Andric               Expr, MCConstantExpr::create(0xffff, Context), Context);
12490b57cec5SDimitry Andric       } else {
12500b57cec5SDimitry Andric         MCValue Value;
12510b57cec5SDimitry Andric         if (Expr->evaluateAsRelocatable(Value, nullptr, nullptr)) {
12520b57cec5SDimitry Andric           if (!Value.isAbsolute()) {
12530b57cec5SDimitry Andric             switch (Value.getAccessVariant()) {
12540b57cec5SDimitry Andric             case MCSymbolRefExpr::VariantKind::VK_TPREL:
12550b57cec5SDimitry Andric             case MCSymbolRefExpr::VariantKind::VK_DTPREL:
12560b57cec5SDimitry Andric               // Don't lazy extend these expression variants
12570b57cec5SDimitry Andric               MustNotExtend = !MustExtend;
12580b57cec5SDimitry Andric               break;
12590b57cec5SDimitry Andric             default:
12600b57cec5SDimitry Andric               break;
12610b57cec5SDimitry Andric             }
12620b57cec5SDimitry Andric           }
12630b57cec5SDimitry Andric         }
12640b57cec5SDimitry Andric       }
12650b57cec5SDimitry Andric       Expr = HexagonMCExpr::create(Expr, Context);
12660b57cec5SDimitry Andric       HexagonMCInstrInfo::setMustNotExtend(*Expr, MustNotExtend);
12670b57cec5SDimitry Andric       HexagonMCInstrInfo::setMustExtend(*Expr, MustExtend);
12680b57cec5SDimitry Andric       std::unique_ptr<HexagonOperand> Operand =
12690b57cec5SDimitry Andric           HexagonOperand::CreateImm(getContext(), Expr, ExprLoc, ExprLoc);
12700b57cec5SDimitry Andric       Operands.push_back(std::move(Operand));
12710b57cec5SDimitry Andric       continue;
12720b57cec5SDimitry Andric     }
12730b57cec5SDimitry Andric     default:
12740b57cec5SDimitry Andric       break;
12750b57cec5SDimitry Andric     }
12760b57cec5SDimitry Andric     if (parseExpressionOrOperand(Operands))
12770b57cec5SDimitry Andric       return true;
12780b57cec5SDimitry Andric   }
12790b57cec5SDimitry Andric }
12800b57cec5SDimitry Andric 
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,AsmToken ID,OperandVector & Operands)12810b57cec5SDimitry Andric bool HexagonAsmParser::ParseInstruction(ParseInstructionInfo &Info,
12820b57cec5SDimitry Andric                                         StringRef Name, AsmToken ID,
12830b57cec5SDimitry Andric                                         OperandVector &Operands) {
12840b57cec5SDimitry Andric   getLexer().UnLex(ID);
12850b57cec5SDimitry Andric   return parseInstruction(Operands);
12860b57cec5SDimitry Andric }
12870b57cec5SDimitry Andric 
makeCombineInst(int opCode,MCOperand & Rdd,MCOperand & MO1,MCOperand & MO2)12880b57cec5SDimitry Andric static MCInst makeCombineInst(int opCode, MCOperand &Rdd, MCOperand &MO1,
12890b57cec5SDimitry Andric                               MCOperand &MO2) {
12900b57cec5SDimitry Andric   MCInst TmpInst;
12910b57cec5SDimitry Andric   TmpInst.setOpcode(opCode);
12920b57cec5SDimitry Andric   TmpInst.addOperand(Rdd);
12930b57cec5SDimitry Andric   TmpInst.addOperand(MO1);
12940b57cec5SDimitry Andric   TmpInst.addOperand(MO2);
12950b57cec5SDimitry Andric 
12960b57cec5SDimitry Andric   return TmpInst;
12970b57cec5SDimitry Andric }
12980b57cec5SDimitry Andric 
12990b57cec5SDimitry Andric // Define this matcher function after the auto-generated include so we
13000b57cec5SDimitry Andric // have the match class enum definitions.
validateTargetOperandClass(MCParsedAsmOperand & AsmOp,unsigned Kind)13010b57cec5SDimitry Andric unsigned HexagonAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
13020b57cec5SDimitry Andric                                                       unsigned Kind) {
13030b57cec5SDimitry Andric   HexagonOperand *Op = static_cast<HexagonOperand *>(&AsmOp);
13040b57cec5SDimitry Andric 
13050b57cec5SDimitry Andric   switch (Kind) {
13060b57cec5SDimitry Andric   case MCK_0: {
13070b57cec5SDimitry Andric     int64_t Value;
13080b57cec5SDimitry Andric     return Op->isImm() && Op->Imm.Val->evaluateAsAbsolute(Value) && Value == 0
13090b57cec5SDimitry Andric                ? Match_Success
13100b57cec5SDimitry Andric                : Match_InvalidOperand;
13110b57cec5SDimitry Andric   }
13120b57cec5SDimitry Andric   case MCK_1: {
13130b57cec5SDimitry Andric     int64_t Value;
13140b57cec5SDimitry Andric     return Op->isImm() && Op->Imm.Val->evaluateAsAbsolute(Value) && Value == 1
13150b57cec5SDimitry Andric                ? Match_Success
13160b57cec5SDimitry Andric                : Match_InvalidOperand;
13170b57cec5SDimitry Andric   }
13180b57cec5SDimitry Andric   }
13190b57cec5SDimitry Andric   if (Op->Kind == HexagonOperand::Token && Kind != InvalidMatchClass) {
13200b57cec5SDimitry Andric     StringRef myStringRef = StringRef(Op->Tok.Data, Op->Tok.Length);
13210b57cec5SDimitry Andric     if (matchTokenString(myStringRef.lower()) == (MatchClassKind)Kind)
13220b57cec5SDimitry Andric       return Match_Success;
13230b57cec5SDimitry Andric     if (matchTokenString(myStringRef.upper()) == (MatchClassKind)Kind)
13240b57cec5SDimitry Andric       return Match_Success;
13250b57cec5SDimitry Andric   }
13260b57cec5SDimitry Andric 
13270b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Unmatched Operand:");
13280b57cec5SDimitry Andric   LLVM_DEBUG(Op->dump());
13290b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "\n");
13300b57cec5SDimitry Andric 
13310b57cec5SDimitry Andric   return Match_InvalidOperand;
13320b57cec5SDimitry Andric }
13330b57cec5SDimitry Andric 
13340b57cec5SDimitry Andric // FIXME: Calls to OutOfRange shoudl propagate failure up to parseStatement.
OutOfRange(SMLoc IDLoc,long long Val,long long Max)13350b57cec5SDimitry Andric bool HexagonAsmParser::OutOfRange(SMLoc IDLoc, long long Val, long long Max) {
13360b57cec5SDimitry Andric   std::string errStr;
13370b57cec5SDimitry Andric   raw_string_ostream ES(errStr);
13380b57cec5SDimitry Andric   ES << "value " << Val << "(" << format_hex(Val, 0) << ") out of range: ";
13390b57cec5SDimitry Andric   if (Max >= 0)
13400b57cec5SDimitry Andric     ES << "0-" << Max;
13410b57cec5SDimitry Andric   else
13420b57cec5SDimitry Andric     ES << Max << "-" << (-Max - 1);
13430b57cec5SDimitry Andric   return Parser.printError(IDLoc, ES.str());
13440b57cec5SDimitry Andric }
13450b57cec5SDimitry Andric 
processInstruction(MCInst & Inst,OperandVector const & Operands,SMLoc IDLoc)13460b57cec5SDimitry Andric int HexagonAsmParser::processInstruction(MCInst &Inst,
13470b57cec5SDimitry Andric                                          OperandVector const &Operands,
13480b57cec5SDimitry Andric                                          SMLoc IDLoc) {
13490b57cec5SDimitry Andric   MCContext &Context = getParser().getContext();
13500b57cec5SDimitry Andric   const MCRegisterInfo *RI = getContext().getRegisterInfo();
13515ffd83dbSDimitry Andric   const std::string r = "r";
13525ffd83dbSDimitry Andric   const std::string v = "v";
13535ffd83dbSDimitry Andric   const std::string Colon = ":";
13545ffd83dbSDimitry Andric   using RegPairVals = std::pair<unsigned, unsigned>;
13555ffd83dbSDimitry Andric   auto GetRegPair = [this, r](RegPairVals RegPair) {
13565ffd83dbSDimitry Andric     const std::string R1 = r + utostr(RegPair.first);
13575ffd83dbSDimitry Andric     const std::string R2 = r + utostr(RegPair.second);
13585ffd83dbSDimitry Andric 
13595ffd83dbSDimitry Andric     return std::make_pair(matchRegister(R1), matchRegister(R2));
13605ffd83dbSDimitry Andric   };
13615ffd83dbSDimitry Andric   auto GetScalarRegs = [RI, GetRegPair](unsigned RegPair) {
13625ffd83dbSDimitry Andric     const unsigned Lower = RI->getEncodingValue(RegPair);
13635ffd83dbSDimitry Andric     const RegPairVals RegPair_ = std::make_pair(Lower + 1, Lower);
13645ffd83dbSDimitry Andric 
13655ffd83dbSDimitry Andric     return GetRegPair(RegPair_);
13665ffd83dbSDimitry Andric   };
13675ffd83dbSDimitry Andric   auto GetVecRegs = [GetRegPair](unsigned VecRegPair) {
13685ffd83dbSDimitry Andric     const RegPairVals RegPair =
13695ffd83dbSDimitry Andric         HexagonMCInstrInfo::GetVecRegPairIndices(VecRegPair);
13705ffd83dbSDimitry Andric 
13715ffd83dbSDimitry Andric     return GetRegPair(RegPair);
13725ffd83dbSDimitry Andric   };
13730b57cec5SDimitry Andric 
13740b57cec5SDimitry Andric   bool is32bit = false; // used to distinguish between CONST32 and CONST64
13750b57cec5SDimitry Andric   switch (Inst.getOpcode()) {
13760b57cec5SDimitry Andric   default:
13770b57cec5SDimitry Andric     if (HexagonMCInstrInfo::getDesc(MII, Inst).isPseudo()) {
13780b57cec5SDimitry Andric       SMDiagnostic Diag = getSourceManager().GetMessage(
13790b57cec5SDimitry Andric           IDLoc, SourceMgr::DK_Error,
13800b57cec5SDimitry Andric           "Found pseudo instruction with no expansion");
13810b57cec5SDimitry Andric       Diag.print("", errs());
13820b57cec5SDimitry Andric       report_fatal_error("Invalid pseudo instruction");
13830b57cec5SDimitry Andric     }
13840b57cec5SDimitry Andric     break;
13850b57cec5SDimitry Andric 
13860b57cec5SDimitry Andric   case Hexagon::J2_trap1:
138706c3fb27SDimitry Andric     if (!getSTI().hasFeature(Hexagon::ArchV65)) {
13880b57cec5SDimitry Andric       MCOperand &Rx = Inst.getOperand(0);
13890b57cec5SDimitry Andric       MCOperand &Ry = Inst.getOperand(1);
13900b57cec5SDimitry Andric       if (Rx.getReg() != Hexagon::R0 || Ry.getReg() != Hexagon::R0) {
13910b57cec5SDimitry Andric         Error(IDLoc, "trap1 can only have register r0 as operand");
13920b57cec5SDimitry Andric         return Match_InvalidOperand;
13930b57cec5SDimitry Andric       }
13940b57cec5SDimitry Andric     }
13950b57cec5SDimitry Andric     break;
13960b57cec5SDimitry Andric 
13970b57cec5SDimitry Andric   case Hexagon::A2_iconst: {
13980b57cec5SDimitry Andric     Inst.setOpcode(Hexagon::A2_addi);
13990b57cec5SDimitry Andric     MCOperand Reg = Inst.getOperand(0);
14000b57cec5SDimitry Andric     MCOperand S27 = Inst.getOperand(1);
14010b57cec5SDimitry Andric     HexagonMCInstrInfo::setMustNotExtend(*S27.getExpr());
14020b57cec5SDimitry Andric     HexagonMCInstrInfo::setS27_2_reloc(*S27.getExpr());
14030b57cec5SDimitry Andric     Inst.clear();
14040b57cec5SDimitry Andric     Inst.addOperand(Reg);
14050b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(Hexagon::R0));
14060b57cec5SDimitry Andric     Inst.addOperand(S27);
14070b57cec5SDimitry Andric     break;
14080b57cec5SDimitry Andric   }
14090b57cec5SDimitry Andric   case Hexagon::M4_mpyrr_addr:
14100b57cec5SDimitry Andric   case Hexagon::S4_addi_asl_ri:
14110b57cec5SDimitry Andric   case Hexagon::S4_addi_lsr_ri:
14120b57cec5SDimitry Andric   case Hexagon::S4_andi_asl_ri:
14130b57cec5SDimitry Andric   case Hexagon::S4_andi_lsr_ri:
14140b57cec5SDimitry Andric   case Hexagon::S4_ori_asl_ri:
14150b57cec5SDimitry Andric   case Hexagon::S4_ori_lsr_ri:
14160b57cec5SDimitry Andric   case Hexagon::S4_or_andix:
14170b57cec5SDimitry Andric   case Hexagon::S4_subi_asl_ri:
14180b57cec5SDimitry Andric   case Hexagon::S4_subi_lsr_ri: {
14190b57cec5SDimitry Andric     MCOperand &Ry = Inst.getOperand(0);
14200b57cec5SDimitry Andric     MCOperand &src = Inst.getOperand(2);
14210b57cec5SDimitry Andric     if (RI->getEncodingValue(Ry.getReg()) != RI->getEncodingValue(src.getReg()))
14220b57cec5SDimitry Andric       return Match_InvalidOperand;
14230b57cec5SDimitry Andric     break;
14240b57cec5SDimitry Andric   }
14250b57cec5SDimitry Andric 
14260b57cec5SDimitry Andric   case Hexagon::C2_cmpgei: {
14270b57cec5SDimitry Andric     MCOperand &MO = Inst.getOperand(2);
14280b57cec5SDimitry Andric     MO.setExpr(HexagonMCExpr::create(
14290b57cec5SDimitry Andric         MCBinaryExpr::createSub(MO.getExpr(),
14300b57cec5SDimitry Andric                                 MCConstantExpr::create(1, Context), Context),
14310b57cec5SDimitry Andric         Context));
14320b57cec5SDimitry Andric     Inst.setOpcode(Hexagon::C2_cmpgti);
14330b57cec5SDimitry Andric     break;
14340b57cec5SDimitry Andric   }
14350b57cec5SDimitry Andric 
14360b57cec5SDimitry Andric   case Hexagon::C2_cmpgeui: {
14370b57cec5SDimitry Andric     MCOperand &MO = Inst.getOperand(2);
14380b57cec5SDimitry Andric     int64_t Value;
14390b57cec5SDimitry Andric     bool Success = MO.getExpr()->evaluateAsAbsolute(Value);
14400b57cec5SDimitry Andric     (void)Success;
14410b57cec5SDimitry Andric     assert(Success && "Assured by matcher");
14420b57cec5SDimitry Andric     if (Value == 0) {
14430b57cec5SDimitry Andric       MCInst TmpInst;
14440b57cec5SDimitry Andric       MCOperand &Pd = Inst.getOperand(0);
14450b57cec5SDimitry Andric       MCOperand &Rt = Inst.getOperand(1);
14460b57cec5SDimitry Andric       TmpInst.setOpcode(Hexagon::C2_cmpeq);
14470b57cec5SDimitry Andric       TmpInst.addOperand(Pd);
14480b57cec5SDimitry Andric       TmpInst.addOperand(Rt);
14490b57cec5SDimitry Andric       TmpInst.addOperand(Rt);
14500b57cec5SDimitry Andric       Inst = TmpInst;
14510b57cec5SDimitry Andric     } else {
14520b57cec5SDimitry Andric       MO.setExpr(HexagonMCExpr::create(
14530b57cec5SDimitry Andric           MCBinaryExpr::createSub(MO.getExpr(),
14540b57cec5SDimitry Andric                                   MCConstantExpr::create(1, Context), Context),
14550b57cec5SDimitry Andric           Context));
14560b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::C2_cmpgtui);
14570b57cec5SDimitry Andric     }
14580b57cec5SDimitry Andric     break;
14590b57cec5SDimitry Andric   }
14600b57cec5SDimitry Andric 
14610b57cec5SDimitry Andric   // Translate a "$Rdd = $Rss" to "$Rdd = combine($Rs, $Rt)"
14620b57cec5SDimitry Andric   case Hexagon::A2_tfrp: {
14630b57cec5SDimitry Andric     MCOperand &MO = Inst.getOperand(1);
14645ffd83dbSDimitry Andric     const std::pair<unsigned, unsigned> RegPair = GetScalarRegs(MO.getReg());
14655ffd83dbSDimitry Andric     MO.setReg(RegPair.first);
14665ffd83dbSDimitry Andric     Inst.addOperand(MCOperand::createReg(RegPair.second));
14670b57cec5SDimitry Andric     Inst.setOpcode(Hexagon::A2_combinew);
14680b57cec5SDimitry Andric     break;
14690b57cec5SDimitry Andric   }
14700b57cec5SDimitry Andric 
14710b57cec5SDimitry Andric   case Hexagon::A2_tfrpt:
14720b57cec5SDimitry Andric   case Hexagon::A2_tfrpf: {
14730b57cec5SDimitry Andric     MCOperand &MO = Inst.getOperand(2);
14745ffd83dbSDimitry Andric     const std::pair<unsigned, unsigned> RegPair = GetScalarRegs(MO.getReg());
14755ffd83dbSDimitry Andric     MO.setReg(RegPair.first);
14765ffd83dbSDimitry Andric     Inst.addOperand(MCOperand::createReg(RegPair.second));
14770b57cec5SDimitry Andric     Inst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrpt)
14780b57cec5SDimitry Andric                        ? Hexagon::C2_ccombinewt
14790b57cec5SDimitry Andric                        : Hexagon::C2_ccombinewf);
14800b57cec5SDimitry Andric     break;
14810b57cec5SDimitry Andric   }
14820b57cec5SDimitry Andric   case Hexagon::A2_tfrptnew:
14830b57cec5SDimitry Andric   case Hexagon::A2_tfrpfnew: {
14840b57cec5SDimitry Andric     MCOperand &MO = Inst.getOperand(2);
14855ffd83dbSDimitry Andric     const std::pair<unsigned, unsigned> RegPair = GetScalarRegs(MO.getReg());
14865ffd83dbSDimitry Andric     MO.setReg(RegPair.first);
14875ffd83dbSDimitry Andric     Inst.addOperand(MCOperand::createReg(RegPair.second));
14880b57cec5SDimitry Andric     Inst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrptnew)
14890b57cec5SDimitry Andric                        ? Hexagon::C2_ccombinewnewt
14900b57cec5SDimitry Andric                        : Hexagon::C2_ccombinewnewf);
14910b57cec5SDimitry Andric     break;
14920b57cec5SDimitry Andric   }
14930b57cec5SDimitry Andric 
14940b57cec5SDimitry Andric   // Translate a "$Vdd = $Vss" to "$Vdd = vcombine($Vs, $Vt)"
14950b57cec5SDimitry Andric   case Hexagon::V6_vassignp: {
14960b57cec5SDimitry Andric     MCOperand &MO = Inst.getOperand(1);
14975ffd83dbSDimitry Andric     const std::pair<unsigned, unsigned> RegPair = GetVecRegs(MO.getReg());
14985ffd83dbSDimitry Andric     MO.setReg(RegPair.first);
14995ffd83dbSDimitry Andric     Inst.addOperand(MCOperand::createReg(RegPair.second));
15000b57cec5SDimitry Andric     Inst.setOpcode(Hexagon::V6_vcombine);
15010b57cec5SDimitry Andric     break;
15020b57cec5SDimitry Andric   }
15030b57cec5SDimitry Andric 
15040b57cec5SDimitry Andric   // Translate a "$Rx =  CONST32(#imm)" to "$Rx = memw(gp+#LABEL) "
15050b57cec5SDimitry Andric   case Hexagon::CONST32:
15060b57cec5SDimitry Andric     is32bit = true;
1507bdd1243dSDimitry Andric     [[fallthrough]];
15080b57cec5SDimitry Andric   // Translate a "$Rx:y =  CONST64(#imm)" to "$Rx:y = memd(gp+#LABEL) "
15090b57cec5SDimitry Andric   case Hexagon::CONST64:
15100b57cec5SDimitry Andric     // FIXME: need better way to detect AsmStreamer (upstream removed getKind())
15110b57cec5SDimitry Andric     if (!Parser.getStreamer().hasRawTextSupport()) {
15120b57cec5SDimitry Andric       MCELFStreamer *MES = static_cast<MCELFStreamer *>(&Parser.getStreamer());
15130b57cec5SDimitry Andric       MCOperand &MO_1 = Inst.getOperand(1);
15140b57cec5SDimitry Andric       MCOperand &MO_0 = Inst.getOperand(0);
15150b57cec5SDimitry Andric 
15160b57cec5SDimitry Andric       // push section onto section stack
151781ad6265SDimitry Andric       MES->pushSection();
15180b57cec5SDimitry Andric 
15190b57cec5SDimitry Andric       std::string myCharStr;
15200b57cec5SDimitry Andric       MCSectionELF *mySection;
15210b57cec5SDimitry Andric 
15220b57cec5SDimitry Andric       // check if this as an immediate or a symbol
15230b57cec5SDimitry Andric       int64_t Value;
15240b57cec5SDimitry Andric       bool Absolute = MO_1.getExpr()->evaluateAsAbsolute(Value);
15250b57cec5SDimitry Andric       if (Absolute) {
15260b57cec5SDimitry Andric         // Create a new section - one for each constant
15270b57cec5SDimitry Andric         // Some or all of the zeros are replaced with the given immediate.
15280b57cec5SDimitry Andric         if (is32bit) {
15290b57cec5SDimitry Andric           std::string myImmStr = utohexstr(static_cast<uint32_t>(Value));
15300b57cec5SDimitry Andric           myCharStr = StringRef(".gnu.linkonce.l4.CONST_00000000")
15310b57cec5SDimitry Andric                           .drop_back(myImmStr.size())
15320b57cec5SDimitry Andric                           .str() +
15330b57cec5SDimitry Andric                       myImmStr;
15340b57cec5SDimitry Andric         } else {
15350b57cec5SDimitry Andric           std::string myImmStr = utohexstr(Value);
15360b57cec5SDimitry Andric           myCharStr = StringRef(".gnu.linkonce.l8.CONST_0000000000000000")
15370b57cec5SDimitry Andric                           .drop_back(myImmStr.size())
15380b57cec5SDimitry Andric                           .str() +
15390b57cec5SDimitry Andric                       myImmStr;
15400b57cec5SDimitry Andric         }
15410b57cec5SDimitry Andric 
15420b57cec5SDimitry Andric         mySection = getContext().getELFSection(myCharStr, ELF::SHT_PROGBITS,
15430b57cec5SDimitry Andric                                                ELF::SHF_ALLOC | ELF::SHF_WRITE);
15440b57cec5SDimitry Andric       } else if (MO_1.isExpr()) {
15450b57cec5SDimitry Andric         // .lita - for expressions
15460b57cec5SDimitry Andric         myCharStr = ".lita";
15470b57cec5SDimitry Andric         mySection = getContext().getELFSection(myCharStr, ELF::SHT_PROGBITS,
15480b57cec5SDimitry Andric                                                ELF::SHF_ALLOC | ELF::SHF_WRITE);
15490b57cec5SDimitry Andric       } else
15500b57cec5SDimitry Andric         llvm_unreachable("unexpected type of machine operand!");
15510b57cec5SDimitry Andric 
155281ad6265SDimitry Andric       MES->switchSection(mySection);
15530b57cec5SDimitry Andric       unsigned byteSize = is32bit ? 4 : 8;
1554bdd1243dSDimitry Andric       getStreamer().emitCodeAlignment(Align(byteSize), &getSTI(), byteSize);
15550b57cec5SDimitry Andric 
15560b57cec5SDimitry Andric       MCSymbol *Sym;
15570b57cec5SDimitry Andric 
15580b57cec5SDimitry Andric       // for symbols, get rid of prepended ".gnu.linkonce.lx."
15590b57cec5SDimitry Andric 
15600b57cec5SDimitry Andric       // emit symbol if needed
15610b57cec5SDimitry Andric       if (Absolute) {
15620b57cec5SDimitry Andric         Sym = getContext().getOrCreateSymbol(StringRef(myCharStr.c_str() + 16));
15630b57cec5SDimitry Andric         if (Sym->isUndefined()) {
15645ffd83dbSDimitry Andric           getStreamer().emitLabel(Sym);
15655ffd83dbSDimitry Andric           getStreamer().emitSymbolAttribute(Sym, MCSA_Global);
15665ffd83dbSDimitry Andric           getStreamer().emitIntValue(Value, byteSize);
15670b57cec5SDimitry Andric         }
15680b57cec5SDimitry Andric       } else if (MO_1.isExpr()) {
15690b57cec5SDimitry Andric         const char *StringStart = nullptr;
15700b57cec5SDimitry Andric         const char *StringEnd = nullptr;
15710b57cec5SDimitry Andric         if (*Operands[4]->getStartLoc().getPointer() == '#') {
15720b57cec5SDimitry Andric           StringStart = Operands[5]->getStartLoc().getPointer();
15730b57cec5SDimitry Andric           StringEnd = Operands[6]->getStartLoc().getPointer();
15740b57cec5SDimitry Andric         } else { // no pound
15750b57cec5SDimitry Andric           StringStart = Operands[4]->getStartLoc().getPointer();
15760b57cec5SDimitry Andric           StringEnd = Operands[5]->getStartLoc().getPointer();
15770b57cec5SDimitry Andric         }
15780b57cec5SDimitry Andric 
15790b57cec5SDimitry Andric         unsigned size = StringEnd - StringStart;
15800b57cec5SDimitry Andric         std::string DotConst = ".CONST_";
15810b57cec5SDimitry Andric         Sym = getContext().getOrCreateSymbol(DotConst +
15820b57cec5SDimitry Andric                                              StringRef(StringStart, size));
15830b57cec5SDimitry Andric 
15840b57cec5SDimitry Andric         if (Sym->isUndefined()) {
15850b57cec5SDimitry Andric           // case where symbol is not yet defined: emit symbol
15865ffd83dbSDimitry Andric           getStreamer().emitLabel(Sym);
15875ffd83dbSDimitry Andric           getStreamer().emitSymbolAttribute(Sym, MCSA_Local);
15885ffd83dbSDimitry Andric           getStreamer().emitValue(MO_1.getExpr(), 4);
15890b57cec5SDimitry Andric         }
15900b57cec5SDimitry Andric       } else
15910b57cec5SDimitry Andric         llvm_unreachable("unexpected type of machine operand!");
15920b57cec5SDimitry Andric 
159381ad6265SDimitry Andric       MES->popSection();
15940b57cec5SDimitry Andric 
15950b57cec5SDimitry Andric       if (Sym) {
15960b57cec5SDimitry Andric         MCInst TmpInst;
15970b57cec5SDimitry Andric         if (is32bit) // 32 bit
15980b57cec5SDimitry Andric           TmpInst.setOpcode(Hexagon::L2_loadrigp);
15990b57cec5SDimitry Andric         else // 64 bit
16000b57cec5SDimitry Andric           TmpInst.setOpcode(Hexagon::L2_loadrdgp);
16010b57cec5SDimitry Andric 
16020b57cec5SDimitry Andric         TmpInst.addOperand(MO_0);
16030b57cec5SDimitry Andric         TmpInst.addOperand(MCOperand::createExpr(HexagonMCExpr::create(
16040b57cec5SDimitry Andric             MCSymbolRefExpr::create(Sym, getContext()), getContext())));
16050b57cec5SDimitry Andric         Inst = TmpInst;
16060b57cec5SDimitry Andric       }
16070b57cec5SDimitry Andric     }
16080b57cec5SDimitry Andric     break;
16090b57cec5SDimitry Andric 
16100b57cec5SDimitry Andric   // Translate a "$Rdd = #-imm" to "$Rdd = combine(#[-1,0], #-imm)"
16110b57cec5SDimitry Andric   case Hexagon::A2_tfrpi: {
16120b57cec5SDimitry Andric     MCOperand &Rdd = Inst.getOperand(0);
16130b57cec5SDimitry Andric     MCOperand &MO = Inst.getOperand(1);
16140b57cec5SDimitry Andric     int64_t Value;
16150b57cec5SDimitry Andric     int sVal = (MO.getExpr()->evaluateAsAbsolute(Value) && Value < 0) ? -1 : 0;
16160b57cec5SDimitry Andric     MCOperand imm(MCOperand::createExpr(
16170b57cec5SDimitry Andric         HexagonMCExpr::create(MCConstantExpr::create(sVal, Context), Context)));
16180b57cec5SDimitry Andric     Inst = makeCombineInst(Hexagon::A2_combineii, Rdd, imm, MO);
16190b57cec5SDimitry Andric     break;
16200b57cec5SDimitry Andric   }
16210b57cec5SDimitry Andric 
16220b57cec5SDimitry Andric   // Translate a "$Rdd = [#]#imm" to "$Rdd = combine(#, [#]#imm)"
16230b57cec5SDimitry Andric   case Hexagon::TFRI64_V4: {
16240b57cec5SDimitry Andric     MCOperand &Rdd = Inst.getOperand(0);
16250b57cec5SDimitry Andric     MCOperand &MO = Inst.getOperand(1);
16260b57cec5SDimitry Andric     int64_t Value;
16270b57cec5SDimitry Andric     if (MO.getExpr()->evaluateAsAbsolute(Value)) {
16280b57cec5SDimitry Andric       int s8 = Hi_32(Value);
16290b57cec5SDimitry Andric       if (!isInt<8>(s8))
16300b57cec5SDimitry Andric         OutOfRange(IDLoc, s8, -128);
16310b57cec5SDimitry Andric       MCOperand imm(MCOperand::createExpr(HexagonMCExpr::create(
16320b57cec5SDimitry Andric           MCConstantExpr::create(s8, Context), Context))); // upper 32
16330b57cec5SDimitry Andric       auto Expr = HexagonMCExpr::create(
16340b57cec5SDimitry Andric           MCConstantExpr::create(Lo_32(Value), Context), Context);
16350b57cec5SDimitry Andric       HexagonMCInstrInfo::setMustExtend(
16360b57cec5SDimitry Andric           *Expr, HexagonMCInstrInfo::mustExtend(*MO.getExpr()));
16370b57cec5SDimitry Andric       MCOperand imm2(MCOperand::createExpr(Expr)); // lower 32
16380b57cec5SDimitry Andric       Inst = makeCombineInst(Hexagon::A4_combineii, Rdd, imm, imm2);
16390b57cec5SDimitry Andric     } else {
16400b57cec5SDimitry Andric       MCOperand imm(MCOperand::createExpr(HexagonMCExpr::create(
16410b57cec5SDimitry Andric           MCConstantExpr::create(0, Context), Context))); // upper 32
16420b57cec5SDimitry Andric       Inst = makeCombineInst(Hexagon::A4_combineii, Rdd, imm, MO);
16430b57cec5SDimitry Andric     }
16440b57cec5SDimitry Andric     break;
16450b57cec5SDimitry Andric   }
16460b57cec5SDimitry Andric 
16470b57cec5SDimitry Andric   // Handle $Rdd = combine(##imm, #imm)"
16480b57cec5SDimitry Andric   case Hexagon::TFRI64_V2_ext: {
16490b57cec5SDimitry Andric     MCOperand &Rdd = Inst.getOperand(0);
16500b57cec5SDimitry Andric     MCOperand &MO1 = Inst.getOperand(1);
16510b57cec5SDimitry Andric     MCOperand &MO2 = Inst.getOperand(2);
16520b57cec5SDimitry Andric     int64_t Value;
16530b57cec5SDimitry Andric     if (MO2.getExpr()->evaluateAsAbsolute(Value)) {
16540b57cec5SDimitry Andric       int s8 = Value;
16550b57cec5SDimitry Andric       if (s8 < -128 || s8 > 127)
16560b57cec5SDimitry Andric         OutOfRange(IDLoc, s8, -128);
16570b57cec5SDimitry Andric     }
16580b57cec5SDimitry Andric     Inst = makeCombineInst(Hexagon::A2_combineii, Rdd, MO1, MO2);
16590b57cec5SDimitry Andric     break;
16600b57cec5SDimitry Andric   }
16610b57cec5SDimitry Andric 
16620b57cec5SDimitry Andric   // Handle $Rdd = combine(#imm, ##imm)"
16630b57cec5SDimitry Andric   case Hexagon::A4_combineii: {
16640b57cec5SDimitry Andric     MCOperand &Rdd = Inst.getOperand(0);
16650b57cec5SDimitry Andric     MCOperand &MO1 = Inst.getOperand(1);
16660b57cec5SDimitry Andric     int64_t Value;
16670b57cec5SDimitry Andric     if (MO1.getExpr()->evaluateAsAbsolute(Value)) {
16680b57cec5SDimitry Andric       int s8 = Value;
16690b57cec5SDimitry Andric       if (s8 < -128 || s8 > 127)
16700b57cec5SDimitry Andric         OutOfRange(IDLoc, s8, -128);
16710b57cec5SDimitry Andric     }
16720b57cec5SDimitry Andric     MCOperand &MO2 = Inst.getOperand(2);
16730b57cec5SDimitry Andric     Inst = makeCombineInst(Hexagon::A4_combineii, Rdd, MO1, MO2);
16740b57cec5SDimitry Andric     break;
16750b57cec5SDimitry Andric   }
16760b57cec5SDimitry Andric 
16770b57cec5SDimitry Andric   case Hexagon::S2_tableidxb_goodsyntax:
16780b57cec5SDimitry Andric     Inst.setOpcode(Hexagon::S2_tableidxb);
16790b57cec5SDimitry Andric     break;
16800b57cec5SDimitry Andric 
16810b57cec5SDimitry Andric   case Hexagon::S2_tableidxh_goodsyntax: {
16820b57cec5SDimitry Andric     MCInst TmpInst;
16830b57cec5SDimitry Andric     MCOperand &Rx = Inst.getOperand(0);
16840b57cec5SDimitry Andric     MCOperand &Rs = Inst.getOperand(2);
16850b57cec5SDimitry Andric     MCOperand &Imm4 = Inst.getOperand(3);
16860b57cec5SDimitry Andric     MCOperand &Imm6 = Inst.getOperand(4);
16870b57cec5SDimitry Andric     Imm6.setExpr(HexagonMCExpr::create(
16880b57cec5SDimitry Andric         MCBinaryExpr::createSub(Imm6.getExpr(),
16890b57cec5SDimitry Andric                                 MCConstantExpr::create(1, Context), Context),
16900b57cec5SDimitry Andric         Context));
16910b57cec5SDimitry Andric     TmpInst.setOpcode(Hexagon::S2_tableidxh);
16920b57cec5SDimitry Andric     TmpInst.addOperand(Rx);
16930b57cec5SDimitry Andric     TmpInst.addOperand(Rx);
16940b57cec5SDimitry Andric     TmpInst.addOperand(Rs);
16950b57cec5SDimitry Andric     TmpInst.addOperand(Imm4);
16960b57cec5SDimitry Andric     TmpInst.addOperand(Imm6);
16970b57cec5SDimitry Andric     Inst = TmpInst;
16980b57cec5SDimitry Andric     break;
16990b57cec5SDimitry Andric   }
17000b57cec5SDimitry Andric 
17010b57cec5SDimitry Andric   case Hexagon::S2_tableidxw_goodsyntax: {
17020b57cec5SDimitry Andric     MCInst TmpInst;
17030b57cec5SDimitry Andric     MCOperand &Rx = Inst.getOperand(0);
17040b57cec5SDimitry Andric     MCOperand &Rs = Inst.getOperand(2);
17050b57cec5SDimitry Andric     MCOperand &Imm4 = Inst.getOperand(3);
17060b57cec5SDimitry Andric     MCOperand &Imm6 = Inst.getOperand(4);
17070b57cec5SDimitry Andric     Imm6.setExpr(HexagonMCExpr::create(
17080b57cec5SDimitry Andric         MCBinaryExpr::createSub(Imm6.getExpr(),
17090b57cec5SDimitry Andric                                 MCConstantExpr::create(2, Context), Context),
17100b57cec5SDimitry Andric         Context));
17110b57cec5SDimitry Andric     TmpInst.setOpcode(Hexagon::S2_tableidxw);
17120b57cec5SDimitry Andric     TmpInst.addOperand(Rx);
17130b57cec5SDimitry Andric     TmpInst.addOperand(Rx);
17140b57cec5SDimitry Andric     TmpInst.addOperand(Rs);
17150b57cec5SDimitry Andric     TmpInst.addOperand(Imm4);
17160b57cec5SDimitry Andric     TmpInst.addOperand(Imm6);
17170b57cec5SDimitry Andric     Inst = TmpInst;
17180b57cec5SDimitry Andric     break;
17190b57cec5SDimitry Andric   }
17200b57cec5SDimitry Andric 
17210b57cec5SDimitry Andric   case Hexagon::S2_tableidxd_goodsyntax: {
17220b57cec5SDimitry Andric     MCInst TmpInst;
17230b57cec5SDimitry Andric     MCOperand &Rx = Inst.getOperand(0);
17240b57cec5SDimitry Andric     MCOperand &Rs = Inst.getOperand(2);
17250b57cec5SDimitry Andric     MCOperand &Imm4 = Inst.getOperand(3);
17260b57cec5SDimitry Andric     MCOperand &Imm6 = Inst.getOperand(4);
17270b57cec5SDimitry Andric     Imm6.setExpr(HexagonMCExpr::create(
17280b57cec5SDimitry Andric         MCBinaryExpr::createSub(Imm6.getExpr(),
17290b57cec5SDimitry Andric                                 MCConstantExpr::create(3, Context), Context),
17300b57cec5SDimitry Andric         Context));
17310b57cec5SDimitry Andric     TmpInst.setOpcode(Hexagon::S2_tableidxd);
17320b57cec5SDimitry Andric     TmpInst.addOperand(Rx);
17330b57cec5SDimitry Andric     TmpInst.addOperand(Rx);
17340b57cec5SDimitry Andric     TmpInst.addOperand(Rs);
17350b57cec5SDimitry Andric     TmpInst.addOperand(Imm4);
17360b57cec5SDimitry Andric     TmpInst.addOperand(Imm6);
17370b57cec5SDimitry Andric     Inst = TmpInst;
17380b57cec5SDimitry Andric     break;
17390b57cec5SDimitry Andric   }
17400b57cec5SDimitry Andric 
17410b57cec5SDimitry Andric   case Hexagon::M2_mpyui:
17420b57cec5SDimitry Andric     Inst.setOpcode(Hexagon::M2_mpyi);
17430b57cec5SDimitry Andric     break;
17440b57cec5SDimitry Andric   case Hexagon::M2_mpysmi: {
17450b57cec5SDimitry Andric     MCInst TmpInst;
17460b57cec5SDimitry Andric     MCOperand &Rd = Inst.getOperand(0);
17470b57cec5SDimitry Andric     MCOperand &Rs = Inst.getOperand(1);
17480b57cec5SDimitry Andric     MCOperand &Imm = Inst.getOperand(2);
17490b57cec5SDimitry Andric     int64_t Value;
17500b57cec5SDimitry Andric     MCExpr const &Expr = *Imm.getExpr();
17510b57cec5SDimitry Andric     bool Absolute = Expr.evaluateAsAbsolute(Value);
17520b57cec5SDimitry Andric     if (!Absolute)
17530b57cec5SDimitry Andric       return Match_InvalidOperand;
17540b57cec5SDimitry Andric     if (!HexagonMCInstrInfo::mustExtend(Expr) &&
17550b57cec5SDimitry Andric         ((Value <= -256) || Value >= 256))
17560b57cec5SDimitry Andric       return Match_InvalidOperand;
17570b57cec5SDimitry Andric     if (Value < 0 && Value > -256) {
17580b57cec5SDimitry Andric       Imm.setExpr(HexagonMCExpr::create(
17590b57cec5SDimitry Andric           MCConstantExpr::create(Value * -1, Context), Context));
17600b57cec5SDimitry Andric       TmpInst.setOpcode(Hexagon::M2_mpysin);
17610b57cec5SDimitry Andric     } else
17620b57cec5SDimitry Andric       TmpInst.setOpcode(Hexagon::M2_mpysip);
17630b57cec5SDimitry Andric     TmpInst.addOperand(Rd);
17640b57cec5SDimitry Andric     TmpInst.addOperand(Rs);
17650b57cec5SDimitry Andric     TmpInst.addOperand(Imm);
17660b57cec5SDimitry Andric     Inst = TmpInst;
17670b57cec5SDimitry Andric     break;
17680b57cec5SDimitry Andric   }
17690b57cec5SDimitry Andric 
17700b57cec5SDimitry Andric   case Hexagon::S2_asr_i_r_rnd_goodsyntax: {
17710b57cec5SDimitry Andric     MCOperand &Imm = Inst.getOperand(2);
17720b57cec5SDimitry Andric     MCInst TmpInst;
17730b57cec5SDimitry Andric     int64_t Value;
17740b57cec5SDimitry Andric     bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Value);
17750b57cec5SDimitry Andric     if (!Absolute)
17760b57cec5SDimitry Andric       return Match_InvalidOperand;
17770b57cec5SDimitry Andric     if (Value == 0) { // convert to $Rd = $Rs
17780b57cec5SDimitry Andric       TmpInst.setOpcode(Hexagon::A2_tfr);
17790b57cec5SDimitry Andric       MCOperand &Rd = Inst.getOperand(0);
17800b57cec5SDimitry Andric       MCOperand &Rs = Inst.getOperand(1);
17810b57cec5SDimitry Andric       TmpInst.addOperand(Rd);
17820b57cec5SDimitry Andric       TmpInst.addOperand(Rs);
17830b57cec5SDimitry Andric     } else {
17840b57cec5SDimitry Andric       Imm.setExpr(HexagonMCExpr::create(
17850b57cec5SDimitry Andric           MCBinaryExpr::createSub(Imm.getExpr(),
17860b57cec5SDimitry Andric                                   MCConstantExpr::create(1, Context), Context),
17870b57cec5SDimitry Andric           Context));
17880b57cec5SDimitry Andric       TmpInst.setOpcode(Hexagon::S2_asr_i_r_rnd);
17890b57cec5SDimitry Andric       MCOperand &Rd = Inst.getOperand(0);
17900b57cec5SDimitry Andric       MCOperand &Rs = Inst.getOperand(1);
17910b57cec5SDimitry Andric       TmpInst.addOperand(Rd);
17920b57cec5SDimitry Andric       TmpInst.addOperand(Rs);
17930b57cec5SDimitry Andric       TmpInst.addOperand(Imm);
17940b57cec5SDimitry Andric     }
17950b57cec5SDimitry Andric     Inst = TmpInst;
17960b57cec5SDimitry Andric     break;
17970b57cec5SDimitry Andric   }
17980b57cec5SDimitry Andric 
17990b57cec5SDimitry Andric   case Hexagon::S2_asr_i_p_rnd_goodsyntax: {
18000b57cec5SDimitry Andric     MCOperand &Rdd = Inst.getOperand(0);
18010b57cec5SDimitry Andric     MCOperand &Rss = Inst.getOperand(1);
18020b57cec5SDimitry Andric     MCOperand &Imm = Inst.getOperand(2);
18030b57cec5SDimitry Andric     int64_t Value;
18040b57cec5SDimitry Andric     bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Value);
18050b57cec5SDimitry Andric     if (!Absolute)
18060b57cec5SDimitry Andric       return Match_InvalidOperand;
18070b57cec5SDimitry Andric     if (Value == 0) { // convert to $Rdd = combine ($Rs[0], $Rs[1])
18080b57cec5SDimitry Andric       MCInst TmpInst;
18090b57cec5SDimitry Andric       unsigned int RegPairNum = RI->getEncodingValue(Rss.getReg());
18100b57cec5SDimitry Andric       std::string R1 = r + utostr(RegPairNum + 1);
18110b57cec5SDimitry Andric       StringRef Reg1(R1);
18120b57cec5SDimitry Andric       Rss.setReg(matchRegister(Reg1));
18130b57cec5SDimitry Andric       // Add a new operand for the second register in the pair.
18140b57cec5SDimitry Andric       std::string R2 = r + utostr(RegPairNum);
18150b57cec5SDimitry Andric       StringRef Reg2(R2);
18160b57cec5SDimitry Andric       TmpInst.setOpcode(Hexagon::A2_combinew);
18170b57cec5SDimitry Andric       TmpInst.addOperand(Rdd);
18180b57cec5SDimitry Andric       TmpInst.addOperand(Rss);
18190b57cec5SDimitry Andric       TmpInst.addOperand(MCOperand::createReg(matchRegister(Reg2)));
18200b57cec5SDimitry Andric       Inst = TmpInst;
18210b57cec5SDimitry Andric     } else {
18220b57cec5SDimitry Andric       Imm.setExpr(HexagonMCExpr::create(
18230b57cec5SDimitry Andric           MCBinaryExpr::createSub(Imm.getExpr(),
18240b57cec5SDimitry Andric                                   MCConstantExpr::create(1, Context), Context),
18250b57cec5SDimitry Andric           Context));
18260b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::S2_asr_i_p_rnd);
18270b57cec5SDimitry Andric     }
18280b57cec5SDimitry Andric     break;
18290b57cec5SDimitry Andric   }
18300b57cec5SDimitry Andric 
18310b57cec5SDimitry Andric   case Hexagon::A4_boundscheck: {
18320b57cec5SDimitry Andric     MCOperand &Rs = Inst.getOperand(1);
18330b57cec5SDimitry Andric     unsigned int RegNum = RI->getEncodingValue(Rs.getReg());
18340b57cec5SDimitry Andric     if (RegNum & 1) { // Odd mapped to raw:hi, regpair is rodd:odd-1, like r3:2
18350b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::A4_boundscheck_hi);
18360b57cec5SDimitry Andric       std::string Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
18370b57cec5SDimitry Andric       StringRef RegPair = Name;
18380b57cec5SDimitry Andric       Rs.setReg(matchRegister(RegPair));
18390b57cec5SDimitry Andric     } else { // raw:lo
18400b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::A4_boundscheck_lo);
18410b57cec5SDimitry Andric       std::string Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
18420b57cec5SDimitry Andric       StringRef RegPair = Name;
18430b57cec5SDimitry Andric       Rs.setReg(matchRegister(RegPair));
18440b57cec5SDimitry Andric     }
18450b57cec5SDimitry Andric     break;
18460b57cec5SDimitry Andric   }
18470b57cec5SDimitry Andric 
18480b57cec5SDimitry Andric   case Hexagon::A2_addsp: {
18490b57cec5SDimitry Andric     MCOperand &Rs = Inst.getOperand(1);
18500b57cec5SDimitry Andric     unsigned int RegNum = RI->getEncodingValue(Rs.getReg());
18510b57cec5SDimitry Andric     if (RegNum & 1) { // Odd mapped to raw:hi
18520b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::A2_addsph);
18530b57cec5SDimitry Andric       std::string Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
18540b57cec5SDimitry Andric       StringRef RegPair = Name;
18550b57cec5SDimitry Andric       Rs.setReg(matchRegister(RegPair));
18560b57cec5SDimitry Andric     } else { // Even mapped raw:lo
18570b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::A2_addspl);
18580b57cec5SDimitry Andric       std::string Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
18590b57cec5SDimitry Andric       StringRef RegPair = Name;
18600b57cec5SDimitry Andric       Rs.setReg(matchRegister(RegPair));
18610b57cec5SDimitry Andric     }
18620b57cec5SDimitry Andric     break;
18630b57cec5SDimitry Andric   }
18640b57cec5SDimitry Andric 
18650b57cec5SDimitry Andric   case Hexagon::M2_vrcmpys_s1: {
18660b57cec5SDimitry Andric     MCOperand &Rt = Inst.getOperand(2);
18670b57cec5SDimitry Andric     unsigned int RegNum = RI->getEncodingValue(Rt.getReg());
18680b57cec5SDimitry Andric     if (RegNum & 1) { // Odd mapped to sat:raw:hi
18690b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::M2_vrcmpys_s1_h);
18700b57cec5SDimitry Andric       std::string Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
18710b57cec5SDimitry Andric       StringRef RegPair = Name;
18720b57cec5SDimitry Andric       Rt.setReg(matchRegister(RegPair));
18730b57cec5SDimitry Andric     } else { // Even mapped sat:raw:lo
18740b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::M2_vrcmpys_s1_l);
18750b57cec5SDimitry Andric       std::string Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
18760b57cec5SDimitry Andric       StringRef RegPair = Name;
18770b57cec5SDimitry Andric       Rt.setReg(matchRegister(RegPair));
18780b57cec5SDimitry Andric     }
18790b57cec5SDimitry Andric     break;
18800b57cec5SDimitry Andric   }
18810b57cec5SDimitry Andric 
18820b57cec5SDimitry Andric   case Hexagon::M2_vrcmpys_acc_s1: {
18830b57cec5SDimitry Andric     MCInst TmpInst;
18840b57cec5SDimitry Andric     MCOperand &Rxx = Inst.getOperand(0);
18850b57cec5SDimitry Andric     MCOperand &Rss = Inst.getOperand(2);
18860b57cec5SDimitry Andric     MCOperand &Rt = Inst.getOperand(3);
18870b57cec5SDimitry Andric     unsigned int RegNum = RI->getEncodingValue(Rt.getReg());
18880b57cec5SDimitry Andric     if (RegNum & 1) { // Odd mapped to sat:raw:hi
18890b57cec5SDimitry Andric       TmpInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_h);
18900b57cec5SDimitry Andric       std::string Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
18910b57cec5SDimitry Andric       StringRef RegPair = Name;
18920b57cec5SDimitry Andric       Rt.setReg(matchRegister(RegPair));
18930b57cec5SDimitry Andric     } else { // Even mapped sat:raw:lo
18940b57cec5SDimitry Andric       TmpInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_l);
18950b57cec5SDimitry Andric       std::string Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
18960b57cec5SDimitry Andric       StringRef RegPair = Name;
18970b57cec5SDimitry Andric       Rt.setReg(matchRegister(RegPair));
18980b57cec5SDimitry Andric     }
18990b57cec5SDimitry Andric     // Registers are in different positions
19000b57cec5SDimitry Andric     TmpInst.addOperand(Rxx);
19010b57cec5SDimitry Andric     TmpInst.addOperand(Rxx);
19020b57cec5SDimitry Andric     TmpInst.addOperand(Rss);
19030b57cec5SDimitry Andric     TmpInst.addOperand(Rt);
19040b57cec5SDimitry Andric     Inst = TmpInst;
19050b57cec5SDimitry Andric     break;
19060b57cec5SDimitry Andric   }
19070b57cec5SDimitry Andric 
19080b57cec5SDimitry Andric   case Hexagon::M2_vrcmpys_s1rp: {
19090b57cec5SDimitry Andric     MCOperand &Rt = Inst.getOperand(2);
19100b57cec5SDimitry Andric     unsigned int RegNum = RI->getEncodingValue(Rt.getReg());
19110b57cec5SDimitry Andric     if (RegNum & 1) { // Odd mapped to rnd:sat:raw:hi
19120b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::M2_vrcmpys_s1rp_h);
19130b57cec5SDimitry Andric       std::string Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
19140b57cec5SDimitry Andric       StringRef RegPair = Name;
19150b57cec5SDimitry Andric       Rt.setReg(matchRegister(RegPair));
19160b57cec5SDimitry Andric     } else { // Even mapped rnd:sat:raw:lo
19170b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::M2_vrcmpys_s1rp_l);
19180b57cec5SDimitry Andric       std::string Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
19190b57cec5SDimitry Andric       StringRef RegPair = Name;
19200b57cec5SDimitry Andric       Rt.setReg(matchRegister(RegPair));
19210b57cec5SDimitry Andric     }
19220b57cec5SDimitry Andric     break;
19230b57cec5SDimitry Andric   }
19240b57cec5SDimitry Andric 
19250b57cec5SDimitry Andric   case Hexagon::S5_asrhub_rnd_sat_goodsyntax: {
19260b57cec5SDimitry Andric     MCOperand &Imm = Inst.getOperand(2);
19270b57cec5SDimitry Andric     int64_t Value;
19280b57cec5SDimitry Andric     bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Value);
19290b57cec5SDimitry Andric     if (!Absolute)
19300b57cec5SDimitry Andric       return Match_InvalidOperand;
19310b57cec5SDimitry Andric     if (Value == 0)
19320b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::S2_vsathub);
19330b57cec5SDimitry Andric     else {
19340b57cec5SDimitry Andric       Imm.setExpr(HexagonMCExpr::create(
19350b57cec5SDimitry Andric           MCBinaryExpr::createSub(Imm.getExpr(),
19360b57cec5SDimitry Andric                                   MCConstantExpr::create(1, Context), Context),
19370b57cec5SDimitry Andric           Context));
19380b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::S5_asrhub_rnd_sat);
19390b57cec5SDimitry Andric     }
19400b57cec5SDimitry Andric     break;
19410b57cec5SDimitry Andric   }
19420b57cec5SDimitry Andric 
19430b57cec5SDimitry Andric   case Hexagon::S5_vasrhrnd_goodsyntax: {
19440b57cec5SDimitry Andric     MCOperand &Rdd = Inst.getOperand(0);
19450b57cec5SDimitry Andric     MCOperand &Rss = Inst.getOperand(1);
19460b57cec5SDimitry Andric     MCOperand &Imm = Inst.getOperand(2);
19470b57cec5SDimitry Andric     int64_t Value;
19480b57cec5SDimitry Andric     bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Value);
19490b57cec5SDimitry Andric     if (!Absolute)
19500b57cec5SDimitry Andric       return Match_InvalidOperand;
19510b57cec5SDimitry Andric     if (Value == 0) {
19520b57cec5SDimitry Andric       MCInst TmpInst;
19530b57cec5SDimitry Andric       unsigned int RegPairNum = RI->getEncodingValue(Rss.getReg());
19540b57cec5SDimitry Andric       std::string R1 = r + utostr(RegPairNum + 1);
19550b57cec5SDimitry Andric       StringRef Reg1(R1);
19560b57cec5SDimitry Andric       Rss.setReg(matchRegister(Reg1));
19570b57cec5SDimitry Andric       // Add a new operand for the second register in the pair.
19580b57cec5SDimitry Andric       std::string R2 = r + utostr(RegPairNum);
19590b57cec5SDimitry Andric       StringRef Reg2(R2);
19600b57cec5SDimitry Andric       TmpInst.setOpcode(Hexagon::A2_combinew);
19610b57cec5SDimitry Andric       TmpInst.addOperand(Rdd);
19620b57cec5SDimitry Andric       TmpInst.addOperand(Rss);
19630b57cec5SDimitry Andric       TmpInst.addOperand(MCOperand::createReg(matchRegister(Reg2)));
19640b57cec5SDimitry Andric       Inst = TmpInst;
19650b57cec5SDimitry Andric     } else {
19660b57cec5SDimitry Andric       Imm.setExpr(HexagonMCExpr::create(
19670b57cec5SDimitry Andric           MCBinaryExpr::createSub(Imm.getExpr(),
19680b57cec5SDimitry Andric                                   MCConstantExpr::create(1, Context), Context),
19690b57cec5SDimitry Andric           Context));
19700b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::S5_vasrhrnd);
19710b57cec5SDimitry Andric     }
19720b57cec5SDimitry Andric     break;
19730b57cec5SDimitry Andric   }
19740b57cec5SDimitry Andric 
19750b57cec5SDimitry Andric   case Hexagon::A2_not: {
19760b57cec5SDimitry Andric     MCInst TmpInst;
19770b57cec5SDimitry Andric     MCOperand &Rd = Inst.getOperand(0);
19780b57cec5SDimitry Andric     MCOperand &Rs = Inst.getOperand(1);
19790b57cec5SDimitry Andric     TmpInst.setOpcode(Hexagon::A2_subri);
19800b57cec5SDimitry Andric     TmpInst.addOperand(Rd);
19810b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createExpr(
19820b57cec5SDimitry Andric         HexagonMCExpr::create(MCConstantExpr::create(-1, Context), Context)));
19830b57cec5SDimitry Andric     TmpInst.addOperand(Rs);
19840b57cec5SDimitry Andric     Inst = TmpInst;
19850b57cec5SDimitry Andric     break;
19860b57cec5SDimitry Andric   }
19870b57cec5SDimitry Andric   case Hexagon::PS_loadrubabs:
19880b57cec5SDimitry Andric     if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(1).getExpr()))
19890b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::L2_loadrubgp);
19900b57cec5SDimitry Andric     break;
19910b57cec5SDimitry Andric   case Hexagon::PS_loadrbabs:
19920b57cec5SDimitry Andric     if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(1).getExpr()))
19930b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::L2_loadrbgp);
19940b57cec5SDimitry Andric     break;
19950b57cec5SDimitry Andric   case Hexagon::PS_loadruhabs:
19960b57cec5SDimitry Andric     if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(1).getExpr()))
19970b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::L2_loadruhgp);
19980b57cec5SDimitry Andric     break;
19990b57cec5SDimitry Andric   case Hexagon::PS_loadrhabs:
20000b57cec5SDimitry Andric     if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(1).getExpr()))
20010b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::L2_loadrhgp);
20020b57cec5SDimitry Andric     break;
20030b57cec5SDimitry Andric   case Hexagon::PS_loadriabs:
20040b57cec5SDimitry Andric     if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(1).getExpr()))
20050b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::L2_loadrigp);
20060b57cec5SDimitry Andric     break;
20070b57cec5SDimitry Andric   case Hexagon::PS_loadrdabs:
20080b57cec5SDimitry Andric     if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(1).getExpr()))
20090b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::L2_loadrdgp);
20100b57cec5SDimitry Andric     break;
20110b57cec5SDimitry Andric   case Hexagon::PS_storerbabs:
20120b57cec5SDimitry Andric     if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(0).getExpr()))
20130b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::S2_storerbgp);
20140b57cec5SDimitry Andric     break;
20150b57cec5SDimitry Andric   case Hexagon::PS_storerhabs:
20160b57cec5SDimitry Andric     if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(0).getExpr()))
20170b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::S2_storerhgp);
20180b57cec5SDimitry Andric     break;
20190b57cec5SDimitry Andric   case Hexagon::PS_storerfabs:
20200b57cec5SDimitry Andric     if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(0).getExpr()))
20210b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::S2_storerfgp);
20220b57cec5SDimitry Andric     break;
20230b57cec5SDimitry Andric   case Hexagon::PS_storeriabs:
20240b57cec5SDimitry Andric     if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(0).getExpr()))
20250b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::S2_storerigp);
20260b57cec5SDimitry Andric     break;
20270b57cec5SDimitry Andric   case Hexagon::PS_storerdabs:
20280b57cec5SDimitry Andric     if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(0).getExpr()))
20290b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::S2_storerdgp);
20300b57cec5SDimitry Andric     break;
20310b57cec5SDimitry Andric   case Hexagon::PS_storerbnewabs:
20320b57cec5SDimitry Andric     if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(0).getExpr()))
20330b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::S2_storerbnewgp);
20340b57cec5SDimitry Andric     break;
20350b57cec5SDimitry Andric   case Hexagon::PS_storerhnewabs:
20360b57cec5SDimitry Andric     if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(0).getExpr()))
20370b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::S2_storerhnewgp);
20380b57cec5SDimitry Andric     break;
20390b57cec5SDimitry Andric   case Hexagon::PS_storerinewabs:
20400b57cec5SDimitry Andric     if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(0).getExpr()))
20410b57cec5SDimitry Andric       Inst.setOpcode(Hexagon::S2_storerinewgp);
20420b57cec5SDimitry Andric     break;
20430b57cec5SDimitry Andric   case Hexagon::A2_zxtb: {
20440b57cec5SDimitry Andric     Inst.setOpcode(Hexagon::A2_andir);
20450b57cec5SDimitry Andric     Inst.addOperand(
20460b57cec5SDimitry Andric         MCOperand::createExpr(MCConstantExpr::create(255, Context)));
20470b57cec5SDimitry Andric     break;
20480b57cec5SDimitry Andric   }
20490b57cec5SDimitry Andric   } // switch
20500b57cec5SDimitry Andric 
20510b57cec5SDimitry Andric   return Match_Success;
20520b57cec5SDimitry Andric }
20530b57cec5SDimitry Andric 
matchRegister(StringRef Name)20540b57cec5SDimitry Andric unsigned HexagonAsmParser::matchRegister(StringRef Name) {
20550b57cec5SDimitry Andric   if (unsigned Reg = MatchRegisterName(Name))
20560b57cec5SDimitry Andric     return Reg;
20570b57cec5SDimitry Andric   return MatchRegisterAltName(Name);
20580b57cec5SDimitry Andric }
2059