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