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