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