Coverage Report

Created: 2024-01-17 10:31

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