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