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