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