xref: /freebsd/contrib/llvm-project/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===- MSP430AsmParser.cpp - Parse MSP430 assembly 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 "MSP430.h"
10 #include "MSP430RegisterInfo.h"
11 #include "MCTargetDesc/MSP430MCTargetDesc.h"
12 #include "TargetInfo/MSP430TargetInfo.h"
13 
14 #include "llvm/ADT/APInt.h"
15 #include "llvm/MC/MCContext.h"
16 #include "llvm/MC/MCExpr.h"
17 #include "llvm/MC/MCInst.h"
18 #include "llvm/MC/MCInstBuilder.h"
19 #include "llvm/MC/MCInstrInfo.h"
20 #include "llvm/MC/MCParser/MCAsmLexer.h"
21 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
22 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
23 #include "llvm/MC/MCStreamer.h"
24 #include "llvm/MC/MCSubtargetInfo.h"
25 #include "llvm/MC/MCSymbol.h"
26 #include "llvm/MC/MCValue.h"
27 #include "llvm/MC/TargetRegistry.h"
28 #include "llvm/Support/Debug.h"
29 #include "llvm/Support/MathExtras.h"
30 
31 #define DEBUG_TYPE "msp430-asm-parser"
32 
33 using namespace llvm;
34 
35 namespace {
36 
37 /// Parses MSP430 assembly from a stream.
38 class MSP430AsmParser : public MCTargetAsmParser {
39   const MCSubtargetInfo &STI;
40   MCAsmParser &Parser;
41   const MCRegisterInfo *MRI;
42 
43   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
44                                OperandVector &Operands, MCStreamer &Out,
45                                uint64_t &ErrorInfo,
46                                bool MatchingInlineAsm) override;
47 
48   bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
49   ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
50                                SMLoc &EndLoc) override;
51 
52   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
53                         SMLoc NameLoc, OperandVector &Operands) override;
54 
55   ParseStatus parseDirective(AsmToken DirectiveID) override;
56   bool ParseDirectiveRefSym(AsmToken DirectiveID);
57 
58   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
59                                       unsigned Kind) override;
60 
61   bool parseJccInstruction(ParseInstructionInfo &Info, StringRef Name,
62                            SMLoc NameLoc, OperandVector &Operands);
63 
64   bool ParseOperand(OperandVector &Operands);
65 
66   bool ParseLiteralValues(unsigned Size, SMLoc L);
67 
getParser() const68   MCAsmParser &getParser() const { return Parser; }
getLexer() const69   MCAsmLexer &getLexer() const { return Parser.getLexer(); }
70 
71   /// @name Auto-generated Matcher Functions
72   /// {
73 
74 #define GET_ASSEMBLER_HEADER
75 #include "MSP430GenAsmMatcher.inc"
76 
77   /// }
78 
79 public:
MSP430AsmParser(const MCSubtargetInfo & STI,MCAsmParser & Parser,const MCInstrInfo & MII,const MCTargetOptions & Options)80   MSP430AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
81                   const MCInstrInfo &MII, const MCTargetOptions &Options)
82       : MCTargetAsmParser(Options, STI, MII), STI(STI), Parser(Parser) {
83     MCAsmParserExtension::Initialize(Parser);
84     MRI = getContext().getRegisterInfo();
85 
86     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
87   }
88 };
89 
90 /// A parsed MSP430 assembly operand.
91 class MSP430Operand : public MCParsedAsmOperand {
92   typedef MCParsedAsmOperand Base;
93 
94   enum KindTy {
95     k_Imm,
96     k_Reg,
97     k_Tok,
98     k_Mem,
99     k_IndReg,
100     k_PostIndReg
101   } Kind;
102 
103   struct Memory {
104     unsigned Reg;
105     const MCExpr *Offset;
106   };
107   union {
108     const MCExpr *Imm;
109     unsigned      Reg;
110     StringRef     Tok;
111     Memory        Mem;
112   };
113 
114   SMLoc Start, End;
115 
116 public:
MSP430Operand(StringRef Tok,SMLoc const & S)117   MSP430Operand(StringRef Tok, SMLoc const &S)
118       : Kind(k_Tok), Tok(Tok), Start(S), End(S) {}
MSP430Operand(KindTy Kind,unsigned Reg,SMLoc const & S,SMLoc const & E)119   MSP430Operand(KindTy Kind, unsigned Reg, SMLoc const &S, SMLoc const &E)
120       : Kind(Kind), Reg(Reg), Start(S), End(E) {}
MSP430Operand(MCExpr const * Imm,SMLoc const & S,SMLoc const & E)121   MSP430Operand(MCExpr const *Imm, SMLoc const &S, SMLoc const &E)
122       : Kind(k_Imm), Imm(Imm), Start(S), End(E) {}
MSP430Operand(unsigned Reg,MCExpr const * Expr,SMLoc const & S,SMLoc const & E)123   MSP430Operand(unsigned Reg, MCExpr const *Expr, SMLoc const &S,
124                 SMLoc const &E)
125       : Kind(k_Mem), Mem({Reg, Expr}), Start(S), End(E) {}
126 
addRegOperands(MCInst & Inst,unsigned N) const127   void addRegOperands(MCInst &Inst, unsigned N) const {
128     assert((Kind == k_Reg || Kind == k_IndReg || Kind == k_PostIndReg) &&
129         "Unexpected operand kind");
130     assert(N == 1 && "Invalid number of operands!");
131 
132     Inst.addOperand(MCOperand::createReg(Reg));
133   }
134 
addExprOperand(MCInst & Inst,const MCExpr * Expr) const135   void addExprOperand(MCInst &Inst, const MCExpr *Expr) const {
136     // Add as immediate when possible
137     if (!Expr)
138       Inst.addOperand(MCOperand::createImm(0));
139     else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
140       Inst.addOperand(MCOperand::createImm(CE->getValue()));
141     else
142       Inst.addOperand(MCOperand::createExpr(Expr));
143   }
144 
addImmOperands(MCInst & Inst,unsigned N) const145   void addImmOperands(MCInst &Inst, unsigned N) const {
146     assert(Kind == k_Imm && "Unexpected operand kind");
147     assert(N == 1 && "Invalid number of operands!");
148 
149     addExprOperand(Inst, Imm);
150   }
151 
addMemOperands(MCInst & Inst,unsigned N) const152   void addMemOperands(MCInst &Inst, unsigned N) const {
153     assert(Kind == k_Mem && "Unexpected operand kind");
154     assert(N == 2 && "Invalid number of operands");
155 
156     Inst.addOperand(MCOperand::createReg(Mem.Reg));
157     addExprOperand(Inst, Mem.Offset);
158   }
159 
isReg() const160   bool isReg()   const override { return Kind == k_Reg; }
isImm() const161   bool isImm()   const override { return Kind == k_Imm; }
isToken() const162   bool isToken() const override { return Kind == k_Tok; }
isMem() const163   bool isMem()   const override { return Kind == k_Mem; }
isIndReg() const164   bool isIndReg()         const { return Kind == k_IndReg; }
isPostIndReg() const165   bool isPostIndReg()     const { return Kind == k_PostIndReg; }
166 
isCGImm() const167   bool isCGImm() const {
168     if (Kind != k_Imm)
169       return false;
170 
171     int64_t Val;
172     if (!Imm->evaluateAsAbsolute(Val))
173       return false;
174 
175     if (Val == 0 || Val == 1 || Val == 2 || Val == 4 || Val == 8 || Val == -1)
176       return true;
177 
178     return false;
179   }
180 
getToken() const181   StringRef getToken() const {
182     assert(Kind == k_Tok && "Invalid access!");
183     return Tok;
184   }
185 
getReg() const186   MCRegister getReg() const override {
187     assert(Kind == k_Reg && "Invalid access!");
188     return Reg;
189   }
190 
setReg(unsigned RegNo)191   void setReg(unsigned RegNo) {
192     assert(Kind == k_Reg && "Invalid access!");
193     Reg = RegNo;
194   }
195 
CreateToken(StringRef Str,SMLoc S)196   static std::unique_ptr<MSP430Operand> CreateToken(StringRef Str, SMLoc S) {
197     return std::make_unique<MSP430Operand>(Str, S);
198   }
199 
CreateReg(unsigned RegNum,SMLoc S,SMLoc E)200   static std::unique_ptr<MSP430Operand> CreateReg(unsigned RegNum, SMLoc S,
201                                                   SMLoc E) {
202     return std::make_unique<MSP430Operand>(k_Reg, RegNum, S, E);
203   }
204 
CreateImm(const MCExpr * Val,SMLoc S,SMLoc E)205   static std::unique_ptr<MSP430Operand> CreateImm(const MCExpr *Val, SMLoc S,
206                                                   SMLoc E) {
207     return std::make_unique<MSP430Operand>(Val, S, E);
208   }
209 
CreateMem(unsigned RegNum,const MCExpr * Val,SMLoc S,SMLoc E)210   static std::unique_ptr<MSP430Operand> CreateMem(unsigned RegNum,
211                                                   const MCExpr *Val,
212                                                   SMLoc S, SMLoc E) {
213     return std::make_unique<MSP430Operand>(RegNum, Val, S, E);
214   }
215 
CreateIndReg(unsigned RegNum,SMLoc S,SMLoc E)216   static std::unique_ptr<MSP430Operand> CreateIndReg(unsigned RegNum, SMLoc S,
217                                                   SMLoc E) {
218     return std::make_unique<MSP430Operand>(k_IndReg, RegNum, S, E);
219   }
220 
CreatePostIndReg(unsigned RegNum,SMLoc S,SMLoc E)221   static std::unique_ptr<MSP430Operand> CreatePostIndReg(unsigned RegNum, SMLoc S,
222                                                   SMLoc E) {
223     return std::make_unique<MSP430Operand>(k_PostIndReg, RegNum, S, E);
224   }
225 
getStartLoc() const226   SMLoc getStartLoc() const override { return Start; }
getEndLoc() const227   SMLoc getEndLoc() const override { return End; }
228 
print(raw_ostream & O) const229   void print(raw_ostream &O) const override {
230     switch (Kind) {
231     case k_Tok:
232       O << "Token " << Tok;
233       break;
234     case k_Reg:
235       O << "Register " << Reg;
236       break;
237     case k_Imm:
238       O << "Immediate " << *Imm;
239       break;
240     case k_Mem:
241       O << "Memory ";
242       O << *Mem.Offset << "(" << Reg << ")";
243       break;
244     case k_IndReg:
245       O << "RegInd " << Reg;
246       break;
247     case k_PostIndReg:
248       O << "PostInc " << Reg;
249       break;
250     }
251   }
252 };
253 } // end anonymous namespace
254 
MatchAndEmitInstruction(SMLoc Loc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)255 bool MSP430AsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,
256                                               OperandVector &Operands,
257                                               MCStreamer &Out,
258                                               uint64_t &ErrorInfo,
259                                               bool MatchingInlineAsm) {
260   MCInst Inst;
261   unsigned MatchResult =
262       MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
263 
264   switch (MatchResult) {
265   case Match_Success:
266     Inst.setLoc(Loc);
267     Out.emitInstruction(Inst, STI);
268     return false;
269   case Match_MnemonicFail:
270     return Error(Loc, "invalid instruction mnemonic");
271   case Match_InvalidOperand: {
272     SMLoc ErrorLoc = Loc;
273     if (ErrorInfo != ~0U) {
274       if (ErrorInfo >= Operands.size())
275         return Error(ErrorLoc, "too few operands for instruction");
276 
277       ErrorLoc = ((MSP430Operand &)*Operands[ErrorInfo]).getStartLoc();
278       if (ErrorLoc == SMLoc())
279         ErrorLoc = Loc;
280     }
281     return Error(ErrorLoc, "invalid operand for instruction");
282   }
283   default:
284     return true;
285   }
286 }
287 
288 // Auto-generated by TableGen
289 static MCRegister MatchRegisterName(StringRef Name);
290 static MCRegister MatchRegisterAltName(StringRef Name);
291 
parseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)292 bool MSP430AsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
293                                     SMLoc &EndLoc) {
294   ParseStatus Res = tryParseRegister(Reg, StartLoc, EndLoc);
295   if (Res.isFailure())
296     return Error(StartLoc, "invalid register name");
297   if (Res.isSuccess())
298     return false;
299   if (Res.isNoMatch())
300     return true;
301 
302   llvm_unreachable("unknown parse status");
303 }
304 
tryParseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)305 ParseStatus MSP430AsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
306                                               SMLoc &EndLoc) {
307   if (getLexer().getKind() == AsmToken::Identifier) {
308     auto Name = getLexer().getTok().getIdentifier().lower();
309     Reg = MatchRegisterName(Name);
310     if (Reg == MSP430::NoRegister) {
311       Reg = MatchRegisterAltName(Name);
312       if (Reg == MSP430::NoRegister)
313         return ParseStatus::NoMatch;
314     }
315 
316     AsmToken const &T = getParser().getTok();
317     StartLoc = T.getLoc();
318     EndLoc = T.getEndLoc();
319     getLexer().Lex(); // eat register token
320 
321     return ParseStatus::Success;
322   }
323 
324   return ParseStatus::Failure;
325 }
326 
parseJccInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)327 bool MSP430AsmParser::parseJccInstruction(ParseInstructionInfo &Info,
328                                           StringRef Name, SMLoc NameLoc,
329                                           OperandVector &Operands) {
330   if (!Name.starts_with_insensitive("j"))
331     return true;
332 
333   auto CC = Name.drop_front().lower();
334   unsigned CondCode;
335   if (CC == "ne" || CC == "nz")
336     CondCode = MSP430CC::COND_NE;
337   else if (CC == "eq" || CC == "z")
338     CondCode = MSP430CC::COND_E;
339   else if (CC == "lo" || CC == "nc")
340     CondCode = MSP430CC::COND_LO;
341   else if (CC == "hs" || CC == "c")
342     CondCode = MSP430CC::COND_HS;
343   else if (CC == "n")
344     CondCode = MSP430CC::COND_N;
345   else if (CC == "ge")
346     CondCode = MSP430CC::COND_GE;
347   else if (CC == "l")
348     CondCode = MSP430CC::COND_L;
349   else if (CC == "mp")
350     CondCode = MSP430CC::COND_NONE;
351   else
352     return Error(NameLoc, "unknown instruction");
353 
354   if (CondCode == (unsigned)MSP430CC::COND_NONE)
355     Operands.push_back(MSP430Operand::CreateToken("jmp", NameLoc));
356   else {
357     Operands.push_back(MSP430Operand::CreateToken("j", NameLoc));
358     const MCExpr *CCode = MCConstantExpr::create(CondCode, getContext());
359     Operands.push_back(MSP430Operand::CreateImm(CCode, SMLoc(), SMLoc()));
360   }
361 
362   // Skip optional '$' sign.
363   (void)parseOptionalToken(AsmToken::Dollar);
364 
365   const MCExpr *Val;
366   SMLoc ExprLoc = getLexer().getLoc();
367   if (getParser().parseExpression(Val))
368     return Error(ExprLoc, "expected expression operand");
369 
370   int64_t Res;
371   if (Val->evaluateAsAbsolute(Res))
372     if (Res < -512 || Res > 511)
373       return Error(ExprLoc, "invalid jump offset");
374 
375   Operands.push_back(MSP430Operand::CreateImm(Val, ExprLoc,
376     getLexer().getLoc()));
377 
378   if (getLexer().isNot(AsmToken::EndOfStatement)) {
379     SMLoc Loc = getLexer().getLoc();
380     getParser().eatToEndOfStatement();
381     return Error(Loc, "unexpected token");
382   }
383 
384   getParser().Lex(); // Consume the EndOfStatement.
385   return false;
386 }
387 
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)388 bool MSP430AsmParser::ParseInstruction(ParseInstructionInfo &Info,
389                                        StringRef Name, SMLoc NameLoc,
390                                        OperandVector &Operands) {
391   // Drop .w suffix
392   if (Name.ends_with_insensitive(".w"))
393     Name = Name.drop_back(2);
394 
395   if (!parseJccInstruction(Info, Name, NameLoc, Operands))
396     return false;
397 
398   // First operand is instruction mnemonic
399   Operands.push_back(MSP430Operand::CreateToken(Name, NameLoc));
400 
401   // If there are no more operands, then finish
402   if (getLexer().is(AsmToken::EndOfStatement))
403     return false;
404 
405   // Parse first operand
406   if (ParseOperand(Operands))
407     return true;
408 
409   // Parse second operand if any
410   if (parseOptionalToken(AsmToken::Comma) && ParseOperand(Operands))
411     return true;
412 
413   if (getLexer().isNot(AsmToken::EndOfStatement)) {
414     SMLoc Loc = getLexer().getLoc();
415     getParser().eatToEndOfStatement();
416     return Error(Loc, "unexpected token");
417   }
418 
419   getParser().Lex(); // Consume the EndOfStatement.
420   return false;
421 }
422 
ParseDirectiveRefSym(AsmToken DirectiveID)423 bool MSP430AsmParser::ParseDirectiveRefSym(AsmToken DirectiveID) {
424   StringRef Name;
425   if (getParser().parseIdentifier(Name))
426     return TokError("expected identifier in directive");
427 
428   MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
429   getStreamer().emitSymbolAttribute(Sym, MCSA_Global);
430   return parseEOL();
431 }
432 
parseDirective(AsmToken DirectiveID)433 ParseStatus MSP430AsmParser::parseDirective(AsmToken DirectiveID) {
434   StringRef IDVal = DirectiveID.getIdentifier();
435   if (IDVal.lower() == ".long")
436     return ParseLiteralValues(4, DirectiveID.getLoc());
437   if (IDVal.lower() == ".word" || IDVal.lower() == ".short")
438     return ParseLiteralValues(2, DirectiveID.getLoc());
439   if (IDVal.lower() == ".byte")
440     return ParseLiteralValues(1, DirectiveID.getLoc());
441   if (IDVal.lower() == ".refsym")
442     return ParseDirectiveRefSym(DirectiveID);
443   return ParseStatus::NoMatch;
444 }
445 
ParseOperand(OperandVector & Operands)446 bool MSP430AsmParser::ParseOperand(OperandVector &Operands) {
447   switch (getLexer().getKind()) {
448     default: return true;
449     case AsmToken::Identifier: {
450       // try rN
451       MCRegister RegNo;
452       SMLoc StartLoc, EndLoc;
453       if (!parseRegister(RegNo, StartLoc, EndLoc)) {
454         Operands.push_back(MSP430Operand::CreateReg(RegNo, StartLoc, EndLoc));
455         return false;
456       }
457       [[fallthrough]];
458     }
459     case AsmToken::Integer:
460     case AsmToken::Plus:
461     case AsmToken::Minus: {
462       SMLoc StartLoc = getParser().getTok().getLoc();
463       const MCExpr *Val;
464       // Try constexpr[(rN)]
465       if (!getParser().parseExpression(Val)) {
466         MCRegister RegNo = MSP430::PC;
467         SMLoc EndLoc = getParser().getTok().getLoc();
468         // Try (rN)
469         if (parseOptionalToken(AsmToken::LParen)) {
470           SMLoc RegStartLoc;
471           if (parseRegister(RegNo, RegStartLoc, EndLoc))
472             return true;
473           EndLoc = getParser().getTok().getEndLoc();
474           if (!parseOptionalToken(AsmToken::RParen))
475             return true;
476         }
477         Operands.push_back(MSP430Operand::CreateMem(RegNo, Val, StartLoc,
478           EndLoc));
479         return false;
480       }
481       return true;
482     }
483     case AsmToken::Amp: {
484       // Try &constexpr
485       SMLoc StartLoc = getParser().getTok().getLoc();
486       getLexer().Lex(); // Eat '&'
487       const MCExpr *Val;
488       if (!getParser().parseExpression(Val)) {
489         SMLoc EndLoc = getParser().getTok().getLoc();
490         Operands.push_back(MSP430Operand::CreateMem(MSP430::SR, Val, StartLoc,
491           EndLoc));
492         return false;
493       }
494       return true;
495     }
496     case AsmToken::At: {
497       // Try @rN[+]
498       SMLoc StartLoc = getParser().getTok().getLoc();
499       getLexer().Lex(); // Eat '@'
500       MCRegister RegNo;
501       SMLoc RegStartLoc, EndLoc;
502       if (parseRegister(RegNo, RegStartLoc, EndLoc))
503         return true;
504       if (parseOptionalToken(AsmToken::Plus)) {
505         Operands.push_back(MSP430Operand::CreatePostIndReg(RegNo, StartLoc, EndLoc));
506         return false;
507       }
508       if (Operands.size() > 1) // Emulate @rd in destination position as 0(rd)
509         Operands.push_back(MSP430Operand::CreateMem(RegNo,
510             MCConstantExpr::create(0, getContext()), StartLoc, EndLoc));
511       else
512         Operands.push_back(MSP430Operand::CreateIndReg(RegNo, StartLoc, EndLoc));
513       return false;
514     }
515     case AsmToken::Hash:
516       // Try #constexpr
517       SMLoc StartLoc = getParser().getTok().getLoc();
518       getLexer().Lex(); // Eat '#'
519       const MCExpr *Val;
520       if (!getParser().parseExpression(Val)) {
521         SMLoc EndLoc = getParser().getTok().getLoc();
522         Operands.push_back(MSP430Operand::CreateImm(Val, StartLoc, EndLoc));
523         return false;
524       }
525       return true;
526   }
527 }
528 
ParseLiteralValues(unsigned Size,SMLoc L)529 bool MSP430AsmParser::ParseLiteralValues(unsigned Size, SMLoc L) {
530   auto parseOne = [&]() -> bool {
531     const MCExpr *Value;
532     if (getParser().parseExpression(Value))
533       return true;
534     getParser().getStreamer().emitValue(Value, Size, L);
535     return false;
536   };
537   return (parseMany(parseOne));
538 }
539 
LLVMInitializeMSP430AsmParser()540 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMSP430AsmParser() {
541   RegisterMCAsmParser<MSP430AsmParser> X(getTheMSP430Target());
542 }
543 
544 #define GET_REGISTER_MATCHER
545 #define GET_MATCHER_IMPLEMENTATION
546 #include "MSP430GenAsmMatcher.inc"
547 
convertGR16ToGR8(unsigned Reg)548 static unsigned convertGR16ToGR8(unsigned Reg) {
549   switch (Reg) {
550   default:
551     llvm_unreachable("Unknown GR16 register");
552   case MSP430::PC:  return MSP430::PCB;
553   case MSP430::SP:  return MSP430::SPB;
554   case MSP430::SR:  return MSP430::SRB;
555   case MSP430::CG:  return MSP430::CGB;
556   case MSP430::R4:  return MSP430::R4B;
557   case MSP430::R5:  return MSP430::R5B;
558   case MSP430::R6:  return MSP430::R6B;
559   case MSP430::R7:  return MSP430::R7B;
560   case MSP430::R8:  return MSP430::R8B;
561   case MSP430::R9:  return MSP430::R9B;
562   case MSP430::R10: return MSP430::R10B;
563   case MSP430::R11: return MSP430::R11B;
564   case MSP430::R12: return MSP430::R12B;
565   case MSP430::R13: return MSP430::R13B;
566   case MSP430::R14: return MSP430::R14B;
567   case MSP430::R15: return MSP430::R15B;
568   }
569 }
570 
validateTargetOperandClass(MCParsedAsmOperand & AsmOp,unsigned Kind)571 unsigned MSP430AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
572                                                      unsigned Kind) {
573   MSP430Operand &Op = static_cast<MSP430Operand &>(AsmOp);
574 
575   if (!Op.isReg())
576     return Match_InvalidOperand;
577 
578   unsigned Reg = Op.getReg();
579   bool isGR16 =
580       MSP430MCRegisterClasses[MSP430::GR16RegClassID].contains(Reg);
581 
582   if (isGR16 && (Kind == MCK_GR8)) {
583     Op.setReg(convertGR16ToGR8(Reg));
584     return Match_Success;
585   }
586 
587   return Match_InvalidOperand;
588 }
589