1 //===- MSP430AsmParser.cpp - Parse MSP430 assembly to MCInst instructions -===//
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
7 //===----------------------------------------------------------------------===//
10 #include "MSP430RegisterInfo.h"
11 #include "MCTargetDesc/MSP430MCTargetDesc.h"
12 #include "TargetInfo/MSP430TargetInfo.h"
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/Support/Debug.h"
27 #include "llvm/Support/MathExtras.h"
28 #include "llvm/Support/TargetRegistry.h"
30 #define DEBUG_TYPE "msp430-asm-parser"
36 /// Parses MSP430 assembly from a stream.
37 class MSP430AsmParser
: public MCTargetAsmParser
{
38 const MCSubtargetInfo
&STI
;
40 const MCRegisterInfo
*MRI
;
42 bool MatchAndEmitInstruction(SMLoc IDLoc
, unsigned &Opcode
,
43 OperandVector
&Operands
, MCStreamer
&Out
,
45 bool MatchingInlineAsm
) override
;
47 bool ParseRegister(unsigned &RegNo
, SMLoc
&StartLoc
, SMLoc
&EndLoc
) override
;
48 OperandMatchResultTy
tryParseRegister(unsigned &RegNo
, SMLoc
&StartLoc
,
49 SMLoc
&EndLoc
) override
;
51 bool ParseInstruction(ParseInstructionInfo
&Info
, StringRef Name
,
52 SMLoc NameLoc
, OperandVector
&Operands
) override
;
54 bool ParseDirective(AsmToken DirectiveID
) override
;
55 bool ParseDirectiveRefSym(AsmToken DirectiveID
);
57 unsigned validateTargetOperandClass(MCParsedAsmOperand
&Op
,
58 unsigned Kind
) override
;
60 bool parseJccInstruction(ParseInstructionInfo
&Info
, StringRef Name
,
61 SMLoc NameLoc
, OperandVector
&Operands
);
63 bool ParseOperand(OperandVector
&Operands
);
65 bool ParseLiteralValues(unsigned Size
, SMLoc L
);
67 MCAsmParser
&getParser() const { return Parser
; }
68 MCAsmLexer
&getLexer() const { return Parser
.getLexer(); }
70 /// @name Auto-generated Matcher Functions
73 #define GET_ASSEMBLER_HEADER
74 #include "MSP430GenAsmMatcher.inc"
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();
85 setAvailableFeatures(ComputeAvailableFeatures(STI
.getFeatureBits()));
89 /// A parsed MSP430 assembly operand.
90 class MSP430Operand
: public MCParsedAsmOperand
{
91 typedef MCParsedAsmOperand Base
;
104 const MCExpr
*Offset
;
116 MSP430Operand(StringRef Tok
, SMLoc
const &S
)
117 : Base(), Kind(k_Tok
), Tok(Tok
), Start(S
), End(S
) {}
118 MSP430Operand(KindTy Kind
, unsigned Reg
, SMLoc
const &S
, SMLoc
const &E
)
119 : Base(), Kind(Kind
), Reg(Reg
), Start(S
), End(E
) {}
120 MSP430Operand(MCExpr
const *Imm
, SMLoc
const &S
, SMLoc
const &E
)
121 : Base(), Kind(k_Imm
), Imm(Imm
), Start(S
), End(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
) {}
125 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!");
130 Inst
.addOperand(MCOperand::createReg(Reg
));
133 void addExprOperand(MCInst
&Inst
, const MCExpr
*Expr
) const {
134 // Add as immediate when possible
136 Inst
.addOperand(MCOperand::createImm(0));
137 else if (const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(Expr
))
138 Inst
.addOperand(MCOperand::createImm(CE
->getValue()));
140 Inst
.addOperand(MCOperand::createExpr(Expr
));
143 void addImmOperands(MCInst
&Inst
, unsigned N
) const {
144 assert(Kind
== k_Imm
&& "Unexpected operand kind");
145 assert(N
== 1 && "Invalid number of operands!");
147 addExprOperand(Inst
, Imm
);
150 void addMemOperands(MCInst
&Inst
, unsigned N
) const {
151 assert(Kind
== k_Mem
&& "Unexpected operand kind");
152 assert(N
== 2 && "Invalid number of operands");
154 Inst
.addOperand(MCOperand::createReg(Mem
.Reg
));
155 addExprOperand(Inst
, Mem
.Offset
);
158 bool isReg() const override
{ return Kind
== k_Reg
; }
159 bool isImm() const override
{ return Kind
== k_Imm
; }
160 bool isToken() const override
{ return Kind
== k_Tok
; }
161 bool isMem() const override
{ return Kind
== k_Mem
; }
162 bool isIndReg() const { return Kind
== k_IndReg
; }
163 bool isPostIndReg() const { return Kind
== k_PostIndReg
; }
165 bool isCGImm() const {
170 if (!Imm
->evaluateAsAbsolute(Val
))
173 if (Val
== 0 || Val
== 1 || Val
== 2 || Val
== 4 || Val
== 8 || Val
== -1)
179 StringRef
getToken() const {
180 assert(Kind
== k_Tok
&& "Invalid access!");
184 unsigned getReg() const override
{
185 assert(Kind
== k_Reg
&& "Invalid access!");
189 void setReg(unsigned RegNo
) {
190 assert(Kind
== k_Reg
&& "Invalid access!");
194 static std::unique_ptr
<MSP430Operand
> CreateToken(StringRef Str
, SMLoc S
) {
195 return std::make_unique
<MSP430Operand
>(Str
, S
);
198 static std::unique_ptr
<MSP430Operand
> CreateReg(unsigned RegNum
, SMLoc S
,
200 return std::make_unique
<MSP430Operand
>(k_Reg
, RegNum
, S
, E
);
203 static std::unique_ptr
<MSP430Operand
> CreateImm(const MCExpr
*Val
, SMLoc S
,
205 return std::make_unique
<MSP430Operand
>(Val
, S
, E
);
208 static std::unique_ptr
<MSP430Operand
> CreateMem(unsigned RegNum
,
211 return std::make_unique
<MSP430Operand
>(RegNum
, Val
, S
, E
);
214 static std::unique_ptr
<MSP430Operand
> CreateIndReg(unsigned RegNum
, SMLoc S
,
216 return std::make_unique
<MSP430Operand
>(k_IndReg
, RegNum
, S
, E
);
219 static std::unique_ptr
<MSP430Operand
> CreatePostIndReg(unsigned RegNum
, SMLoc S
,
221 return std::make_unique
<MSP430Operand
>(k_PostIndReg
, RegNum
, S
, E
);
224 SMLoc
getStartLoc() const override
{ return Start
; }
225 SMLoc
getEndLoc() const override
{ return End
; }
227 void print(raw_ostream
&O
) const override
{
230 O
<< "Token " << Tok
;
233 O
<< "Register " << Reg
;
236 O
<< "Immediate " << *Imm
;
240 O
<< *Mem
.Offset
<< "(" << Reg
<< ")";
243 O
<< "RegInd " << Reg
;
246 O
<< "PostInc " << Reg
;
251 } // end anonymous namespace
253 bool MSP430AsmParser::MatchAndEmitInstruction(SMLoc Loc
, unsigned &Opcode
,
254 OperandVector
&Operands
,
257 bool MatchingInlineAsm
) {
259 unsigned MatchResult
=
260 MatchInstructionImpl(Operands
, Inst
, ErrorInfo
, MatchingInlineAsm
);
262 switch (MatchResult
) {
265 Out
.emitInstruction(Inst
, STI
);
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");
275 ErrorLoc
= ((MSP430Operand
&)*Operands
[ErrorInfo
]).getStartLoc();
276 if (ErrorLoc
== SMLoc())
279 return Error(ErrorLoc
, "invalid operand for instruction");
286 // Auto-generated by TableGen
287 static unsigned MatchRegisterName(StringRef Name
);
288 static unsigned MatchRegisterAltName(StringRef Name
);
290 bool MSP430AsmParser::ParseRegister(unsigned &RegNo
, SMLoc
&StartLoc
,
292 switch (tryParseRegister(RegNo
, StartLoc
, EndLoc
)) {
293 case MatchOperand_ParseFail
:
294 return Error(StartLoc
, "invalid register name");
295 case MatchOperand_Success
:
297 case MatchOperand_NoMatch
:
301 llvm_unreachable("unknown match result type");
304 OperandMatchResultTy
MSP430AsmParser::tryParseRegister(unsigned &RegNo
,
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
;
316 AsmToken
const &T
= getParser().getTok();
317 StartLoc
= T
.getLoc();
318 EndLoc
= T
.getEndLoc();
319 getLexer().Lex(); // eat register token
321 return MatchOperand_Success
;
324 return MatchOperand_ParseFail
;
327 bool MSP430AsmParser::parseJccInstruction(ParseInstructionInfo
&Info
,
328 StringRef Name
, SMLoc NameLoc
,
329 OperandVector
&Operands
) {
330 if (!Name
.startswith_insensitive("j"))
333 auto CC
= Name
.drop_front().lower();
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
;
344 CondCode
= MSP430CC::COND_N
;
346 CondCode
= MSP430CC::COND_GE
;
348 CondCode
= MSP430CC::COND_L
;
350 CondCode
= MSP430CC::COND_NONE
;
352 return Error(NameLoc
, "unknown instruction");
354 if (CondCode
== (unsigned)MSP430CC::COND_NONE
)
355 Operands
.push_back(MSP430Operand::CreateToken("jmp", NameLoc
));
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()));
362 // Skip optional '$' sign.
363 if (getLexer().getKind() == AsmToken::Dollar
)
364 getLexer().Lex(); // Eat '$'
367 SMLoc ExprLoc
= getLexer().getLoc();
368 if (getParser().parseExpression(Val
))
369 return Error(ExprLoc
, "expected expression operand");
372 if (Val
->evaluateAsAbsolute(Res
))
373 if (Res
< -512 || Res
> 511)
374 return Error(ExprLoc
, "invalid jump offset");
376 Operands
.push_back(MSP430Operand::CreateImm(Val
, ExprLoc
,
377 getLexer().getLoc()));
379 if (getLexer().isNot(AsmToken::EndOfStatement
)) {
380 SMLoc Loc
= getLexer().getLoc();
381 getParser().eatToEndOfStatement();
382 return Error(Loc
, "unexpected token");
385 getParser().Lex(); // Consume the EndOfStatement.
389 bool MSP430AsmParser::ParseInstruction(ParseInstructionInfo
&Info
,
390 StringRef Name
, SMLoc NameLoc
,
391 OperandVector
&Operands
) {
393 if (Name
.endswith_insensitive(".w"))
394 Name
= Name
.drop_back(2);
396 if (!parseJccInstruction(Info
, Name
, NameLoc
, Operands
))
399 // First operand is instruction mnemonic
400 Operands
.push_back(MSP430Operand::CreateToken(Name
, NameLoc
));
402 // If there are no more operands, then finish
403 if (getLexer().is(AsmToken::EndOfStatement
))
406 // Parse first operand
407 if (ParseOperand(Operands
))
410 // Parse second operand if any
411 if (getLexer().is(AsmToken::Comma
)) {
412 getLexer().Lex(); // Eat ','
413 if (ParseOperand(Operands
))
417 if (getLexer().isNot(AsmToken::EndOfStatement
)) {
418 SMLoc Loc
= getLexer().getLoc();
419 getParser().eatToEndOfStatement();
420 return Error(Loc
, "unexpected token");
423 getParser().Lex(); // Consume the EndOfStatement.
427 bool MSP430AsmParser::ParseDirectiveRefSym(AsmToken DirectiveID
) {
429 if (getParser().parseIdentifier(Name
))
430 return TokError("expected identifier in directive");
432 MCSymbol
*Sym
= getContext().getOrCreateSymbol(Name
);
433 getStreamer().emitSymbolAttribute(Sym
, MCSA_Global
);
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
);
451 bool MSP430AsmParser::ParseOperand(OperandVector
&Operands
) {
452 switch (getLexer().getKind()) {
453 default: return true;
454 case AsmToken::Identifier
: {
457 SMLoc StartLoc
, EndLoc
;
458 if (!ParseRegister(RegNo
, StartLoc
, EndLoc
)) {
459 Operands
.push_back(MSP430Operand::CreateReg(RegNo
, StartLoc
, EndLoc
));
464 case AsmToken::Integer
:
466 case AsmToken::Minus
: {
467 SMLoc StartLoc
= getParser().getTok().getLoc();
469 // Try constexpr[(rN)]
470 if (!getParser().parseExpression(Val
)) {
471 unsigned RegNo
= MSP430::PC
;
472 SMLoc EndLoc
= getParser().getTok().getLoc();
474 if (getLexer().getKind() == AsmToken::LParen
) {
475 getLexer().Lex(); // Eat '('
477 if (ParseRegister(RegNo
, RegStartLoc
, EndLoc
))
479 if (getLexer().getKind() != AsmToken::RParen
)
481 EndLoc
= getParser().getTok().getEndLoc();
482 getLexer().Lex(); // Eat ')'
484 Operands
.push_back(MSP430Operand::CreateMem(RegNo
, Val
, StartLoc
,
490 case AsmToken::Amp
: {
492 SMLoc StartLoc
= getParser().getTok().getLoc();
493 getLexer().Lex(); // Eat '&'
495 if (!getParser().parseExpression(Val
)) {
496 SMLoc EndLoc
= getParser().getTok().getLoc();
497 Operands
.push_back(MSP430Operand::CreateMem(MSP430::SR
, Val
, StartLoc
,
505 SMLoc StartLoc
= getParser().getTok().getLoc();
506 getLexer().Lex(); // Eat '@'
508 SMLoc RegStartLoc
, EndLoc
;
509 if (ParseRegister(RegNo
, RegStartLoc
, EndLoc
))
511 if (getLexer().getKind() == AsmToken::Plus
) {
512 Operands
.push_back(MSP430Operand::CreatePostIndReg(RegNo
, StartLoc
, EndLoc
));
513 getLexer().Lex(); // Eat '+'
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
));
520 Operands
.push_back(MSP430Operand::CreateIndReg(RegNo
, StartLoc
, EndLoc
));
525 SMLoc StartLoc
= getParser().getTok().getLoc();
526 getLexer().Lex(); // Eat '#'
528 if (!getParser().parseExpression(Val
)) {
529 SMLoc EndLoc
= getParser().getTok().getLoc();
530 Operands
.push_back(MSP430Operand::CreateImm(Val
, StartLoc
, EndLoc
));
537 bool MSP430AsmParser::ParseLiteralValues(unsigned Size
, SMLoc L
) {
538 auto parseOne
= [&]() -> bool {
540 if (getParser().parseExpression(Value
))
542 getParser().getStreamer().emitValue(Value
, Size
, L
);
545 return (parseMany(parseOne
));
548 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeMSP430AsmParser() {
549 RegisterMCAsmParser
<MSP430AsmParser
> X(getTheMSP430Target());
552 #define GET_REGISTER_MATCHER
553 #define GET_MATCHER_IMPLEMENTATION
554 #include "MSP430GenAsmMatcher.inc"
556 static unsigned convertGR16ToGR8(unsigned Reg
) {
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
;
579 unsigned MSP430AsmParser::validateTargetOperandClass(MCParsedAsmOperand
&AsmOp
,
581 MSP430Operand
&Op
= static_cast<MSP430Operand
&>(AsmOp
);
584 return Match_InvalidOperand
;
586 unsigned Reg
= Op
.getReg();
588 MSP430MCRegisterClasses
[MSP430::GR16RegClassID
].contains(Reg
);
590 if (isGR16
&& (Kind
== MCK_GR8
)) {
591 Op
.setReg(convertGR16ToGR8(Reg
));
592 return Match_Success
;
595 return Match_InvalidOperand
;