1//===-- HexagonAsmParser.cpp - Parse Hexagon asm to MCInst instructions----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "MCTargetDesc/HexagonMCAsmInfo.h"
10#include "MCTargetDesc/HexagonMCChecker.h"
11#include "MCTargetDesc/HexagonMCELFStreamer.h"
12#include "MCTargetDesc/HexagonMCExpr.h"
13#include "MCTargetDesc/HexagonMCInstrInfo.h"
14#include "MCTargetDesc/HexagonMCTargetDesc.h"
15#include "MCTargetDesc/HexagonShuffler.h"
16#include "MCTargetDesc/HexagonTargetStreamer.h"
17#include "TargetInfo/HexagonTargetInfo.h"
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/SmallVector.h"
20#include "llvm/ADT/StringExtras.h"
21#include "llvm/ADT/StringRef.h"
22#include "llvm/ADT/Twine.h"
23#include "llvm/BinaryFormat/ELF.h"
24#include "llvm/MC/MCAssembler.h"
25#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCDirectives.h"
27#include "llvm/MC/MCELFStreamer.h"
28#include "llvm/MC/MCExpr.h"
29#include "llvm/MC/MCInst.h"
30#include "llvm/MC/MCParser/AsmLexer.h"
31#include "llvm/MC/MCParser/MCAsmParser.h"
32#include "llvm/MC/MCParser/MCAsmParserExtension.h"
33#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
34#include "llvm/MC/MCParser/MCTargetAsmParser.h"
35#include "llvm/MC/MCRegisterInfo.h"
36#include "llvm/MC/MCSectionELF.h"
37#include "llvm/MC/MCStreamer.h"
38#include "llvm/MC/MCSubtargetInfo.h"
39#include "llvm/MC/MCSymbol.h"
40#include "llvm/MC/MCValue.h"
41#include "llvm/MC/TargetRegistry.h"
42#include "llvm/Support/Casting.h"
43#include "llvm/Support/CommandLine.h"
44#include "llvm/Support/Compiler.h"
45#include "llvm/Support/Debug.h"
46#include "llvm/Support/ErrorHandling.h"
47#include "llvm/Support/Format.h"
48#include "llvm/Support/HexagonAttributes.h"
49#include "llvm/Support/MathExtras.h"
50#include "llvm/Support/SMLoc.h"
51#include "llvm/Support/SourceMgr.h"
52#include "llvm/Support/raw_ostream.h"
53#include <cassert>
54#include <cctype>
55#include <cstddef>
56#include <cstdint>
57#include <memory>
58#include <string>
59#include <utility>
60
61#define DEBUG_TYPE "mcasmparser"
62
63using namespace llvm;
64
65static cl::opt<bool> WarnMissingParenthesis(
66 "mwarn-missing-parenthesis",
67 cl::desc("Warn for missing parenthesis around predicate registers"),
68 cl::init(Val: true));
69static cl::opt<bool> ErrorMissingParenthesis(
70 "merror-missing-parenthesis",
71 cl::desc("Error for missing parenthesis around predicate registers"),
72 cl::init(Val: false));
73static cl::opt<bool> WarnSignedMismatch(
74 "mwarn-sign-mismatch",
75 cl::desc("Warn for mismatching a signed and unsigned value"),
76 cl::init(Val: false));
77static cl::opt<bool> WarnNoncontigiousRegister(
78 "mwarn-noncontigious-register",
79 cl::desc("Warn for register names that aren't contigious"), cl::init(Val: true));
80static cl::opt<bool> ErrorNoncontigiousRegister(
81 "merror-noncontigious-register",
82 cl::desc("Error for register names that aren't contigious"),
83 cl::init(Val: false));
84static cl::opt<bool> AddBuildAttributes("hexagon-add-build-attributes");
85namespace {
86
87struct HexagonOperand;
88
89class HexagonAsmParser : public MCTargetAsmParser {
90
91 HexagonTargetStreamer &getTargetStreamer() {
92 MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer();
93 return static_cast<HexagonTargetStreamer &>(TS);
94 }
95
96 MCAsmParser &Parser;
97 MCInst MCB;
98 bool InBrackets;
99
100 MCAsmParser &getParser() const { return Parser; }
101 MCAssembler *getAssembler() const {
102 MCAssembler *Assembler = nullptr;
103 // FIXME: need better way to detect AsmStreamer (upstream removed getKind())
104 if (!Parser.getStreamer().hasRawTextSupport()) {
105 MCELFStreamer *MES = static_cast<MCELFStreamer *>(&Parser.getStreamer());
106 Assembler = &MES->getAssembler();
107 }
108 return Assembler;
109 }
110
111 AsmLexer &getLexer() const { return Parser.getLexer(); }
112
113 bool equalIsAsmAssignment() override { return false; }
114 bool isLabel(AsmToken &Token) override;
115 bool tokenIsStartOfStatement(AsmToken::TokenKind Token) override;
116
117 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
118 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
119 bool ParseDirectiveFalign(unsigned Size, SMLoc L);
120
121 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
122 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
123 SMLoc &EndLoc) override;
124 bool ParseDirectiveSubsection(SMLoc L);
125 bool ParseDirectiveComm(bool IsLocal, SMLoc L);
126
127 bool parseDirectiveAttribute(SMLoc L);
128
129 bool RegisterMatchesArch(MCRegister MatchNum) const;
130
131 bool matchBundleOptions();
132 bool handleNoncontigiousRegister(bool Contigious, SMLoc &Loc);
133 bool finishBundle(SMLoc IDLoc, MCStreamer &Out);
134 void canonicalizeImmediates(MCInst &MCI);
135 bool matchOneInstruction(MCInst &MCB, SMLoc IDLoc,
136 OperandVector &InstOperands, uint64_t &ErrorInfo,
137 bool MatchingInlineAsm);
138 void eatToEndOfPacket();
139 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
140 OperandVector &Operands, MCStreamer &Out,
141 uint64_t &ErrorInfo,
142 bool MatchingInlineAsm) override;
143
144 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
145 unsigned Kind) override;
146 bool OutOfRange(SMLoc IDLoc, long long Val, long long Max);
147 int processInstruction(MCInst &Inst, OperandVector const &Operands,
148 SMLoc IDLoc);
149
150 MCRegister matchRegister(StringRef Name);
151
152 /// @name Auto-generated Match Functions
153 /// {
154
155#define GET_ASSEMBLER_HEADER
156#include "HexagonGenAsmMatcher.inc"
157
158 /// }
159
160public:
161 HexagonAsmParser(const MCSubtargetInfo &_STI, MCAsmParser &_Parser,
162 const MCInstrInfo &MII)
163 : MCTargetAsmParser(_STI, MII), Parser(_Parser), InBrackets(false) {
164 MCB.setOpcode(Hexagon::BUNDLE);
165 setAvailableFeatures(ComputeAvailableFeatures(FB: getSTI().getFeatureBits()));
166
167 Parser.addAliasForDirective(Directive: ".half", Alias: ".2byte");
168 Parser.addAliasForDirective(Directive: ".hword", Alias: ".2byte");
169 Parser.addAliasForDirective(Directive: ".word", Alias: ".4byte");
170
171 MCAsmParserExtension::Initialize(Parser&: _Parser);
172
173 if (AddBuildAttributes)
174 getTargetStreamer().emitTargetAttributes(STI: *STI);
175 }
176
177 bool splitIdentifier(OperandVector &Operands);
178 bool parseOperand(OperandVector &Operands);
179 bool parseInstruction(OperandVector &Operands);
180 bool implicitExpressionLocation(OperandVector &Operands);
181 bool parseExpressionOrOperand(OperandVector &Operands);
182 bool parseExpression(MCExpr const *&Expr);
183
184 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
185 SMLoc NameLoc, OperandVector &Operands) override {
186 llvm_unreachable("Unimplemented");
187 }
188
189 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name, AsmToken ID,
190 OperandVector &Operands) override;
191
192 bool ParseDirective(AsmToken DirectiveID) override;
193};
194
195/// HexagonOperand - Instances of this class represent a parsed Hexagon machine
196/// instruction.
197struct HexagonOperand : public MCParsedAsmOperand {
198 enum KindTy { Token, Immediate, Register } Kind;
199 MCContext &Context;
200
201 SMLoc StartLoc, EndLoc;
202
203 struct TokTy {
204 const char *Data;
205 unsigned Length;
206 };
207
208 struct RegTy {
209 MCRegister RegNum;
210 };
211
212 struct ImmTy {
213 const MCExpr *Val;
214 };
215
216 union {
217 struct TokTy Tok;
218 struct RegTy Reg;
219 struct ImmTy Imm;
220 };
221
222 HexagonOperand(KindTy K, MCContext &Context) : Kind(K), Context(Context) {}
223
224public:
225 HexagonOperand(const HexagonOperand &o)
226 : MCParsedAsmOperand(), Context(o.Context) {
227 Kind = o.Kind;
228 StartLoc = o.StartLoc;
229 EndLoc = o.EndLoc;
230 switch (Kind) {
231 case Register:
232 Reg = o.Reg;
233 break;
234 case Immediate:
235 Imm = o.Imm;
236 break;
237 case Token:
238 Tok = o.Tok;
239 break;
240 }
241 }
242
243 /// getStartLoc - Get the location of the first token of this operand.
244 SMLoc getStartLoc() const override { return StartLoc; }
245
246 /// getEndLoc - Get the location of the last token of this operand.
247 SMLoc getEndLoc() const override { return EndLoc; }
248
249 MCRegister getReg() const override {
250 assert(Kind == Register && "Invalid access!");
251 return Reg.RegNum;
252 }
253
254 const MCExpr *getImm() const {
255 assert(Kind == Immediate && "Invalid access!");
256 return Imm.Val;
257 }
258
259 bool isToken() const override { return Kind == Token; }
260 bool isImm() const override { return Kind == Immediate; }
261 bool isMem() const override { llvm_unreachable("No isMem"); }
262 bool isReg() const override { return Kind == Register; }
263
264 bool CheckImmRange(int immBits, int zeroBits, bool isSigned,
265 bool isRelocatable, bool Extendable) const {
266 if (Kind == Immediate) {
267 const MCExpr *myMCExpr = &HexagonMCInstrInfo::getExpr(Expr: *getImm());
268 if (HexagonMCInstrInfo::mustExtend(Expr: *Imm.Val) && !Extendable)
269 return false;
270 int64_t Res;
271 if (myMCExpr->evaluateAsAbsolute(Res)) {
272 int bits = immBits + zeroBits;
273 // Field bit range is zerobits + bits
274 // zeroBits must be 0
275 if (Res & ((1 << zeroBits) - 1))
276 return false;
277 if (isSigned) {
278 if (Res < (1LL << (bits - 1)) && Res >= -(1LL << (bits - 1)))
279 return true;
280 } else {
281 if (bits == 64)
282 return true;
283 if (Res >= 0)
284 return ((uint64_t)Res < (uint64_t)(1ULL << bits));
285 else {
286 const int64_t high_bit_set = 1ULL << 63;
287 const uint64_t mask = (high_bit_set >> (63 - bits));
288 return (((uint64_t)Res & mask) == mask);
289 }
290 }
291 } else if (myMCExpr->getKind() == MCExpr::SymbolRef && isRelocatable)
292 return true;
293 else if (myMCExpr->getKind() == MCExpr::Binary ||
294 myMCExpr->getKind() == MCExpr::Unary)
295 return true;
296 }
297 return false;
298 }
299
300 bool isa30_2Imm() const { return CheckImmRange(immBits: 30, zeroBits: 2, isSigned: true, isRelocatable: true, Extendable: true); }
301 bool isb30_2Imm() const { return CheckImmRange(immBits: 30, zeroBits: 2, isSigned: true, isRelocatable: true, Extendable: true); }
302 bool isb15_2Imm() const { return CheckImmRange(immBits: 15, zeroBits: 2, isSigned: true, isRelocatable: true, Extendable: false); }
303 bool isb13_2Imm() const { return CheckImmRange(immBits: 13, zeroBits: 2, isSigned: true, isRelocatable: true, Extendable: false); }
304
305 bool ism32_0Imm() const { return true; }
306
307 bool isf32Imm() const { return false; }
308 bool isf64Imm() const { return false; }
309 bool iss32_0Imm() const { return true; }
310 bool iss31_1Imm() const { return true; }
311 bool iss30_2Imm() const { return true; }
312 bool iss29_3Imm() const { return true; }
313 bool iss27_2Imm() const { return CheckImmRange(immBits: 27, zeroBits: 2, isSigned: true, isRelocatable: true, Extendable: false); }
314 bool iss10_0Imm() const { return CheckImmRange(immBits: 10, zeroBits: 0, isSigned: true, isRelocatable: false, Extendable: false); }
315 bool iss10_6Imm() const { return CheckImmRange(immBits: 10, zeroBits: 6, isSigned: true, isRelocatable: false, Extendable: false); }
316 bool iss9_0Imm() const { return CheckImmRange(immBits: 9, zeroBits: 0, isSigned: true, isRelocatable: false, Extendable: false); }
317 bool iss8_0Imm() const { return CheckImmRange(immBits: 8, zeroBits: 0, isSigned: true, isRelocatable: false, Extendable: false); }
318 bool iss8_0Imm64() const { return CheckImmRange(immBits: 8, zeroBits: 0, isSigned: true, isRelocatable: true, Extendable: false); }
319 bool iss7_0Imm() const { return CheckImmRange(immBits: 7, zeroBits: 0, isSigned: true, isRelocatable: false, Extendable: false); }
320 bool iss6_0Imm() const { return CheckImmRange(immBits: 6, zeroBits: 0, isSigned: true, isRelocatable: false, Extendable: false); }
321 bool iss6_3Imm() const { return CheckImmRange(immBits: 6, zeroBits: 3, isSigned: true, isRelocatable: false, Extendable: false); }
322 bool iss4_0Imm() const { return CheckImmRange(immBits: 4, zeroBits: 0, isSigned: true, isRelocatable: false, Extendable: false); }
323 bool iss4_1Imm() const { return CheckImmRange(immBits: 4, zeroBits: 1, isSigned: true, isRelocatable: false, Extendable: false); }
324 bool iss4_2Imm() const { return CheckImmRange(immBits: 4, zeroBits: 2, isSigned: true, isRelocatable: false, Extendable: false); }
325 bool iss4_3Imm() const { return CheckImmRange(immBits: 4, zeroBits: 3, isSigned: true, isRelocatable: false, Extendable: false); }
326 bool iss3_0Imm() const { return CheckImmRange(immBits: 3, zeroBits: 0, isSigned: true, isRelocatable: false, Extendable: false); }
327
328 bool isu64_0Imm() const { return CheckImmRange(immBits: 64, zeroBits: 0, isSigned: false, isRelocatable: true, Extendable: true); }
329 bool isu32_0Imm() const { return true; }
330 bool isu31_1Imm() const { return true; }
331 bool isu30_2Imm() const { return true; }
332 bool isu29_3Imm() const { return true; }
333 bool isu26_6Imm() const { return CheckImmRange(immBits: 26, zeroBits: 6, isSigned: false, isRelocatable: true, Extendable: false); }
334 bool isu16_0Imm() const { return CheckImmRange(immBits: 16, zeroBits: 0, isSigned: false, isRelocatable: true, Extendable: false); }
335 bool isu16_1Imm() const { return CheckImmRange(immBits: 16, zeroBits: 1, isSigned: false, isRelocatable: true, Extendable: false); }
336 bool isu16_2Imm() const { return CheckImmRange(immBits: 16, zeroBits: 2, isSigned: false, isRelocatable: true, Extendable: false); }
337 bool isu16_3Imm() const { return CheckImmRange(immBits: 16, zeroBits: 3, isSigned: false, isRelocatable: true, Extendable: false); }
338 bool isu11_3Imm() const { return CheckImmRange(immBits: 11, zeroBits: 3, isSigned: false, isRelocatable: false, Extendable: false); }
339 bool isu10_0Imm() const { return CheckImmRange(immBits: 10, zeroBits: 0, isSigned: false, isRelocatable: false, Extendable: false); }
340 bool isu9_0Imm() const { return CheckImmRange(immBits: 9, zeroBits: 0, isSigned: false, isRelocatable: false, Extendable: false); }
341 bool isu8_0Imm() const { return CheckImmRange(immBits: 8, zeroBits: 0, isSigned: false, isRelocatable: false, Extendable: false); }
342 bool isu7_0Imm() const { return CheckImmRange(immBits: 7, zeroBits: 0, isSigned: false, isRelocatable: false, Extendable: false); }
343 bool isu6_0Imm() const { return CheckImmRange(immBits: 6, zeroBits: 0, isSigned: false, isRelocatable: false, Extendable: false); }
344 bool isu6_1Imm() const { return CheckImmRange(immBits: 6, zeroBits: 1, isSigned: false, isRelocatable: false, Extendable: false); }
345 bool isu6_2Imm() const { return CheckImmRange(immBits: 6, zeroBits: 2, isSigned: false, isRelocatable: false, Extendable: false); }
346 bool isu6_3Imm() const { return CheckImmRange(immBits: 6, zeroBits: 3, isSigned: false, isRelocatable: false, Extendable: false); }
347 bool isu5_0Imm() const { return CheckImmRange(immBits: 5, zeroBits: 0, isSigned: false, isRelocatable: false, Extendable: false); }
348 bool isu5_2Imm() const { return CheckImmRange(immBits: 5, zeroBits: 2, isSigned: false, isRelocatable: false, Extendable: false); }
349 bool isu5_3Imm() const { return CheckImmRange(immBits: 5, zeroBits: 3, isSigned: false, isRelocatable: false, Extendable: false); }
350 bool isu4_0Imm() const { return CheckImmRange(immBits: 4, zeroBits: 0, isSigned: false, isRelocatable: false, Extendable: false); }
351 bool isu4_2Imm() const { return CheckImmRange(immBits: 4, zeroBits: 2, isSigned: false, isRelocatable: false, Extendable: false); }
352 bool isu3_0Imm() const { return CheckImmRange(immBits: 3, zeroBits: 0, isSigned: false, isRelocatable: false, Extendable: false); }
353 bool isu3_1Imm() const { return CheckImmRange(immBits: 3, zeroBits: 1, isSigned: false, isRelocatable: false, Extendable: false); }
354 bool isu2_0Imm() const { return CheckImmRange(immBits: 2, zeroBits: 0, isSigned: false, isRelocatable: false, Extendable: false); }
355 bool isu1_0Imm() const { return CheckImmRange(immBits: 1, zeroBits: 0, isSigned: false, isRelocatable: false, Extendable: false); }
356
357 bool isn1Const() const {
358 if (!isImm())
359 return false;
360 int64_t Value;
361 if (!getImm()->evaluateAsAbsolute(Res&: Value))
362 return false;
363 return Value == -1;
364 }
365 bool issgp10Const() const {
366 if (!isReg())
367 return false;
368 return getReg() == Hexagon::SGP1_0;
369 }
370 bool iss11_0Imm() const {
371 return CheckImmRange(immBits: 11 + 26, zeroBits: 0, isSigned: true, isRelocatable: true, Extendable: true);
372 }
373 bool iss11_1Imm() const {
374 return CheckImmRange(immBits: 11 + 26, zeroBits: 1, isSigned: true, isRelocatable: true, Extendable: true);
375 }
376 bool iss11_2Imm() const {
377 return CheckImmRange(immBits: 11 + 26, zeroBits: 2, isSigned: true, isRelocatable: true, Extendable: true);
378 }
379 bool iss11_3Imm() const {
380 return CheckImmRange(immBits: 11 + 26, zeroBits: 3, isSigned: true, isRelocatable: true, Extendable: true);
381 }
382 bool isu32_0MustExt() const { return isImm(); }
383
384 void addRegOperands(MCInst &Inst, unsigned N) const {
385 assert(N == 1 && "Invalid number of operands!");
386 Inst.addOperand(Op: MCOperand::createReg(Reg: getReg()));
387 }
388
389 void addImmOperands(MCInst &Inst, unsigned N) const {
390 assert(N == 1 && "Invalid number of operands!");
391 Inst.addOperand(Op: MCOperand::createExpr(Val: getImm()));
392 }
393
394 void addSignedImmOperands(MCInst &Inst, unsigned N) const {
395 assert(N == 1 && "Invalid number of operands!");
396 HexagonMCExpr *Expr =
397 const_cast<HexagonMCExpr *>(cast<HexagonMCExpr>(Val: getImm()));
398 int64_t Value;
399 if (!Expr->evaluateAsAbsolute(Res&: Value)) {
400 Inst.addOperand(Op: MCOperand::createExpr(Val: Expr));
401 return;
402 }
403 int64_t Extended = SignExtend64(X: Value, B: 32);
404 HexagonMCExpr *NewExpr = HexagonMCExpr::create(
405 Expr: MCConstantExpr::create(Value: Extended, Ctx&: Context), Ctx&: Context);
406 if ((Extended < 0) != (Value < 0))
407 NewExpr->setSignMismatch();
408 NewExpr->setMustExtend(Expr->mustExtend());
409 NewExpr->setMustNotExtend(Expr->mustNotExtend());
410 Inst.addOperand(Op: MCOperand::createExpr(Val: NewExpr));
411 }
412
413 void addn1ConstOperands(MCInst &Inst, unsigned N) const {
414 addImmOperands(Inst, N);
415 }
416 void addsgp10ConstOperands(MCInst &Inst, unsigned N) const {
417 addRegOperands(Inst, N);
418 }
419
420 StringRef getToken() const {
421 assert(Kind == Token && "Invalid access!");
422 return StringRef(Tok.Data, Tok.Length);
423 }
424
425 void print(raw_ostream &OS, const MCAsmInfo &MAI) const override;
426
427 static std::unique_ptr<HexagonOperand> CreateToken(MCContext &Context,
428 StringRef Str, SMLoc S) {
429 HexagonOperand *Op = new HexagonOperand(Token, Context);
430 Op->Tok.Data = Str.data();
431 Op->Tok.Length = Str.size();
432 Op->StartLoc = S;
433 Op->EndLoc = S;
434 return std::unique_ptr<HexagonOperand>(Op);
435 }
436
437 static std::unique_ptr<HexagonOperand>
438 CreateReg(MCContext &Context, MCRegister Reg, SMLoc S, SMLoc E) {
439 HexagonOperand *Op = new HexagonOperand(Register, Context);
440 Op->Reg.RegNum = Reg;
441 Op->StartLoc = S;
442 Op->EndLoc = E;
443 return std::unique_ptr<HexagonOperand>(Op);
444 }
445
446 static std::unique_ptr<HexagonOperand>
447 CreateImm(MCContext &Context, const MCExpr *Val, SMLoc S, SMLoc E) {
448 HexagonOperand *Op = new HexagonOperand(Immediate, Context);
449 Op->Imm.Val = Val;
450 Op->StartLoc = S;
451 Op->EndLoc = E;
452 return std::unique_ptr<HexagonOperand>(Op);
453 }
454};
455
456} // end anonymous namespace
457
458void HexagonOperand::print(raw_ostream &OS, const MCAsmInfo &MAI) const {
459 switch (Kind) {
460 case Immediate:
461 MAI.printExpr(OS, *getImm());
462 break;
463 case Register:
464 OS << "<register R";
465 OS << getReg().id() << ">";
466 break;
467 case Token:
468 OS << "'" << getToken() << "'";
469 break;
470 }
471}
472
473bool HexagonAsmParser::finishBundle(SMLoc IDLoc, MCStreamer &Out) {
474 LLVM_DEBUG(dbgs() << "Bundle:");
475 LLVM_DEBUG(MCB.dump_pretty(dbgs()));
476 LLVM_DEBUG(dbgs() << "--\n");
477
478 MCB.setLoc(IDLoc);
479
480 // Check the bundle for errors.
481 const MCRegisterInfo *RI = getContext().getRegisterInfo();
482 MCSubtargetInfo const &STI = getSTI();
483
484 MCInst OrigBundle = MCB;
485 HexagonMCChecker Check(getContext(), MII, STI, MCB, *RI, true);
486
487 bool CheckOk = HexagonMCInstrInfo::canonicalizePacket(
488 MCII: MII, STI, Context&: getContext(), MCB, Checker: &Check, AttemptCompatibility: true);
489
490 if (CheckOk) {
491 if (HexagonMCInstrInfo::bundleSize(MCI: MCB) == 0) {
492 assert(!HexagonMCInstrInfo::isInnerLoop(MCB));
493 assert(!HexagonMCInstrInfo::isOuterLoop(MCB));
494 // Empty packets are valid yet aren't emitted
495 return false;
496 }
497
498 assert(HexagonMCInstrInfo::isBundle(MCB));
499
500 Out.emitInstruction(Inst: MCB, STI);
501 } else
502 return true; // Error
503
504 return false; // No error
505}
506
507bool HexagonAsmParser::matchBundleOptions() {
508 MCAsmParser &Parser = getParser();
509 while (true) {
510 if (!Parser.getTok().is(K: AsmToken::Colon))
511 return false;
512 Lex();
513 char const *MemNoShuffMsg =
514 "invalid instruction packet: mem_noshuf specifier not "
515 "supported with this architecture";
516 StringRef Option = Parser.getTok().getString();
517 auto IDLoc = Parser.getTok().getLoc();
518 if (Option.compare_insensitive(RHS: "endloop01") == 0) {
519 HexagonMCInstrInfo::setInnerLoop(MCB);
520 HexagonMCInstrInfo::setOuterLoop(MCB);
521 } else if (Option.compare_insensitive(RHS: "endloop0") == 0) {
522 HexagonMCInstrInfo::setInnerLoop(MCB);
523 } else if (Option.compare_insensitive(RHS: "endloop1") == 0) {
524 HexagonMCInstrInfo::setOuterLoop(MCB);
525 } else if (Option.compare_insensitive(RHS: "mem_noshuf") == 0) {
526 if (getSTI().hasFeature(Feature: Hexagon::FeatureMemNoShuf))
527 HexagonMCInstrInfo::setMemReorderDisabled(MCB);
528 else
529 return getParser().Error(L: IDLoc, Msg: MemNoShuffMsg);
530 } else if (Option.compare_insensitive(RHS: "mem_no_order") == 0) {
531 // Nothing.
532 } else
533 return getParser().Error(L: IDLoc, Msg: llvm::Twine("'") + Option +
534 "' is not a valid bundle option");
535 Lex();
536 }
537}
538
539// For instruction aliases, immediates are generated rather than
540// MCConstantExpr. Convert them for uniform MCExpr.
541// Also check for signed/unsigned mismatches and warn
542void HexagonAsmParser::canonicalizeImmediates(MCInst &MCI) {
543 MCInst NewInst;
544 NewInst.setOpcode(MCI.getOpcode());
545 for (MCOperand &I : MCI)
546 if (I.isImm()) {
547 int64_t Value(I.getImm());
548 NewInst.addOperand(Op: MCOperand::createExpr(Val: HexagonMCExpr::create(
549 Expr: MCConstantExpr::create(Value, Ctx&: getContext()), Ctx&: getContext())));
550 } else {
551 if (I.isExpr() && cast<HexagonMCExpr>(Val: I.getExpr())->signMismatch() &&
552 WarnSignedMismatch)
553 Warning(L: MCI.getLoc(), Msg: "Signed/Unsigned mismatch");
554 NewInst.addOperand(Op: I);
555 }
556 MCI = NewInst;
557}
558
559bool HexagonAsmParser::matchOneInstruction(MCInst &MCI, SMLoc IDLoc,
560 OperandVector &InstOperands,
561 uint64_t &ErrorInfo,
562 bool MatchingInlineAsm) {
563 // Perform matching with tablegen asmmatcher generated function
564 int result =
565 MatchInstructionImpl(Operands: InstOperands, Inst&: MCI, ErrorInfo, matchingInlineAsm: MatchingInlineAsm);
566 if (result == Match_Success) {
567 MCI.setLoc(IDLoc);
568 canonicalizeImmediates(MCI);
569 result = processInstruction(Inst&: MCI, Operands: InstOperands, IDLoc);
570
571 LLVM_DEBUG(dbgs() << "Insn:");
572 LLVM_DEBUG(MCI.dump_pretty(dbgs()));
573 LLVM_DEBUG(dbgs() << "\n\n");
574
575 MCI.setLoc(IDLoc);
576 }
577
578 // Create instruction operand for bundle instruction
579 // Break this into a separate function Code here is less readable
580 // Think about how to get an instruction error to report correctly.
581 // SMLoc will return the "{"
582 switch (result) {
583 default:
584 break;
585 case Match_Success:
586 return false;
587 case Match_MissingFeature:
588 return Error(L: IDLoc, Msg: "invalid instruction");
589 case Match_MnemonicFail:
590 return Error(L: IDLoc, Msg: "unrecognized instruction");
591 case Match_InvalidOperand:
592 [[fallthrough]];
593 case Match_InvalidTiedOperand:
594 SMLoc ErrorLoc = IDLoc;
595 if (ErrorInfo != ~0U) {
596 if (ErrorInfo >= InstOperands.size())
597 return Error(L: IDLoc, Msg: "too few operands for instruction");
598
599 ErrorLoc = (static_cast<HexagonOperand *>(InstOperands[ErrorInfo].get()))
600 ->getStartLoc();
601 if (ErrorLoc == SMLoc())
602 ErrorLoc = IDLoc;
603 }
604 return Error(L: ErrorLoc, Msg: "invalid operand for instruction");
605 }
606 llvm_unreachable("Implement any new match types added!");
607}
608
609void HexagonAsmParser::eatToEndOfPacket() {
610 assert(InBrackets);
611 AsmLexer &Lexer = getLexer();
612 while (!Lexer.is(K: AsmToken::RCurly))
613 Lexer.Lex();
614 Lexer.Lex();
615 InBrackets = false;
616}
617
618bool HexagonAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
619 OperandVector &Operands,
620 MCStreamer &Out,
621 uint64_t &ErrorInfo,
622 bool MatchingInlineAsm) {
623 if (!InBrackets) {
624 MCB.clear();
625 MCB.addOperand(Op: MCOperand::createImm(Val: 0));
626 }
627 HexagonOperand &FirstOperand = static_cast<HexagonOperand &>(*Operands[0]);
628 if (FirstOperand.isToken() && FirstOperand.getToken() == "{") {
629 assert(Operands.size() == 1 && "Brackets should be by themselves");
630 if (InBrackets) {
631 getParser().Error(L: IDLoc, Msg: "Already in a packet");
632 InBrackets = false;
633 return true;
634 }
635 InBrackets = true;
636 return false;
637 }
638 if (FirstOperand.isToken() && FirstOperand.getToken() == "}") {
639 assert(Operands.size() == 1 && "Brackets should be by themselves");
640 if (!InBrackets) {
641 getParser().Error(L: IDLoc, Msg: "Not in a packet");
642 return true;
643 }
644 InBrackets = false;
645 if (matchBundleOptions())
646 return true;
647 return finishBundle(IDLoc, Out);
648 }
649 MCInst *SubInst = getParser().getContext().createMCInst();
650 if (matchOneInstruction(MCI&: *SubInst, IDLoc, InstOperands&: Operands, ErrorInfo,
651 MatchingInlineAsm)) {
652 if (InBrackets)
653 eatToEndOfPacket();
654 return true;
655 }
656 HexagonMCInstrInfo::extendIfNeeded(
657 Context&: getParser().getContext(), MCII: MII, MCB, MCI: *SubInst);
658 MCB.addOperand(Op: MCOperand::createInst(Val: SubInst));
659 if (!InBrackets)
660 return finishBundle(IDLoc, Out);
661 return false;
662}
663/// parseDirectiveAttribute
664/// ::= .attribute int, int
665/// ::= .attribute Tag_name, int
666bool HexagonAsmParser::parseDirectiveAttribute(SMLoc L) {
667 MCAsmParser &Parser = getParser();
668 int64_t Tag;
669 SMLoc TagLoc = Parser.getTok().getLoc();
670 if (Parser.getTok().is(K: AsmToken::Identifier)) {
671 StringRef Name = Parser.getTok().getIdentifier();
672 std::optional<unsigned> Ret = ELFAttrs::attrTypeFromString(
673 tag: Name, tagNameMap: HexagonAttrs::getHexagonAttributeTags());
674 if (!Ret)
675 return Error(L: TagLoc, Msg: "attribute name not recognized: " + Name);
676 Tag = *Ret;
677 Parser.Lex();
678 } else {
679 const MCExpr *AttrExpr;
680
681 TagLoc = Parser.getTok().getLoc();
682 if (Parser.parseExpression(Res&: AttrExpr))
683 return true;
684
685 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: AttrExpr);
686 if (check(P: !CE, Loc: TagLoc, Msg: "expected numeric constant"))
687 return true;
688
689 Tag = CE->getValue();
690 }
691
692 if (Parser.parseComma())
693 return true;
694
695 // We currently only have integer values.
696 int64_t IntegerValue = 0;
697 SMLoc ValueExprLoc = Parser.getTok().getLoc();
698 const MCExpr *ValueExpr;
699 if (Parser.parseExpression(Res&: ValueExpr))
700 return true;
701
702 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: ValueExpr);
703 if (!CE)
704 return Error(L: ValueExprLoc, Msg: "expected numeric constant");
705 IntegerValue = CE->getValue();
706
707 if (Parser.parseEOL())
708 return true;
709
710 getTargetStreamer().emitAttribute(Attribute: Tag, Value: IntegerValue);
711 return false;
712}
713
714/// ParseDirective parses the Hexagon specific directives
715bool HexagonAsmParser::ParseDirective(AsmToken DirectiveID) {
716 StringRef IDVal = DirectiveID.getIdentifier();
717 if (IDVal.lower() == ".falign")
718 return ParseDirectiveFalign(Size: 256, L: DirectiveID.getLoc());
719 if ((IDVal.lower() == ".lcomm") || (IDVal.lower() == ".lcommon"))
720 return ParseDirectiveComm(IsLocal: true, L: DirectiveID.getLoc());
721 if ((IDVal.lower() == ".comm") || (IDVal.lower() == ".common"))
722 return ParseDirectiveComm(IsLocal: false, L: DirectiveID.getLoc());
723 if (IDVal.lower() == ".subsection")
724 return ParseDirectiveSubsection(L: DirectiveID.getLoc());
725 if (IDVal == ".attribute")
726 return parseDirectiveAttribute(L: DirectiveID.getLoc());
727
728 return true;
729}
730bool HexagonAsmParser::ParseDirectiveSubsection(SMLoc L) {
731 const MCExpr *Subsection = nullptr;
732 int64_t Res;
733
734 assert((getLexer().isNot(AsmToken::EndOfStatement)) &&
735 "Invalid subsection directive");
736 getParser().parseExpression(Res&: Subsection);
737
738 if (!Subsection->evaluateAsAbsolute(Res))
739 return Error(L, Msg: "Cannot evaluate subsection number");
740
741 if (getLexer().isNot(K: AsmToken::EndOfStatement))
742 return TokError(Msg: "unexpected token in directive");
743
744 // 0-8192 is the hard-coded range in MCObjectStreamper.cpp, this keeps the
745 // negative subsections together and in the same order but at the opposite
746 // end of the section. Only legacy hexagon-gcc created assembly code
747 // used negative subsections.
748 if ((Res < 0) && (Res > -8193))
749 Res += 8192;
750 getStreamer().switchSection(Section: getStreamer().getCurrentSectionOnly(), Subsec: Res);
751 return false;
752}
753
754/// ::= .falign [expression]
755bool HexagonAsmParser::ParseDirectiveFalign(unsigned Size, SMLoc L) {
756
757 int64_t MaxBytesToFill = 15;
758
759 // if there is an argument
760 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
761 const MCExpr *Value;
762 SMLoc ExprLoc = L;
763
764 // Make sure we have a number (false is returned if expression is a number)
765 if (!getParser().parseExpression(Res&: Value)) {
766 // Make sure this is a number that is in range
767 auto *MCE = cast<MCConstantExpr>(Val: Value);
768 uint64_t IntValue = MCE->getValue();
769 if (!isUIntN(N: Size, x: IntValue) && !isIntN(N: Size, x: IntValue))
770 return Error(L: ExprLoc, Msg: "literal value out of range (256) for falign");
771 MaxBytesToFill = IntValue;
772 Lex();
773 } else {
774 return Error(L: ExprLoc, Msg: "not a valid expression for falign directive");
775 }
776 }
777
778 getTargetStreamer().emitFAlign(Size: 16, MaxBytesToEmit: MaxBytesToFill);
779 Lex();
780
781 return false;
782}
783
784// This is largely a copy of AsmParser's ParseDirectiveComm extended to
785// accept a 3rd argument, AccessAlignment which indicates the smallest
786// memory access made to the symbol, expressed in bytes. If no
787// AccessAlignment is specified it defaults to the Alignment Value.
788// Hexagon's .lcomm:
789// .lcomm Symbol, Length, Alignment, AccessAlignment
790bool HexagonAsmParser::ParseDirectiveComm(bool IsLocal, SMLoc Loc) {
791 // FIXME: need better way to detect if AsmStreamer (upstream removed
792 // getKind())
793 if (getStreamer().hasRawTextSupport())
794 return true; // Only object file output requires special treatment.
795
796 StringRef Name;
797 if (getParser().parseIdentifier(Res&: Name))
798 return TokError(Msg: "expected identifier in directive");
799 // Handle the identifier as the key symbol.
800 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
801
802 if (getLexer().isNot(K: AsmToken::Comma))
803 return TokError(Msg: "unexpected token in directive");
804 Lex();
805
806 int64_t Size;
807 SMLoc SizeLoc = getLexer().getLoc();
808 if (getParser().parseAbsoluteExpression(Res&: Size))
809 return true;
810
811 int64_t ByteAlignment = 1;
812 SMLoc ByteAlignmentLoc;
813 if (getLexer().is(K: AsmToken::Comma)) {
814 Lex();
815 ByteAlignmentLoc = getLexer().getLoc();
816 if (getParser().parseAbsoluteExpression(Res&: ByteAlignment))
817 return true;
818 if (!isPowerOf2_64(Value: ByteAlignment))
819 return Error(L: ByteAlignmentLoc, Msg: "alignment must be a power of 2");
820 }
821
822 int64_t AccessAlignment = 0;
823 if (getLexer().is(K: AsmToken::Comma)) {
824 // The optional access argument specifies the size of the smallest memory
825 // access to be made to the symbol, expressed in bytes.
826 SMLoc AccessAlignmentLoc;
827 Lex();
828 AccessAlignmentLoc = getLexer().getLoc();
829 if (getParser().parseAbsoluteExpression(Res&: AccessAlignment))
830 return true;
831
832 if (!isPowerOf2_64(Value: AccessAlignment))
833 return Error(L: AccessAlignmentLoc, Msg: "access alignment must be a power of 2");
834 }
835
836 if (getLexer().isNot(K: AsmToken::EndOfStatement))
837 return TokError(Msg: "unexpected token in '.comm' or '.lcomm' directive");
838
839 Lex();
840
841 // NOTE: a size of zero for a .comm should create a undefined symbol
842 // but a size of .lcomm creates a bss symbol of size zero.
843 if (Size < 0)
844 return Error(L: SizeLoc, Msg: "invalid '.comm' or '.lcomm' directive size, can't "
845 "be less than zero");
846
847 // NOTE: The alignment in the directive is a power of 2 value, the assembler
848 // may internally end up wanting an alignment in bytes.
849 // FIXME: Diagnose overflow.
850 if (ByteAlignment < 0)
851 return Error(L: ByteAlignmentLoc, Msg: "invalid '.comm' or '.lcomm' directive "
852 "alignment, can't be less than zero");
853
854 if (!Sym->isUndefined())
855 return Error(L: Loc, Msg: "invalid symbol redefinition");
856
857 HexagonMCELFStreamer &HexagonELFStreamer =
858 static_cast<HexagonMCELFStreamer &>(getStreamer());
859 if (IsLocal) {
860 HexagonELFStreamer.HexagonMCEmitLocalCommonSymbol(
861 Symbol: Sym, Size, ByteAlignment: Align(ByteAlignment), AccessSize: AccessAlignment);
862 return false;
863 }
864
865 HexagonELFStreamer.HexagonMCEmitCommonSymbol(Symbol: Sym, Size, ByteAlignment: Align(ByteAlignment),
866 AccessSize: AccessAlignment);
867 return false;
868}
869
870// validate register against architecture
871bool HexagonAsmParser::RegisterMatchesArch(MCRegister MatchNum) const {
872 if (HexagonMCRegisterClasses[Hexagon::V62RegsRegClassID].contains(Reg: MatchNum))
873 if (!getSTI().hasFeature(Feature: Hexagon::ArchV62))
874 return false;
875 return true;
876}
877
878// extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeHexagonAsmLexer();
879
880/// Force static initialization.
881extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
882LLVMInitializeHexagonAsmParser() {
883 RegisterMCAsmParser<HexagonAsmParser> X(getTheHexagonTarget());
884}
885
886#define GET_MATCHER_IMPLEMENTATION
887#define GET_REGISTER_MATCHER
888#include "HexagonGenAsmMatcher.inc"
889
890static bool previousEqual(OperandVector &Operands, size_t Index,
891 StringRef String) {
892 if (Index >= Operands.size())
893 return false;
894 MCParsedAsmOperand &Operand = *Operands[Operands.size() - Index - 1];
895 if (!Operand.isToken())
896 return false;
897 return static_cast<HexagonOperand &>(Operand).getToken().equals_insensitive(
898 RHS: String);
899}
900
901static bool previousIsLoop(OperandVector &Operands, size_t Index) {
902 return previousEqual(Operands, Index, String: "loop0") ||
903 previousEqual(Operands, Index, String: "loop1") ||
904 previousEqual(Operands, Index, String: "sp1loop0") ||
905 previousEqual(Operands, Index, String: "sp2loop0") ||
906 previousEqual(Operands, Index, String: "sp3loop0");
907}
908
909bool HexagonAsmParser::splitIdentifier(OperandVector &Operands) {
910 AsmToken const &Token = getParser().getTok();
911 StringRef String = Token.getString();
912 SMLoc Loc = Token.getLoc();
913 Lex();
914 do {
915 std::pair<StringRef, StringRef> HeadTail = String.split(Separator: '.');
916 if (!HeadTail.first.empty())
917 Operands.push_back(
918 Elt: HexagonOperand::CreateToken(Context&: getContext(), Str: HeadTail.first, S: Loc));
919 if (!HeadTail.second.empty())
920 Operands.push_back(Elt: HexagonOperand::CreateToken(
921 Context&: getContext(), Str: String.substr(Start: HeadTail.first.size(), N: 1), S: Loc));
922 String = HeadTail.second;
923 } while (!String.empty());
924 return false;
925}
926
927bool HexagonAsmParser::parseOperand(OperandVector &Operands) {
928 MCRegister Register;
929 SMLoc Begin;
930 SMLoc End;
931 AsmLexer &Lexer = getLexer();
932 if (!parseRegister(Reg&: Register, StartLoc&: Begin, EndLoc&: End)) {
933 if (!ErrorMissingParenthesis)
934 switch (Register.id()) {
935 default:
936 break;
937 case Hexagon::P0:
938 case Hexagon::P1:
939 case Hexagon::P2:
940 case Hexagon::P3:
941 if (previousEqual(Operands, Index: 0, String: "if")) {
942 if (WarnMissingParenthesis)
943 Warning(L: Begin, Msg: "Missing parenthesis around predicate register");
944 static char const *LParen = "(";
945 static char const *RParen = ")";
946 Operands.push_back(
947 Elt: HexagonOperand::CreateToken(Context&: getContext(), Str: LParen, S: Begin));
948 Operands.push_back(
949 Elt: HexagonOperand::CreateReg(Context&: getContext(), Reg: Register, S: Begin, E: End));
950 const AsmToken &MaybeDotNew = Lexer.getTok();
951 if (MaybeDotNew.is(K: AsmToken::TokenKind::Identifier) &&
952 MaybeDotNew.getString().equals_insensitive(RHS: ".new"))
953 splitIdentifier(Operands);
954 Operands.push_back(
955 Elt: HexagonOperand::CreateToken(Context&: getContext(), Str: RParen, S: Begin));
956 return false;
957 }
958 if (previousEqual(Operands, Index: 0, String: "!") &&
959 previousEqual(Operands, Index: 1, String: "if")) {
960 if (WarnMissingParenthesis)
961 Warning(L: Begin, Msg: "Missing parenthesis around predicate register");
962 static char const *LParen = "(";
963 static char const *RParen = ")";
964 Operands.insert(I: Operands.end() - 1, Elt: HexagonOperand::CreateToken(
965 Context&: getContext(), Str: LParen, S: Begin));
966 Operands.push_back(
967 Elt: HexagonOperand::CreateReg(Context&: getContext(), Reg: Register, S: Begin, E: End));
968 const AsmToken &MaybeDotNew = Lexer.getTok();
969 if (MaybeDotNew.is(K: AsmToken::TokenKind::Identifier) &&
970 MaybeDotNew.getString().equals_insensitive(RHS: ".new"))
971 splitIdentifier(Operands);
972 Operands.push_back(
973 Elt: HexagonOperand::CreateToken(Context&: getContext(), Str: RParen, S: Begin));
974 return false;
975 }
976 break;
977 }
978 Operands.push_back(
979 Elt: HexagonOperand::CreateReg(Context&: getContext(), Reg: Register, S: Begin, E: End));
980 return false;
981 }
982 return splitIdentifier(Operands);
983}
984
985bool HexagonAsmParser::isLabel(AsmToken &Token) {
986 AsmLexer &Lexer = getLexer();
987 AsmToken const &Second = Lexer.getTok();
988 AsmToken Third = Lexer.peekTok();
989 StringRef String = Token.getString();
990 if (Token.is(K: AsmToken::TokenKind::LCurly) ||
991 Token.is(K: AsmToken::TokenKind::RCurly))
992 return false;
993 // special case for parsing vwhist256:sat
994 if (String.lower() == "vwhist256" && Second.is(K: AsmToken::Colon) &&
995 Third.getString().lower() == "sat")
996 return false;
997 if (!Token.is(K: AsmToken::TokenKind::Identifier))
998 return true;
999 if (!matchRegister(Name: String.lower()))
1000 return true;
1001 assert(Second.is(AsmToken::Colon));
1002 StringRef Raw(String.data(), Third.getString().data() - String.data() +
1003 Third.getString().size());
1004 std::string Collapsed = std::string(Raw);
1005 llvm::erase_if(C&: Collapsed, P: isSpace);
1006 StringRef Whole = Collapsed;
1007 std::pair<StringRef, StringRef> DotSplit = Whole.split(Separator: '.');
1008 if (!matchRegister(Name: DotSplit.first.lower()))
1009 return true;
1010 return false;
1011}
1012
1013bool HexagonAsmParser::tokenIsStartOfStatement(AsmToken::TokenKind Token) {
1014 return Token == AsmToken::LCurly || Token == AsmToken::RCurly;
1015}
1016
1017bool HexagonAsmParser::handleNoncontigiousRegister(bool Contigious,
1018 SMLoc &Loc) {
1019 if (!Contigious && ErrorNoncontigiousRegister) {
1020 Error(L: Loc, Msg: "Register name is not contigious");
1021 return true;
1022 }
1023 if (!Contigious && WarnNoncontigiousRegister)
1024 Warning(L: Loc, Msg: "Register name is not contigious");
1025 return false;
1026}
1027
1028bool HexagonAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
1029 SMLoc &EndLoc) {
1030 return !tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
1031}
1032
1033ParseStatus HexagonAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1034 SMLoc &EndLoc) {
1035 AsmLexer &Lexer = getLexer();
1036 StartLoc = getLexer().getLoc();
1037 SmallVector<AsmToken, 5> Lookahead;
1038 StringRef RawString(Lexer.getTok().getString().data(), 0);
1039 bool Again = Lexer.is(K: AsmToken::Identifier);
1040 bool NeededWorkaround = false;
1041 while (Again) {
1042 AsmToken const &Token = Lexer.getTok();
1043 RawString = StringRef(RawString.data(), Token.getString().data() -
1044 RawString.data() +
1045 Token.getString().size());
1046 Lookahead.push_back(Elt: Token);
1047 Lexer.Lex();
1048 bool Contigious = Lexer.getTok().getString().data() ==
1049 Lookahead.back().getString().data() +
1050 Lookahead.back().getString().size();
1051 bool Type = Lexer.is(K: AsmToken::Identifier) || Lexer.is(K: AsmToken::Dot) ||
1052 Lexer.is(K: AsmToken::Integer) || Lexer.is(K: AsmToken::Real) ||
1053 Lexer.is(K: AsmToken::Colon);
1054 bool Workaround =
1055 Lexer.is(K: AsmToken::Colon) || Lookahead.back().is(K: AsmToken::Colon);
1056 Again = (Contigious && Type) || (Workaround && Type);
1057 NeededWorkaround = NeededWorkaround || (Again && !(Contigious && Type));
1058 }
1059 std::string Collapsed = std::string(RawString);
1060 llvm::erase_if(C&: Collapsed, P: isSpace);
1061 StringRef FullString = Collapsed;
1062 std::pair<StringRef, StringRef> DotSplit = FullString.split(Separator: '.');
1063 MCRegister DotReg = matchRegister(Name: DotSplit.first.lower());
1064 if (DotReg && RegisterMatchesArch(MatchNum: DotReg)) {
1065 if (DotSplit.second.empty()) {
1066 Reg = DotReg;
1067 EndLoc = Lexer.getLoc();
1068 if (handleNoncontigiousRegister(Contigious: !NeededWorkaround, Loc&: StartLoc))
1069 return ParseStatus::NoMatch;
1070 return ParseStatus::Success;
1071 } else {
1072 Reg = DotReg;
1073 size_t First = RawString.find(C: '.');
1074 StringRef DotString (RawString.data() + First, RawString.size() - First);
1075 Lexer.UnLex(Token: AsmToken(AsmToken::Identifier, DotString));
1076 EndLoc = Lexer.getLoc();
1077 if (handleNoncontigiousRegister(Contigious: !NeededWorkaround, Loc&: StartLoc))
1078 return ParseStatus::NoMatch;
1079 return ParseStatus::Success;
1080 }
1081 }
1082 std::pair<StringRef, StringRef> ColonSplit = StringRef(FullString).split(Separator: ':');
1083 MCRegister ColonReg = matchRegister(Name: ColonSplit.first.lower());
1084 if (ColonReg && RegisterMatchesArch(MatchNum: DotReg)) {
1085 do {
1086 Lexer.UnLex(Token: Lookahead.pop_back_val());
1087 } while (!Lookahead.empty() && !Lexer.is(K: AsmToken::Colon));
1088 Reg = ColonReg;
1089 EndLoc = Lexer.getLoc();
1090 if (handleNoncontigiousRegister(Contigious: !NeededWorkaround, Loc&: StartLoc))
1091 return ParseStatus::NoMatch;
1092 return ParseStatus::Success;
1093 }
1094 while (!Lookahead.empty()) {
1095 Lexer.UnLex(Token: Lookahead.pop_back_val());
1096 }
1097 return ParseStatus::NoMatch;
1098}
1099
1100bool HexagonAsmParser::implicitExpressionLocation(OperandVector &Operands) {
1101 if (previousEqual(Operands, Index: 0, String: "call"))
1102 return true;
1103 if (previousEqual(Operands, Index: 0, String: "jump"))
1104 if (!getLexer().getTok().is(K: AsmToken::Colon))
1105 return true;
1106 if (previousEqual(Operands, Index: 0, String: "(") && previousIsLoop(Operands, Index: 1))
1107 return true;
1108 if (previousEqual(Operands, Index: 1, String: ":") && previousEqual(Operands, Index: 2, String: "jump") &&
1109 (previousEqual(Operands, Index: 0, String: "nt") || previousEqual(Operands, Index: 0, String: "t")))
1110 return true;
1111 return false;
1112}
1113
1114bool HexagonAsmParser::parseExpression(MCExpr const *&Expr) {
1115 SmallVector<AsmToken, 4> Tokens;
1116 AsmLexer &Lexer = getLexer();
1117 bool Done = false;
1118 static char const *Comma = ",";
1119 do {
1120 Tokens.emplace_back(Args: Lexer.getTok());
1121 Lex();
1122 switch (Tokens.back().getKind()) {
1123 case AsmToken::TokenKind::Hash:
1124 if (Tokens.size() > 1)
1125 if ((Tokens.end() - 2)->getKind() == AsmToken::TokenKind::Plus) {
1126 Tokens.insert(I: Tokens.end() - 2,
1127 Elt: AsmToken(AsmToken::TokenKind::Comma, Comma));
1128 Done = true;
1129 }
1130 break;
1131 case AsmToken::TokenKind::RCurly:
1132 case AsmToken::TokenKind::EndOfStatement:
1133 case AsmToken::TokenKind::Eof:
1134 Done = true;
1135 break;
1136 default:
1137 break;
1138 }
1139 } while (!Done);
1140 while (!Tokens.empty()) {
1141 Lexer.UnLex(Token: Tokens.back());
1142 Tokens.pop_back();
1143 }
1144 SMLoc Loc = Lexer.getLoc();
1145 return getParser().parseExpression(Res&: Expr, EndLoc&: Loc);
1146}
1147
1148bool HexagonAsmParser::parseExpressionOrOperand(OperandVector &Operands) {
1149 if (implicitExpressionLocation(Operands)) {
1150 MCAsmParser &Parser = getParser();
1151 SMLoc Loc = Parser.getLexer().getLoc();
1152 MCExpr const *Expr = nullptr;
1153 bool Error = parseExpression(Expr);
1154 Expr = HexagonMCExpr::create(Expr, Ctx&: getContext());
1155 if (!Error)
1156 Operands.push_back(
1157 Elt: HexagonOperand::CreateImm(Context&: getContext(), Val: Expr, S: Loc, E: Loc));
1158 return Error;
1159 }
1160 return parseOperand(Operands);
1161}
1162
1163/// Parse an instruction.
1164bool HexagonAsmParser::parseInstruction(OperandVector &Operands) {
1165 MCAsmParser &Parser = getParser();
1166 AsmLexer &Lexer = getLexer();
1167 while (true) {
1168 AsmToken const &Token = Parser.getTok();
1169 switch (Token.getKind()) {
1170 case AsmToken::Eof:
1171 case AsmToken::EndOfStatement: {
1172 Lex();
1173 return false;
1174 }
1175 case AsmToken::LCurly: {
1176 if (!Operands.empty())
1177 return true;
1178 Operands.push_back(Elt: HexagonOperand::CreateToken(
1179 Context&: getContext(), Str: Token.getString(), S: Token.getLoc()));
1180 Lex();
1181 return false;
1182 }
1183 case AsmToken::RCurly: {
1184 if (Operands.empty()) {
1185 Operands.push_back(Elt: HexagonOperand::CreateToken(
1186 Context&: getContext(), Str: Token.getString(), S: Token.getLoc()));
1187 Lex();
1188 }
1189 return false;
1190 }
1191 case AsmToken::Comma: {
1192 Lex();
1193 continue;
1194 }
1195 case AsmToken::EqualEqual:
1196 case AsmToken::ExclaimEqual:
1197 case AsmToken::GreaterEqual:
1198 case AsmToken::GreaterGreater:
1199 case AsmToken::LessEqual:
1200 case AsmToken::LessLess: {
1201 Operands.push_back(Elt: HexagonOperand::CreateToken(
1202 Context&: getContext(), Str: Token.getString().substr(Start: 0, N: 1), S: Token.getLoc()));
1203 Operands.push_back(Elt: HexagonOperand::CreateToken(
1204 Context&: getContext(), Str: Token.getString().substr(Start: 1, N: 1), S: Token.getLoc()));
1205 Lex();
1206 continue;
1207 }
1208 case AsmToken::Hash: {
1209 bool MustNotExtend = false;
1210 bool ImplicitExpression = implicitExpressionLocation(Operands);
1211 SMLoc ExprLoc = Lexer.getLoc();
1212 if (!ImplicitExpression)
1213 Operands.push_back(Elt: HexagonOperand::CreateToken(
1214 Context&: getContext(), Str: Token.getString(), S: Token.getLoc()));
1215 Lex();
1216 bool MustExtend = false;
1217 bool HiOnly = false;
1218 bool LoOnly = false;
1219 if (Lexer.is(K: AsmToken::Hash)) {
1220 Lex();
1221 MustExtend = true;
1222 } else if (ImplicitExpression)
1223 MustNotExtend = true;
1224 AsmToken const &Token = Parser.getTok();
1225 if (Token.is(K: AsmToken::Identifier)) {
1226 StringRef String = Token.getString();
1227 if (String.lower() == "hi") {
1228 HiOnly = true;
1229 } else if (String.lower() == "lo") {
1230 LoOnly = true;
1231 }
1232 if (HiOnly || LoOnly) {
1233 AsmToken LParen = Lexer.peekTok();
1234 if (!LParen.is(K: AsmToken::LParen)) {
1235 HiOnly = false;
1236 LoOnly = false;
1237 } else {
1238 Lex();
1239 }
1240 }
1241 }
1242 MCExpr const *Expr = nullptr;
1243 if (parseExpression(Expr))
1244 return true;
1245 int64_t Value;
1246 MCContext &Context = Parser.getContext();
1247 assert(Expr != nullptr);
1248 if (Expr->evaluateAsAbsolute(Res&: Value)) {
1249 if (HiOnly)
1250 Expr = MCBinaryExpr::createLShr(
1251 LHS: Expr, RHS: MCConstantExpr::create(Value: 16, Ctx&: Context), Ctx&: Context);
1252 if (HiOnly || LoOnly)
1253 Expr = MCBinaryExpr::createAnd(
1254 LHS: Expr, RHS: MCConstantExpr::create(Value: 0xffff, Ctx&: Context), Ctx&: Context);
1255 } else {
1256 MCValue Value;
1257 if (Expr->evaluateAsRelocatable(Res&: Value, Asm: nullptr)) {
1258 if (!Value.isAbsolute()) {
1259 switch (HexagonMCExpr::VariantKind(Value.getSpecifier())) {
1260 case HexagonMCExpr::VK_TPREL:
1261 case HexagonMCExpr::VK_DTPREL:
1262 // Don't lazy extend these expression variants
1263 MustNotExtend = !MustExtend;
1264 break;
1265 default:
1266 break;
1267 }
1268 }
1269 }
1270 }
1271 Expr = HexagonMCExpr::create(Expr, Ctx&: Context);
1272 HexagonMCInstrInfo::setMustNotExtend(Expr: *Expr, Val: MustNotExtend);
1273 HexagonMCInstrInfo::setMustExtend(Expr: *Expr, Val: MustExtend);
1274 std::unique_ptr<HexagonOperand> Operand =
1275 HexagonOperand::CreateImm(Context&: getContext(), Val: Expr, S: ExprLoc, E: ExprLoc);
1276 Operands.push_back(Elt: std::move(Operand));
1277 continue;
1278 }
1279 default:
1280 break;
1281 }
1282 if (parseExpressionOrOperand(Operands))
1283 return true;
1284 }
1285}
1286
1287bool HexagonAsmParser::parseInstruction(ParseInstructionInfo &Info,
1288 StringRef Name, AsmToken ID,
1289 OperandVector &Operands) {
1290 getLexer().UnLex(Token: ID);
1291 return parseInstruction(Operands);
1292}
1293
1294static MCInst makeCombineInst(int opCode, MCOperand &Rdd, MCOperand &MO1,
1295 MCOperand &MO2) {
1296 MCInst TmpInst;
1297 TmpInst.setOpcode(opCode);
1298 TmpInst.addOperand(Op: Rdd);
1299 TmpInst.addOperand(Op: MO1);
1300 TmpInst.addOperand(Op: MO2);
1301
1302 return TmpInst;
1303}
1304
1305// Define this matcher function after the auto-generated include so we
1306// have the match class enum definitions.
1307unsigned HexagonAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
1308 unsigned Kind) {
1309 HexagonOperand *Op = static_cast<HexagonOperand *>(&AsmOp);
1310
1311 switch (Kind) {
1312 case MCK_0: {
1313 int64_t Value;
1314 return Op->isImm() && Op->Imm.Val->evaluateAsAbsolute(Res&: Value) && Value == 0
1315 ? Match_Success
1316 : Match_InvalidOperand;
1317 }
1318 case MCK_1: {
1319 int64_t Value;
1320 return Op->isImm() && Op->Imm.Val->evaluateAsAbsolute(Res&: Value) && Value == 1
1321 ? Match_Success
1322 : Match_InvalidOperand;
1323 }
1324 }
1325 if (Op->Kind == HexagonOperand::Token && Kind != InvalidMatchClass) {
1326 StringRef myStringRef = StringRef(Op->Tok.Data, Op->Tok.Length);
1327 if (matchTokenString(Name: myStringRef.lower()) == (MatchClassKind)Kind)
1328 return Match_Success;
1329 if (matchTokenString(Name: myStringRef.upper()) == (MatchClassKind)Kind)
1330 return Match_Success;
1331 }
1332
1333 LLVM_DEBUG(dbgs() << "Unmatched Operand:");
1334 LLVM_DEBUG(Op->dump());
1335 LLVM_DEBUG(dbgs() << "\n");
1336
1337 return Match_InvalidOperand;
1338}
1339
1340// FIXME: Calls to OutOfRange should propagate failure up to parseStatement.
1341bool HexagonAsmParser::OutOfRange(SMLoc IDLoc, long long Val, long long Max) {
1342 std::string errStr;
1343 raw_string_ostream ES(errStr);
1344 ES << "value " << Val << "(" << format_hex(N: Val, Width: 0) << ") out of range: ";
1345 if (Max >= 0)
1346 ES << "0-" << Max;
1347 else
1348 ES << Max << "-" << (-Max - 1);
1349 return Parser.printError(L: IDLoc, Msg: ES.str());
1350}
1351
1352int HexagonAsmParser::processInstruction(MCInst &Inst,
1353 OperandVector const &Operands,
1354 SMLoc IDLoc) {
1355 MCContext &Context = getParser().getContext();
1356 const MCRegisterInfo *RI = getContext().getRegisterInfo();
1357 const std::string r = "r";
1358 const std::string Colon = ":";
1359 using RegPairVals = std::pair<unsigned, unsigned>;
1360 auto GetRegPair = [this, r](RegPairVals RegPair) {
1361 const std::string R1 = r + utostr(X: RegPair.first);
1362 const std::string R2 = r + utostr(X: RegPair.second);
1363
1364 return std::make_pair(x: matchRegister(Name: R1), y: matchRegister(Name: R2));
1365 };
1366 auto GetScalarRegs = [RI, GetRegPair](MCRegister RegPair) {
1367 const unsigned Lower = RI->getEncodingValue(Reg: RegPair);
1368 const RegPairVals RegPair_ = std::make_pair(x: Lower + 1, y: Lower);
1369
1370 return GetRegPair(RegPair_);
1371 };
1372 auto GetVecRegs = [GetRegPair](MCRegister VecRegPair) {
1373 const RegPairVals RegPair =
1374 HexagonMCInstrInfo::GetVecRegPairIndices(VecRegPair);
1375
1376 return GetRegPair(RegPair);
1377 };
1378
1379 bool is32bit = false; // used to distinguish between CONST32 and CONST64
1380 switch (Inst.getOpcode()) {
1381 default:
1382 if (HexagonMCInstrInfo::getDesc(MCII: MII, MCI: Inst).isPseudo()) {
1383 SMDiagnostic Diag = getSourceManager().GetMessage(
1384 Loc: IDLoc, Kind: SourceMgr::DK_Error,
1385 Msg: "Found pseudo instruction with no expansion");
1386 Diag.print(ProgName: "", S&: errs());
1387 report_fatal_error(reason: "Invalid pseudo instruction");
1388 }
1389 break;
1390
1391 case Hexagon::J2_trap1:
1392 if (!getSTI().hasFeature(Feature: Hexagon::ArchV65)) {
1393 MCOperand &Rx = Inst.getOperand(i: 0);
1394 MCOperand &Ry = Inst.getOperand(i: 1);
1395 if (Rx.getReg() != Hexagon::R0 || Ry.getReg() != Hexagon::R0) {
1396 Error(L: IDLoc, Msg: "trap1 can only have register r0 as operand");
1397 return Match_InvalidOperand;
1398 }
1399 }
1400 break;
1401
1402 case Hexagon::A2_iconst: {
1403 Inst.setOpcode(Hexagon::A2_addi);
1404 MCOperand Reg = Inst.getOperand(i: 0);
1405 MCOperand S27 = Inst.getOperand(i: 1);
1406 HexagonMCInstrInfo::setMustNotExtend(Expr: *S27.getExpr());
1407 HexagonMCInstrInfo::setS27_2_reloc(Expr: *S27.getExpr());
1408 Inst.clear();
1409 Inst.addOperand(Op: Reg);
1410 Inst.addOperand(Op: MCOperand::createReg(Reg: Hexagon::R0));
1411 Inst.addOperand(Op: S27);
1412 break;
1413 }
1414 case Hexagon::M4_mpyrr_addr:
1415 case Hexagon::S4_addi_asl_ri:
1416 case Hexagon::S4_addi_lsr_ri:
1417 case Hexagon::S4_andi_asl_ri:
1418 case Hexagon::S4_andi_lsr_ri:
1419 case Hexagon::S4_ori_asl_ri:
1420 case Hexagon::S4_ori_lsr_ri:
1421 case Hexagon::S4_or_andix:
1422 case Hexagon::S4_subi_asl_ri:
1423 case Hexagon::S4_subi_lsr_ri: {
1424 MCOperand &Ry = Inst.getOperand(i: 0);
1425 MCOperand &src = Inst.getOperand(i: 2);
1426 if (RI->getEncodingValue(Reg: Ry.getReg()) != RI->getEncodingValue(Reg: src.getReg()))
1427 return Match_InvalidOperand;
1428 break;
1429 }
1430
1431 case Hexagon::C2_cmpgei: {
1432 MCOperand &MO = Inst.getOperand(i: 2);
1433 MO.setExpr(HexagonMCExpr::create(
1434 Expr: MCBinaryExpr::createSub(LHS: MO.getExpr(),
1435 RHS: MCConstantExpr::create(Value: 1, Ctx&: Context), Ctx&: Context),
1436 Ctx&: Context));
1437 Inst.setOpcode(Hexagon::C2_cmpgti);
1438 break;
1439 }
1440
1441 case Hexagon::C2_cmpgeui: {
1442 MCOperand &MO = Inst.getOperand(i: 2);
1443 int64_t Value;
1444 bool Success = MO.getExpr()->evaluateAsAbsolute(Res&: Value);
1445 (void)Success;
1446 assert(Success && "Assured by matcher");
1447 if (Value == 0) {
1448 MCInst TmpInst;
1449 MCOperand &Pd = Inst.getOperand(i: 0);
1450 MCOperand &Rt = Inst.getOperand(i: 1);
1451 TmpInst.setOpcode(Hexagon::C2_cmpeq);
1452 TmpInst.addOperand(Op: Pd);
1453 TmpInst.addOperand(Op: Rt);
1454 TmpInst.addOperand(Op: Rt);
1455 Inst = TmpInst;
1456 } else {
1457 MO.setExpr(HexagonMCExpr::create(
1458 Expr: MCBinaryExpr::createSub(LHS: MO.getExpr(),
1459 RHS: MCConstantExpr::create(Value: 1, Ctx&: Context), Ctx&: Context),
1460 Ctx&: Context));
1461 Inst.setOpcode(Hexagon::C2_cmpgtui);
1462 }
1463 break;
1464 }
1465
1466 // Translate a "$Rdd = $Rss" to "$Rdd = combine($Rs, $Rt)"
1467 case Hexagon::A2_tfrp: {
1468 MCOperand &MO = Inst.getOperand(i: 1);
1469 const std::pair<MCRegister, MCRegister> RegPair =
1470 GetScalarRegs(MO.getReg());
1471 MO.setReg(RegPair.first);
1472 Inst.addOperand(Op: MCOperand::createReg(Reg: RegPair.second));
1473 Inst.setOpcode(Hexagon::A2_combinew);
1474 break;
1475 }
1476
1477 case Hexagon::A2_tfrpt:
1478 case Hexagon::A2_tfrpf: {
1479 MCOperand &MO = Inst.getOperand(i: 2);
1480 const std::pair<MCRegister, MCRegister> RegPair =
1481 GetScalarRegs(MO.getReg());
1482 MO.setReg(RegPair.first);
1483 Inst.addOperand(Op: MCOperand::createReg(Reg: RegPair.second));
1484 Inst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrpt)
1485 ? Hexagon::C2_ccombinewt
1486 : Hexagon::C2_ccombinewf);
1487 break;
1488 }
1489 case Hexagon::A2_tfrptnew:
1490 case Hexagon::A2_tfrpfnew: {
1491 MCOperand &MO = Inst.getOperand(i: 2);
1492 const std::pair<MCRegister, MCRegister> RegPair =
1493 GetScalarRegs(MO.getReg());
1494 MO.setReg(RegPair.first);
1495 Inst.addOperand(Op: MCOperand::createReg(Reg: RegPair.second));
1496 Inst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrptnew)
1497 ? Hexagon::C2_ccombinewnewt
1498 : Hexagon::C2_ccombinewnewf);
1499 break;
1500 }
1501
1502 // Translate a "$Vdd = $Vss" to "$Vdd = vcombine($Vs, $Vt)"
1503 case Hexagon::V6_vassignp: {
1504 MCOperand &MO = Inst.getOperand(i: 1);
1505 const std::pair<MCRegister, MCRegister> RegPair = GetVecRegs(MO.getReg());
1506 MO.setReg(RegPair.first);
1507 Inst.addOperand(Op: MCOperand::createReg(Reg: RegPair.second));
1508 Inst.setOpcode(Hexagon::V6_vcombine);
1509 break;
1510 }
1511
1512 // Translate a "$Rx = CONST32(#imm)" to "$Rx = memw(gp+#LABEL) "
1513 case Hexagon::CONST32:
1514 is32bit = true;
1515 [[fallthrough]];
1516 // Translate a "$Rx:y = CONST64(#imm)" to "$Rx:y = memd(gp+#LABEL) "
1517 case Hexagon::CONST64:
1518 // FIXME: need better way to detect AsmStreamer (upstream removed getKind())
1519 if (!Parser.getStreamer().hasRawTextSupport()) {
1520 MCELFStreamer *MES = static_cast<MCELFStreamer *>(&Parser.getStreamer());
1521 MCOperand &MO_1 = Inst.getOperand(i: 1);
1522 MCOperand &MO_0 = Inst.getOperand(i: 0);
1523
1524 // push section onto section stack
1525 MES->pushSection();
1526
1527 std::string myCharStr;
1528 MCSectionELF *mySection;
1529
1530 // check if this as an immediate or a symbol
1531 int64_t Value;
1532 bool Absolute = MO_1.getExpr()->evaluateAsAbsolute(Res&: Value);
1533 if (Absolute) {
1534 // Create a new section - one for each constant
1535 // Some or all of the zeros are replaced with the given immediate.
1536 if (is32bit) {
1537 std::string myImmStr = utohexstr(X: static_cast<uint32_t>(Value));
1538 myCharStr = StringRef(".gnu.linkonce.l4.CONST_00000000")
1539 .drop_back(N: myImmStr.size())
1540 .str() +
1541 myImmStr;
1542 } else {
1543 std::string myImmStr = utohexstr(X: Value);
1544 myCharStr = StringRef(".gnu.linkonce.l8.CONST_0000000000000000")
1545 .drop_back(N: myImmStr.size())
1546 .str() +
1547 myImmStr;
1548 }
1549
1550 mySection = getContext().getELFSection(Section: myCharStr, Type: ELF::SHT_PROGBITS,
1551 Flags: ELF::SHF_ALLOC | ELF::SHF_WRITE);
1552 } else if (MO_1.isExpr()) {
1553 // .lita - for expressions
1554 myCharStr = ".lita";
1555 mySection = getContext().getELFSection(Section: myCharStr, Type: ELF::SHT_PROGBITS,
1556 Flags: ELF::SHF_ALLOC | ELF::SHF_WRITE);
1557 } else
1558 llvm_unreachable("unexpected type of machine operand!");
1559
1560 MES->switchSection(Section: mySection);
1561 unsigned byteSize = is32bit ? 4 : 8;
1562 getStreamer().emitCodeAlignment(Alignment: Align(byteSize), STI: getSTI(), MaxBytesToEmit: byteSize);
1563
1564 MCSymbol *Sym;
1565
1566 // for symbols, get rid of prepended ".gnu.linkonce.lx."
1567
1568 // emit symbol if needed
1569 if (Absolute) {
1570 Sym = getContext().getOrCreateSymbol(Name: StringRef(myCharStr.c_str() + 16));
1571 if (Sym->isUndefined()) {
1572 getStreamer().emitLabel(Symbol: Sym);
1573 getStreamer().emitSymbolAttribute(Symbol: Sym, Attribute: MCSA_Global);
1574 getStreamer().emitIntValue(Value, Size: byteSize);
1575 }
1576 } else if (MO_1.isExpr()) {
1577 const char *StringStart = nullptr;
1578 const char *StringEnd = nullptr;
1579 if (*Operands[4]->getStartLoc().getPointer() == '#') {
1580 StringStart = Operands[5]->getStartLoc().getPointer();
1581 StringEnd = Operands[6]->getStartLoc().getPointer();
1582 } else { // no pound
1583 StringStart = Operands[4]->getStartLoc().getPointer();
1584 StringEnd = Operands[5]->getStartLoc().getPointer();
1585 }
1586
1587 unsigned size = StringEnd - StringStart;
1588 std::string DotConst = ".CONST_";
1589 Sym = getContext().getOrCreateSymbol(Name: DotConst +
1590 StringRef(StringStart, size));
1591
1592 if (Sym->isUndefined()) {
1593 // case where symbol is not yet defined: emit symbol
1594 getStreamer().emitLabel(Symbol: Sym);
1595 getStreamer().emitSymbolAttribute(Symbol: Sym, Attribute: MCSA_Local);
1596 getStreamer().emitValue(Value: MO_1.getExpr(), Size: 4);
1597 }
1598 } else
1599 llvm_unreachable("unexpected type of machine operand!");
1600
1601 MES->popSection();
1602
1603 if (Sym) {
1604 MCInst TmpInst;
1605 if (is32bit) // 32 bit
1606 TmpInst.setOpcode(Hexagon::L2_loadrigp);
1607 else // 64 bit
1608 TmpInst.setOpcode(Hexagon::L2_loadrdgp);
1609
1610 TmpInst.addOperand(Op: MO_0);
1611 TmpInst.addOperand(Op: MCOperand::createExpr(Val: HexagonMCExpr::create(
1612 Expr: MCSymbolRefExpr::create(Symbol: Sym, Ctx&: getContext()), Ctx&: getContext())));
1613 Inst = TmpInst;
1614 }
1615 }
1616 break;
1617
1618 // Translate a "$Rdd = #-imm" to "$Rdd = combine(#[-1,0], #-imm)"
1619 case Hexagon::A2_tfrpi: {
1620 MCOperand &Rdd = Inst.getOperand(i: 0);
1621 MCOperand &MO = Inst.getOperand(i: 1);
1622 int64_t Value;
1623 int sVal = (MO.getExpr()->evaluateAsAbsolute(Res&: Value) && Value < 0) ? -1 : 0;
1624 MCOperand imm(MCOperand::createExpr(
1625 Val: HexagonMCExpr::create(Expr: MCConstantExpr::create(Value: sVal, Ctx&: Context), Ctx&: Context)));
1626 Inst = makeCombineInst(opCode: Hexagon::A2_combineii, Rdd, MO1&: imm, MO2&: MO);
1627 break;
1628 }
1629
1630 // Translate a "$Rdd = [#]#imm" to "$Rdd = combine(#, [#]#imm)"
1631 case Hexagon::TFRI64_V4: {
1632 MCOperand &Rdd = Inst.getOperand(i: 0);
1633 MCOperand &MO = Inst.getOperand(i: 1);
1634 int64_t Value;
1635 if (MO.getExpr()->evaluateAsAbsolute(Res&: Value)) {
1636 int s8 = Hi_32(Value);
1637 if (!isInt<8>(x: s8))
1638 OutOfRange(IDLoc, Val: s8, Max: -128);
1639 MCOperand imm(MCOperand::createExpr(Val: HexagonMCExpr::create(
1640 Expr: MCConstantExpr::create(Value: s8, Ctx&: Context), Ctx&: Context))); // upper 32
1641 auto Expr = HexagonMCExpr::create(
1642 Expr: MCConstantExpr::create(Value: Lo_32(Value), Ctx&: Context), Ctx&: Context);
1643 HexagonMCInstrInfo::setMustExtend(
1644 Expr: *Expr, Val: HexagonMCInstrInfo::mustExtend(Expr: *MO.getExpr()));
1645 MCOperand imm2(MCOperand::createExpr(Val: Expr)); // lower 32
1646 Inst = makeCombineInst(opCode: Hexagon::A4_combineii, Rdd, MO1&: imm, MO2&: imm2);
1647 } else {
1648 MCOperand imm(MCOperand::createExpr(Val: HexagonMCExpr::create(
1649 Expr: MCConstantExpr::create(Value: 0, Ctx&: Context), Ctx&: Context))); // upper 32
1650 Inst = makeCombineInst(opCode: Hexagon::A4_combineii, Rdd, MO1&: imm, MO2&: MO);
1651 }
1652 break;
1653 }
1654
1655 // Handle $Rdd = combine(##imm, #imm)"
1656 case Hexagon::TFRI64_V2_ext: {
1657 MCOperand &Rdd = Inst.getOperand(i: 0);
1658 MCOperand &MO1 = Inst.getOperand(i: 1);
1659 MCOperand &MO2 = Inst.getOperand(i: 2);
1660 int64_t Value;
1661 if (MO2.getExpr()->evaluateAsAbsolute(Res&: Value)) {
1662 int s8 = Value;
1663 if (s8 < -128 || s8 > 127)
1664 OutOfRange(IDLoc, Val: s8, Max: -128);
1665 }
1666 Inst = makeCombineInst(opCode: Hexagon::A2_combineii, Rdd, MO1, MO2);
1667 break;
1668 }
1669
1670 // Handle $Rdd = combine(#imm, ##imm)"
1671 case Hexagon::A4_combineii: {
1672 MCOperand &Rdd = Inst.getOperand(i: 0);
1673 MCOperand &MO1 = Inst.getOperand(i: 1);
1674 int64_t Value;
1675 if (MO1.getExpr()->evaluateAsAbsolute(Res&: Value)) {
1676 int s8 = Value;
1677 if (s8 < -128 || s8 > 127)
1678 OutOfRange(IDLoc, Val: s8, Max: -128);
1679 }
1680 MCOperand &MO2 = Inst.getOperand(i: 2);
1681 Inst = makeCombineInst(opCode: Hexagon::A4_combineii, Rdd, MO1, MO2);
1682 break;
1683 }
1684
1685 case Hexagon::S2_tableidxb_goodsyntax:
1686 Inst.setOpcode(Hexagon::S2_tableidxb);
1687 break;
1688
1689 case Hexagon::S2_tableidxh_goodsyntax: {
1690 MCInst TmpInst;
1691 MCOperand &Rx = Inst.getOperand(i: 0);
1692 MCOperand &Rs = Inst.getOperand(i: 2);
1693 MCOperand &Imm4 = Inst.getOperand(i: 3);
1694 MCOperand &Imm6 = Inst.getOperand(i: 4);
1695 Imm6.setExpr(HexagonMCExpr::create(
1696 Expr: MCBinaryExpr::createSub(LHS: Imm6.getExpr(),
1697 RHS: MCConstantExpr::create(Value: 1, Ctx&: Context), Ctx&: Context),
1698 Ctx&: Context));
1699 TmpInst.setOpcode(Hexagon::S2_tableidxh);
1700 TmpInst.addOperand(Op: Rx);
1701 TmpInst.addOperand(Op: Rx);
1702 TmpInst.addOperand(Op: Rs);
1703 TmpInst.addOperand(Op: Imm4);
1704 TmpInst.addOperand(Op: Imm6);
1705 Inst = TmpInst;
1706 break;
1707 }
1708
1709 case Hexagon::S2_tableidxw_goodsyntax: {
1710 MCInst TmpInst;
1711 MCOperand &Rx = Inst.getOperand(i: 0);
1712 MCOperand &Rs = Inst.getOperand(i: 2);
1713 MCOperand &Imm4 = Inst.getOperand(i: 3);
1714 MCOperand &Imm6 = Inst.getOperand(i: 4);
1715 Imm6.setExpr(HexagonMCExpr::create(
1716 Expr: MCBinaryExpr::createSub(LHS: Imm6.getExpr(),
1717 RHS: MCConstantExpr::create(Value: 2, Ctx&: Context), Ctx&: Context),
1718 Ctx&: Context));
1719 TmpInst.setOpcode(Hexagon::S2_tableidxw);
1720 TmpInst.addOperand(Op: Rx);
1721 TmpInst.addOperand(Op: Rx);
1722 TmpInst.addOperand(Op: Rs);
1723 TmpInst.addOperand(Op: Imm4);
1724 TmpInst.addOperand(Op: Imm6);
1725 Inst = TmpInst;
1726 break;
1727 }
1728
1729 case Hexagon::S2_tableidxd_goodsyntax: {
1730 MCInst TmpInst;
1731 MCOperand &Rx = Inst.getOperand(i: 0);
1732 MCOperand &Rs = Inst.getOperand(i: 2);
1733 MCOperand &Imm4 = Inst.getOperand(i: 3);
1734 MCOperand &Imm6 = Inst.getOperand(i: 4);
1735 Imm6.setExpr(HexagonMCExpr::create(
1736 Expr: MCBinaryExpr::createSub(LHS: Imm6.getExpr(),
1737 RHS: MCConstantExpr::create(Value: 3, Ctx&: Context), Ctx&: Context),
1738 Ctx&: Context));
1739 TmpInst.setOpcode(Hexagon::S2_tableidxd);
1740 TmpInst.addOperand(Op: Rx);
1741 TmpInst.addOperand(Op: Rx);
1742 TmpInst.addOperand(Op: Rs);
1743 TmpInst.addOperand(Op: Imm4);
1744 TmpInst.addOperand(Op: Imm6);
1745 Inst = TmpInst;
1746 break;
1747 }
1748
1749 case Hexagon::M2_mpyui:
1750 Inst.setOpcode(Hexagon::M2_mpyi);
1751 break;
1752 case Hexagon::M2_mpysmi: {
1753 MCInst TmpInst;
1754 MCOperand &Rd = Inst.getOperand(i: 0);
1755 MCOperand &Rs = Inst.getOperand(i: 1);
1756 MCOperand &Imm = Inst.getOperand(i: 2);
1757 int64_t Value;
1758 MCExpr const &Expr = *Imm.getExpr();
1759 bool Absolute = Expr.evaluateAsAbsolute(Res&: Value);
1760 if (!Absolute)
1761 return Match_InvalidOperand;
1762 if (!HexagonMCInstrInfo::mustExtend(Expr) &&
1763 ((Value <= -256) || Value >= 256))
1764 return Match_InvalidOperand;
1765 if (Value < 0 && Value > -256) {
1766 Imm.setExpr(HexagonMCExpr::create(
1767 Expr: MCConstantExpr::create(Value: Value * -1, Ctx&: Context), Ctx&: Context));
1768 TmpInst.setOpcode(Hexagon::M2_mpysin);
1769 } else
1770 TmpInst.setOpcode(Hexagon::M2_mpysip);
1771 TmpInst.addOperand(Op: Rd);
1772 TmpInst.addOperand(Op: Rs);
1773 TmpInst.addOperand(Op: Imm);
1774 Inst = TmpInst;
1775 break;
1776 }
1777
1778 case Hexagon::S2_asr_i_r_rnd_goodsyntax: {
1779 MCOperand &Imm = Inst.getOperand(i: 2);
1780 MCInst TmpInst;
1781 int64_t Value;
1782 bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Res&: Value);
1783 if (!Absolute)
1784 return Match_InvalidOperand;
1785 if (Value == 0) { // convert to $Rd = $Rs
1786 TmpInst.setOpcode(Hexagon::A2_tfr);
1787 MCOperand &Rd = Inst.getOperand(i: 0);
1788 MCOperand &Rs = Inst.getOperand(i: 1);
1789 TmpInst.addOperand(Op: Rd);
1790 TmpInst.addOperand(Op: Rs);
1791 } else {
1792 Imm.setExpr(HexagonMCExpr::create(
1793 Expr: MCBinaryExpr::createSub(LHS: Imm.getExpr(),
1794 RHS: MCConstantExpr::create(Value: 1, Ctx&: Context), Ctx&: Context),
1795 Ctx&: Context));
1796 TmpInst.setOpcode(Hexagon::S2_asr_i_r_rnd);
1797 MCOperand &Rd = Inst.getOperand(i: 0);
1798 MCOperand &Rs = Inst.getOperand(i: 1);
1799 TmpInst.addOperand(Op: Rd);
1800 TmpInst.addOperand(Op: Rs);
1801 TmpInst.addOperand(Op: Imm);
1802 }
1803 Inst = TmpInst;
1804 break;
1805 }
1806
1807 case Hexagon::S2_asr_i_p_rnd_goodsyntax: {
1808 MCOperand &Rdd = Inst.getOperand(i: 0);
1809 MCOperand &Rss = Inst.getOperand(i: 1);
1810 MCOperand &Imm = Inst.getOperand(i: 2);
1811 int64_t Value;
1812 bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Res&: Value);
1813 if (!Absolute)
1814 return Match_InvalidOperand;
1815 if (Value == 0) { // convert to $Rdd = combine ($Rs[0], $Rs[1])
1816 MCInst TmpInst;
1817 unsigned int RegPairNum = RI->getEncodingValue(Reg: Rss.getReg());
1818 std::string R1 = r + utostr(X: RegPairNum + 1);
1819 StringRef Reg1(R1);
1820 Rss.setReg(matchRegister(Name: Reg1));
1821 // Add a new operand for the second register in the pair.
1822 std::string R2 = r + utostr(X: RegPairNum);
1823 StringRef Reg2(R2);
1824 TmpInst.setOpcode(Hexagon::A2_combinew);
1825 TmpInst.addOperand(Op: Rdd);
1826 TmpInst.addOperand(Op: Rss);
1827 TmpInst.addOperand(Op: MCOperand::createReg(Reg: matchRegister(Name: Reg2)));
1828 Inst = TmpInst;
1829 } else {
1830 Imm.setExpr(HexagonMCExpr::create(
1831 Expr: MCBinaryExpr::createSub(LHS: Imm.getExpr(),
1832 RHS: MCConstantExpr::create(Value: 1, Ctx&: Context), Ctx&: Context),
1833 Ctx&: Context));
1834 Inst.setOpcode(Hexagon::S2_asr_i_p_rnd);
1835 }
1836 break;
1837 }
1838
1839 case Hexagon::A4_boundscheck: {
1840 MCOperand &Rs = Inst.getOperand(i: 1);
1841 unsigned int RegNum = RI->getEncodingValue(Reg: Rs.getReg());
1842 if (RegNum & 1) { // Odd mapped to raw:hi, regpair is rodd:odd-1, like r3:2
1843 Inst.setOpcode(Hexagon::A4_boundscheck_hi);
1844 std::string Name = r + utostr(X: RegNum) + Colon + utostr(X: RegNum - 1);
1845 StringRef RegPair = Name;
1846 Rs.setReg(matchRegister(Name: RegPair));
1847 } else { // raw:lo
1848 Inst.setOpcode(Hexagon::A4_boundscheck_lo);
1849 std::string Name = r + utostr(X: RegNum + 1) + Colon + utostr(X: RegNum);
1850 StringRef RegPair = Name;
1851 Rs.setReg(matchRegister(Name: RegPair));
1852 }
1853 break;
1854 }
1855
1856 case Hexagon::A2_addsp: {
1857 MCOperand &Rs = Inst.getOperand(i: 1);
1858 unsigned int RegNum = RI->getEncodingValue(Reg: Rs.getReg());
1859 if (RegNum & 1) { // Odd mapped to raw:hi
1860 Inst.setOpcode(Hexagon::A2_addsph);
1861 std::string Name = r + utostr(X: RegNum) + Colon + utostr(X: RegNum - 1);
1862 StringRef RegPair = Name;
1863 Rs.setReg(matchRegister(Name: RegPair));
1864 } else { // Even mapped raw:lo
1865 Inst.setOpcode(Hexagon::A2_addspl);
1866 std::string Name = r + utostr(X: RegNum + 1) + Colon + utostr(X: RegNum);
1867 StringRef RegPair = Name;
1868 Rs.setReg(matchRegister(Name: RegPair));
1869 }
1870 break;
1871 }
1872
1873 case Hexagon::M2_vrcmpys_s1: {
1874 MCOperand &Rt = Inst.getOperand(i: 2);
1875 unsigned int RegNum = RI->getEncodingValue(Reg: Rt.getReg());
1876 if (RegNum & 1) { // Odd mapped to sat:raw:hi
1877 Inst.setOpcode(Hexagon::M2_vrcmpys_s1_h);
1878 std::string Name = r + utostr(X: RegNum) + Colon + utostr(X: RegNum - 1);
1879 StringRef RegPair = Name;
1880 Rt.setReg(matchRegister(Name: RegPair));
1881 } else { // Even mapped sat:raw:lo
1882 Inst.setOpcode(Hexagon::M2_vrcmpys_s1_l);
1883 std::string Name = r + utostr(X: RegNum + 1) + Colon + utostr(X: RegNum);
1884 StringRef RegPair = Name;
1885 Rt.setReg(matchRegister(Name: RegPair));
1886 }
1887 break;
1888 }
1889
1890 case Hexagon::M2_vrcmpys_acc_s1: {
1891 MCInst TmpInst;
1892 MCOperand &Rxx = Inst.getOperand(i: 0);
1893 MCOperand &Rss = Inst.getOperand(i: 2);
1894 MCOperand &Rt = Inst.getOperand(i: 3);
1895 unsigned int RegNum = RI->getEncodingValue(Reg: Rt.getReg());
1896 if (RegNum & 1) { // Odd mapped to sat:raw:hi
1897 TmpInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_h);
1898 std::string Name = r + utostr(X: RegNum) + Colon + utostr(X: RegNum - 1);
1899 StringRef RegPair = Name;
1900 Rt.setReg(matchRegister(Name: RegPair));
1901 } else { // Even mapped sat:raw:lo
1902 TmpInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_l);
1903 std::string Name = r + utostr(X: RegNum + 1) + Colon + utostr(X: RegNum);
1904 StringRef RegPair = Name;
1905 Rt.setReg(matchRegister(Name: RegPair));
1906 }
1907 // Registers are in different positions
1908 TmpInst.addOperand(Op: Rxx);
1909 TmpInst.addOperand(Op: Rxx);
1910 TmpInst.addOperand(Op: Rss);
1911 TmpInst.addOperand(Op: Rt);
1912 Inst = TmpInst;
1913 break;
1914 }
1915
1916 case Hexagon::M2_vrcmpys_s1rp: {
1917 MCOperand &Rt = Inst.getOperand(i: 2);
1918 unsigned int RegNum = RI->getEncodingValue(Reg: Rt.getReg());
1919 if (RegNum & 1) { // Odd mapped to rnd:sat:raw:hi
1920 Inst.setOpcode(Hexagon::M2_vrcmpys_s1rp_h);
1921 std::string Name = r + utostr(X: RegNum) + Colon + utostr(X: RegNum - 1);
1922 StringRef RegPair = Name;
1923 Rt.setReg(matchRegister(Name: RegPair));
1924 } else { // Even mapped rnd:sat:raw:lo
1925 Inst.setOpcode(Hexagon::M2_vrcmpys_s1rp_l);
1926 std::string Name = r + utostr(X: RegNum + 1) + Colon + utostr(X: RegNum);
1927 StringRef RegPair = Name;
1928 Rt.setReg(matchRegister(Name: RegPair));
1929 }
1930 break;
1931 }
1932
1933 case Hexagon::S5_asrhub_rnd_sat_goodsyntax: {
1934 MCOperand &Imm = Inst.getOperand(i: 2);
1935 int64_t Value;
1936 bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Res&: Value);
1937 if (!Absolute)
1938 return Match_InvalidOperand;
1939 if (Value == 0)
1940 Inst.setOpcode(Hexagon::S2_vsathub);
1941 else {
1942 Imm.setExpr(HexagonMCExpr::create(
1943 Expr: MCBinaryExpr::createSub(LHS: Imm.getExpr(),
1944 RHS: MCConstantExpr::create(Value: 1, Ctx&: Context), Ctx&: Context),
1945 Ctx&: Context));
1946 Inst.setOpcode(Hexagon::S5_asrhub_rnd_sat);
1947 }
1948 break;
1949 }
1950
1951 case Hexagon::S5_vasrhrnd_goodsyntax: {
1952 MCOperand &Rdd = Inst.getOperand(i: 0);
1953 MCOperand &Rss = Inst.getOperand(i: 1);
1954 MCOperand &Imm = Inst.getOperand(i: 2);
1955 int64_t Value;
1956 bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Res&: Value);
1957 if (!Absolute)
1958 return Match_InvalidOperand;
1959 if (Value == 0) {
1960 MCInst TmpInst;
1961 unsigned int RegPairNum = RI->getEncodingValue(Reg: Rss.getReg());
1962 std::string R1 = r + utostr(X: RegPairNum + 1);
1963 StringRef Reg1(R1);
1964 Rss.setReg(matchRegister(Name: Reg1));
1965 // Add a new operand for the second register in the pair.
1966 std::string R2 = r + utostr(X: RegPairNum);
1967 StringRef Reg2(R2);
1968 TmpInst.setOpcode(Hexagon::A2_combinew);
1969 TmpInst.addOperand(Op: Rdd);
1970 TmpInst.addOperand(Op: Rss);
1971 TmpInst.addOperand(Op: MCOperand::createReg(Reg: matchRegister(Name: Reg2)));
1972 Inst = TmpInst;
1973 } else {
1974 Imm.setExpr(HexagonMCExpr::create(
1975 Expr: MCBinaryExpr::createSub(LHS: Imm.getExpr(),
1976 RHS: MCConstantExpr::create(Value: 1, Ctx&: Context), Ctx&: Context),
1977 Ctx&: Context));
1978 Inst.setOpcode(Hexagon::S5_vasrhrnd);
1979 }
1980 break;
1981 }
1982
1983 case Hexagon::A2_not: {
1984 MCInst TmpInst;
1985 MCOperand &Rd = Inst.getOperand(i: 0);
1986 MCOperand &Rs = Inst.getOperand(i: 1);
1987 TmpInst.setOpcode(Hexagon::A2_subri);
1988 TmpInst.addOperand(Op: Rd);
1989 TmpInst.addOperand(Op: MCOperand::createExpr(
1990 Val: HexagonMCExpr::create(Expr: MCConstantExpr::create(Value: -1, Ctx&: Context), Ctx&: Context)));
1991 TmpInst.addOperand(Op: Rs);
1992 Inst = TmpInst;
1993 break;
1994 }
1995 case Hexagon::PS_loadrubabs:
1996 if (!HexagonMCInstrInfo::mustExtend(Expr: *Inst.getOperand(i: 1).getExpr()))
1997 Inst.setOpcode(Hexagon::L2_loadrubgp);
1998 break;
1999 case Hexagon::PS_loadrbabs:
2000 if (!HexagonMCInstrInfo::mustExtend(Expr: *Inst.getOperand(i: 1).getExpr()))
2001 Inst.setOpcode(Hexagon::L2_loadrbgp);
2002 break;
2003 case Hexagon::PS_loadruhabs:
2004 if (!HexagonMCInstrInfo::mustExtend(Expr: *Inst.getOperand(i: 1).getExpr()))
2005 Inst.setOpcode(Hexagon::L2_loadruhgp);
2006 break;
2007 case Hexagon::PS_loadrhabs:
2008 if (!HexagonMCInstrInfo::mustExtend(Expr: *Inst.getOperand(i: 1).getExpr()))
2009 Inst.setOpcode(Hexagon::L2_loadrhgp);
2010 break;
2011 case Hexagon::PS_loadriabs:
2012 if (!HexagonMCInstrInfo::mustExtend(Expr: *Inst.getOperand(i: 1).getExpr()))
2013 Inst.setOpcode(Hexagon::L2_loadrigp);
2014 break;
2015 case Hexagon::PS_loadrdabs:
2016 if (!HexagonMCInstrInfo::mustExtend(Expr: *Inst.getOperand(i: 1).getExpr()))
2017 Inst.setOpcode(Hexagon::L2_loadrdgp);
2018 break;
2019 case Hexagon::PS_storerbabs:
2020 if (!HexagonMCInstrInfo::mustExtend(Expr: *Inst.getOperand(i: 0).getExpr()))
2021 Inst.setOpcode(Hexagon::S2_storerbgp);
2022 break;
2023 case Hexagon::PS_storerhabs:
2024 if (!HexagonMCInstrInfo::mustExtend(Expr: *Inst.getOperand(i: 0).getExpr()))
2025 Inst.setOpcode(Hexagon::S2_storerhgp);
2026 break;
2027 case Hexagon::PS_storerfabs:
2028 if (!HexagonMCInstrInfo::mustExtend(Expr: *Inst.getOperand(i: 0).getExpr()))
2029 Inst.setOpcode(Hexagon::S2_storerfgp);
2030 break;
2031 case Hexagon::PS_storeriabs:
2032 if (!HexagonMCInstrInfo::mustExtend(Expr: *Inst.getOperand(i: 0).getExpr()))
2033 Inst.setOpcode(Hexagon::S2_storerigp);
2034 break;
2035 case Hexagon::PS_storerdabs:
2036 if (!HexagonMCInstrInfo::mustExtend(Expr: *Inst.getOperand(i: 0).getExpr()))
2037 Inst.setOpcode(Hexagon::S2_storerdgp);
2038 break;
2039 case Hexagon::PS_storerbnewabs:
2040 if (!HexagonMCInstrInfo::mustExtend(Expr: *Inst.getOperand(i: 0).getExpr()))
2041 Inst.setOpcode(Hexagon::S2_storerbnewgp);
2042 break;
2043 case Hexagon::PS_storerhnewabs:
2044 if (!HexagonMCInstrInfo::mustExtend(Expr: *Inst.getOperand(i: 0).getExpr()))
2045 Inst.setOpcode(Hexagon::S2_storerhnewgp);
2046 break;
2047 case Hexagon::PS_storerinewabs:
2048 if (!HexagonMCInstrInfo::mustExtend(Expr: *Inst.getOperand(i: 0).getExpr()))
2049 Inst.setOpcode(Hexagon::S2_storerinewgp);
2050 break;
2051 case Hexagon::A2_zxtb: {
2052 Inst.setOpcode(Hexagon::A2_andir);
2053 Inst.addOperand(
2054 Op: MCOperand::createExpr(Val: MCConstantExpr::create(Value: 255, Ctx&: Context)));
2055 break;
2056 }
2057 } // switch
2058
2059 return Match_Success;
2060}
2061
2062MCRegister HexagonAsmParser::matchRegister(StringRef Name) {
2063 if (MCRegister Reg = MatchRegisterName(Name))
2064 return Reg;
2065 return MatchRegisterAltName(Name);
2066}
2067