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