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(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
49 OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
50 SMLoc &EndLoc) override;
51
52 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
53 SMLoc NameLoc, OperandVector &Operands) override;
54
55 bool 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 unsigned 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 unsigned MatchRegisterName(StringRef Name);
290 static unsigned MatchRegisterAltName(StringRef Name);
291
ParseRegister(unsigned & RegNo,SMLoc & StartLoc,SMLoc & EndLoc)292 bool MSP430AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
293 SMLoc &EndLoc) {
294 switch (tryParseRegister(RegNo, StartLoc, EndLoc)) {
295 case MatchOperand_ParseFail:
296 return Error(StartLoc, "invalid register name");
297 case MatchOperand_Success:
298 return false;
299 case MatchOperand_NoMatch:
300 return true;
301 }
302
303 llvm_unreachable("unknown match result type");
304 }
305
tryParseRegister(unsigned & RegNo,SMLoc & StartLoc,SMLoc & EndLoc)306 OperandMatchResultTy MSP430AsmParser::tryParseRegister(unsigned &RegNo,
307 SMLoc &StartLoc,
308 SMLoc &EndLoc) {
309 if (getLexer().getKind() == AsmToken::Identifier) {
310 auto Name = getLexer().getTok().getIdentifier().lower();
311 RegNo = MatchRegisterName(Name);
312 if (RegNo == MSP430::NoRegister) {
313 RegNo = MatchRegisterAltName(Name);
314 if (RegNo == MSP430::NoRegister)
315 return MatchOperand_NoMatch;
316 }
317
318 AsmToken const &T = getParser().getTok();
319 StartLoc = T.getLoc();
320 EndLoc = T.getEndLoc();
321 getLexer().Lex(); // eat register token
322
323 return MatchOperand_Success;
324 }
325
326 return MatchOperand_ParseFail;
327 }
328
parseJccInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)329 bool MSP430AsmParser::parseJccInstruction(ParseInstructionInfo &Info,
330 StringRef Name, SMLoc NameLoc,
331 OperandVector &Operands) {
332 if (!Name.startswith_insensitive("j"))
333 return true;
334
335 auto CC = Name.drop_front().lower();
336 unsigned CondCode;
337 if (CC == "ne" || CC == "nz")
338 CondCode = MSP430CC::COND_NE;
339 else if (CC == "eq" || CC == "z")
340 CondCode = MSP430CC::COND_E;
341 else if (CC == "lo" || CC == "nc")
342 CondCode = MSP430CC::COND_LO;
343 else if (CC == "hs" || CC == "c")
344 CondCode = MSP430CC::COND_HS;
345 else if (CC == "n")
346 CondCode = MSP430CC::COND_N;
347 else if (CC == "ge")
348 CondCode = MSP430CC::COND_GE;
349 else if (CC == "l")
350 CondCode = MSP430CC::COND_L;
351 else if (CC == "mp")
352 CondCode = MSP430CC::COND_NONE;
353 else
354 return Error(NameLoc, "unknown instruction");
355
356 if (CondCode == (unsigned)MSP430CC::COND_NONE)
357 Operands.push_back(MSP430Operand::CreateToken("jmp", NameLoc));
358 else {
359 Operands.push_back(MSP430Operand::CreateToken("j", NameLoc));
360 const MCExpr *CCode = MCConstantExpr::create(CondCode, getContext());
361 Operands.push_back(MSP430Operand::CreateImm(CCode, SMLoc(), SMLoc()));
362 }
363
364 // Skip optional '$' sign.
365 if (getLexer().getKind() == AsmToken::Dollar)
366 getLexer().Lex(); // Eat '$'
367
368 const MCExpr *Val;
369 SMLoc ExprLoc = getLexer().getLoc();
370 if (getParser().parseExpression(Val))
371 return Error(ExprLoc, "expected expression operand");
372
373 int64_t Res;
374 if (Val->evaluateAsAbsolute(Res))
375 if (Res < -512 || Res > 511)
376 return Error(ExprLoc, "invalid jump offset");
377
378 Operands.push_back(MSP430Operand::CreateImm(Val, ExprLoc,
379 getLexer().getLoc()));
380
381 if (getLexer().isNot(AsmToken::EndOfStatement)) {
382 SMLoc Loc = getLexer().getLoc();
383 getParser().eatToEndOfStatement();
384 return Error(Loc, "unexpected token");
385 }
386
387 getParser().Lex(); // Consume the EndOfStatement.
388 return false;
389 }
390
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)391 bool MSP430AsmParser::ParseInstruction(ParseInstructionInfo &Info,
392 StringRef Name, SMLoc NameLoc,
393 OperandVector &Operands) {
394 // Drop .w suffix
395 if (Name.endswith_insensitive(".w"))
396 Name = Name.drop_back(2);
397
398 if (!parseJccInstruction(Info, Name, NameLoc, Operands))
399 return false;
400
401 // First operand is instruction mnemonic
402 Operands.push_back(MSP430Operand::CreateToken(Name, NameLoc));
403
404 // If there are no more operands, then finish
405 if (getLexer().is(AsmToken::EndOfStatement))
406 return false;
407
408 // Parse first operand
409 if (ParseOperand(Operands))
410 return true;
411
412 // Parse second operand if any
413 if (getLexer().is(AsmToken::Comma)) {
414 getLexer().Lex(); // Eat ','
415 if (ParseOperand(Operands))
416 return true;
417 }
418
419 if (getLexer().isNot(AsmToken::EndOfStatement)) {
420 SMLoc Loc = getLexer().getLoc();
421 getParser().eatToEndOfStatement();
422 return Error(Loc, "unexpected token");
423 }
424
425 getParser().Lex(); // Consume the EndOfStatement.
426 return false;
427 }
428
ParseDirectiveRefSym(AsmToken DirectiveID)429 bool MSP430AsmParser::ParseDirectiveRefSym(AsmToken DirectiveID) {
430 StringRef Name;
431 if (getParser().parseIdentifier(Name))
432 return TokError("expected identifier in directive");
433
434 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
435 getStreamer().emitSymbolAttribute(Sym, MCSA_Global);
436 return false;
437 }
438
ParseDirective(AsmToken DirectiveID)439 bool MSP430AsmParser::ParseDirective(AsmToken DirectiveID) {
440 StringRef IDVal = DirectiveID.getIdentifier();
441 if (IDVal.lower() == ".long") {
442 ParseLiteralValues(4, DirectiveID.getLoc());
443 } else if (IDVal.lower() == ".word" || IDVal.lower() == ".short") {
444 ParseLiteralValues(2, DirectiveID.getLoc());
445 } else if (IDVal.lower() == ".byte") {
446 ParseLiteralValues(1, DirectiveID.getLoc());
447 } else if (IDVal.lower() == ".refsym") {
448 return ParseDirectiveRefSym(DirectiveID);
449 }
450 return true;
451 }
452
ParseOperand(OperandVector & Operands)453 bool MSP430AsmParser::ParseOperand(OperandVector &Operands) {
454 switch (getLexer().getKind()) {
455 default: return true;
456 case AsmToken::Identifier: {
457 // try rN
458 unsigned RegNo;
459 SMLoc StartLoc, EndLoc;
460 if (!ParseRegister(RegNo, StartLoc, EndLoc)) {
461 Operands.push_back(MSP430Operand::CreateReg(RegNo, StartLoc, EndLoc));
462 return false;
463 }
464 LLVM_FALLTHROUGH;
465 }
466 case AsmToken::Integer:
467 case AsmToken::Plus:
468 case AsmToken::Minus: {
469 SMLoc StartLoc = getParser().getTok().getLoc();
470 const MCExpr *Val;
471 // Try constexpr[(rN)]
472 if (!getParser().parseExpression(Val)) {
473 unsigned RegNo = MSP430::PC;
474 SMLoc EndLoc = getParser().getTok().getLoc();
475 // Try (rN)
476 if (getLexer().getKind() == AsmToken::LParen) {
477 getLexer().Lex(); // Eat '('
478 SMLoc RegStartLoc;
479 if (ParseRegister(RegNo, RegStartLoc, EndLoc))
480 return true;
481 if (getLexer().getKind() != AsmToken::RParen)
482 return true;
483 EndLoc = getParser().getTok().getEndLoc();
484 getLexer().Lex(); // Eat ')'
485 }
486 Operands.push_back(MSP430Operand::CreateMem(RegNo, Val, StartLoc,
487 EndLoc));
488 return false;
489 }
490 return true;
491 }
492 case AsmToken::Amp: {
493 // Try &constexpr
494 SMLoc StartLoc = getParser().getTok().getLoc();
495 getLexer().Lex(); // Eat '&'
496 const MCExpr *Val;
497 if (!getParser().parseExpression(Val)) {
498 SMLoc EndLoc = getParser().getTok().getLoc();
499 Operands.push_back(MSP430Operand::CreateMem(MSP430::SR, Val, StartLoc,
500 EndLoc));
501 return false;
502 }
503 return true;
504 }
505 case AsmToken::At: {
506 // Try @rN[+]
507 SMLoc StartLoc = getParser().getTok().getLoc();
508 getLexer().Lex(); // Eat '@'
509 unsigned RegNo;
510 SMLoc RegStartLoc, EndLoc;
511 if (ParseRegister(RegNo, RegStartLoc, EndLoc))
512 return true;
513 if (getLexer().getKind() == AsmToken::Plus) {
514 Operands.push_back(MSP430Operand::CreatePostIndReg(RegNo, StartLoc, EndLoc));
515 getLexer().Lex(); // Eat '+'
516 return false;
517 }
518 if (Operands.size() > 1) // Emulate @rd in destination position as 0(rd)
519 Operands.push_back(MSP430Operand::CreateMem(RegNo,
520 MCConstantExpr::create(0, getContext()), StartLoc, EndLoc));
521 else
522 Operands.push_back(MSP430Operand::CreateIndReg(RegNo, StartLoc, EndLoc));
523 return false;
524 }
525 case AsmToken::Hash:
526 // Try #constexpr
527 SMLoc StartLoc = getParser().getTok().getLoc();
528 getLexer().Lex(); // Eat '#'
529 const MCExpr *Val;
530 if (!getParser().parseExpression(Val)) {
531 SMLoc EndLoc = getParser().getTok().getLoc();
532 Operands.push_back(MSP430Operand::CreateImm(Val, StartLoc, EndLoc));
533 return false;
534 }
535 return true;
536 }
537 }
538
ParseLiteralValues(unsigned Size,SMLoc L)539 bool MSP430AsmParser::ParseLiteralValues(unsigned Size, SMLoc L) {
540 auto parseOne = [&]() -> bool {
541 const MCExpr *Value;
542 if (getParser().parseExpression(Value))
543 return true;
544 getParser().getStreamer().emitValue(Value, Size, L);
545 return false;
546 };
547 return (parseMany(parseOne));
548 }
549
LLVMInitializeMSP430AsmParser()550 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMSP430AsmParser() {
551 RegisterMCAsmParser<MSP430AsmParser> X(getTheMSP430Target());
552 }
553
554 #define GET_REGISTER_MATCHER
555 #define GET_MATCHER_IMPLEMENTATION
556 #include "MSP430GenAsmMatcher.inc"
557
convertGR16ToGR8(unsigned Reg)558 static unsigned convertGR16ToGR8(unsigned Reg) {
559 switch (Reg) {
560 default:
561 llvm_unreachable("Unknown GR16 register");
562 case MSP430::PC: return MSP430::PCB;
563 case MSP430::SP: return MSP430::SPB;
564 case MSP430::SR: return MSP430::SRB;
565 case MSP430::CG: return MSP430::CGB;
566 case MSP430::R4: return MSP430::R4B;
567 case MSP430::R5: return MSP430::R5B;
568 case MSP430::R6: return MSP430::R6B;
569 case MSP430::R7: return MSP430::R7B;
570 case MSP430::R8: return MSP430::R8B;
571 case MSP430::R9: return MSP430::R9B;
572 case MSP430::R10: return MSP430::R10B;
573 case MSP430::R11: return MSP430::R11B;
574 case MSP430::R12: return MSP430::R12B;
575 case MSP430::R13: return MSP430::R13B;
576 case MSP430::R14: return MSP430::R14B;
577 case MSP430::R15: return MSP430::R15B;
578 }
579 }
580
validateTargetOperandClass(MCParsedAsmOperand & AsmOp,unsigned Kind)581 unsigned MSP430AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
582 unsigned Kind) {
583 MSP430Operand &Op = static_cast<MSP430Operand &>(AsmOp);
584
585 if (!Op.isReg())
586 return Match_InvalidOperand;
587
588 unsigned Reg = Op.getReg();
589 bool isGR16 =
590 MSP430MCRegisterClasses[MSP430::GR16RegClassID].contains(Reg);
591
592 if (isGR16 && (Kind == MCK_GR8)) {
593 Op.setReg(convertGR16ToGR8(Reg));
594 return Match_Success;
595 }
596
597 return Match_InvalidOperand;
598 }
599