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/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"
31 #define DEBUG_TYPE "msp430-asm-parser"
37 /// Parses MSP430 assembly from a stream.
38 class MSP430AsmParser
: public MCTargetAsmParser
{
39 const MCSubtargetInfo
&STI
;
41 const MCRegisterInfo
*MRI
;
43 bool MatchAndEmitInstruction(SMLoc IDLoc
, unsigned &Opcode
,
44 OperandVector
&Operands
, MCStreamer
&Out
,
46 bool MatchingInlineAsm
) override
;
48 bool parseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
, SMLoc
&EndLoc
) override
;
49 ParseStatus
tryParseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
,
50 SMLoc
&EndLoc
) override
;
52 bool ParseInstruction(ParseInstructionInfo
&Info
, StringRef Name
,
53 SMLoc NameLoc
, OperandVector
&Operands
) override
;
55 ParseStatus
parseDirective(AsmToken DirectiveID
) override
;
56 bool ParseDirectiveRefSym(AsmToken DirectiveID
);
58 unsigned validateTargetOperandClass(MCParsedAsmOperand
&Op
,
59 unsigned Kind
) override
;
61 bool parseJccInstruction(ParseInstructionInfo
&Info
, StringRef Name
,
62 SMLoc NameLoc
, OperandVector
&Operands
);
64 bool ParseOperand(OperandVector
&Operands
);
66 bool ParseLiteralValues(unsigned Size
, SMLoc L
);
68 MCAsmParser
&getParser() const { return Parser
; }
69 MCAsmLexer
&getLexer() const { return Parser
.getLexer(); }
71 /// @name Auto-generated Matcher Functions
74 #define GET_ASSEMBLER_HEADER
75 #include "MSP430GenAsmMatcher.inc"
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();
86 setAvailableFeatures(ComputeAvailableFeatures(STI
.getFeatureBits()));
90 /// A parsed MSP430 assembly operand.
91 class MSP430Operand
: public MCParsedAsmOperand
{
92 typedef MCParsedAsmOperand Base
;
105 const MCExpr
*Offset
;
117 MSP430Operand(StringRef Tok
, SMLoc
const &S
)
118 : Kind(k_Tok
), Tok(Tok
), Start(S
), End(S
) {}
119 MSP430Operand(KindTy Kind
, unsigned Reg
, SMLoc
const &S
, SMLoc
const &E
)
120 : Kind(Kind
), Reg(Reg
), Start(S
), End(E
) {}
121 MSP430Operand(MCExpr
const *Imm
, SMLoc
const &S
, SMLoc
const &E
)
122 : Kind(k_Imm
), Imm(Imm
), Start(S
), End(E
) {}
123 MSP430Operand(unsigned Reg
, MCExpr
const *Expr
, SMLoc
const &S
,
125 : Kind(k_Mem
), Mem({Reg
, Expr
}), Start(S
), End(E
) {}
127 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!");
132 Inst
.addOperand(MCOperand::createReg(Reg
));
135 void addExprOperand(MCInst
&Inst
, const MCExpr
*Expr
) const {
136 // Add as immediate when possible
138 Inst
.addOperand(MCOperand::createImm(0));
139 else if (const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(Expr
))
140 Inst
.addOperand(MCOperand::createImm(CE
->getValue()));
142 Inst
.addOperand(MCOperand::createExpr(Expr
));
145 void addImmOperands(MCInst
&Inst
, unsigned N
) const {
146 assert(Kind
== k_Imm
&& "Unexpected operand kind");
147 assert(N
== 1 && "Invalid number of operands!");
149 addExprOperand(Inst
, Imm
);
152 void addMemOperands(MCInst
&Inst
, unsigned N
) const {
153 assert(Kind
== k_Mem
&& "Unexpected operand kind");
154 assert(N
== 2 && "Invalid number of operands");
156 Inst
.addOperand(MCOperand::createReg(Mem
.Reg
));
157 addExprOperand(Inst
, Mem
.Offset
);
160 bool isReg() const override
{ return Kind
== k_Reg
; }
161 bool isImm() const override
{ return Kind
== k_Imm
; }
162 bool isToken() const override
{ return Kind
== k_Tok
; }
163 bool isMem() const override
{ return Kind
== k_Mem
; }
164 bool isIndReg() const { return Kind
== k_IndReg
; }
165 bool isPostIndReg() const { return Kind
== k_PostIndReg
; }
167 bool isCGImm() const {
172 if (!Imm
->evaluateAsAbsolute(Val
))
175 if (Val
== 0 || Val
== 1 || Val
== 2 || Val
== 4 || Val
== 8 || Val
== -1)
181 StringRef
getToken() const {
182 assert(Kind
== k_Tok
&& "Invalid access!");
186 unsigned getReg() const override
{
187 assert(Kind
== k_Reg
&& "Invalid access!");
191 void setReg(unsigned RegNo
) {
192 assert(Kind
== k_Reg
&& "Invalid access!");
196 static std::unique_ptr
<MSP430Operand
> CreateToken(StringRef Str
, SMLoc S
) {
197 return std::make_unique
<MSP430Operand
>(Str
, S
);
200 static std::unique_ptr
<MSP430Operand
> CreateReg(unsigned RegNum
, SMLoc S
,
202 return std::make_unique
<MSP430Operand
>(k_Reg
, RegNum
, S
, E
);
205 static std::unique_ptr
<MSP430Operand
> CreateImm(const MCExpr
*Val
, SMLoc S
,
207 return std::make_unique
<MSP430Operand
>(Val
, S
, E
);
210 static std::unique_ptr
<MSP430Operand
> CreateMem(unsigned RegNum
,
213 return std::make_unique
<MSP430Operand
>(RegNum
, Val
, S
, E
);
216 static std::unique_ptr
<MSP430Operand
> CreateIndReg(unsigned RegNum
, SMLoc S
,
218 return std::make_unique
<MSP430Operand
>(k_IndReg
, RegNum
, S
, E
);
221 static std::unique_ptr
<MSP430Operand
> CreatePostIndReg(unsigned RegNum
, SMLoc S
,
223 return std::make_unique
<MSP430Operand
>(k_PostIndReg
, RegNum
, S
, E
);
226 SMLoc
getStartLoc() const override
{ return Start
; }
227 SMLoc
getEndLoc() const override
{ return End
; }
229 void print(raw_ostream
&O
) const override
{
232 O
<< "Token " << Tok
;
235 O
<< "Register " << Reg
;
238 O
<< "Immediate " << *Imm
;
242 O
<< *Mem
.Offset
<< "(" << Reg
<< ")";
245 O
<< "RegInd " << Reg
;
248 O
<< "PostInc " << Reg
;
253 } // end anonymous namespace
255 bool MSP430AsmParser::MatchAndEmitInstruction(SMLoc Loc
, unsigned &Opcode
,
256 OperandVector
&Operands
,
259 bool MatchingInlineAsm
) {
261 unsigned MatchResult
=
262 MatchInstructionImpl(Operands
, Inst
, ErrorInfo
, MatchingInlineAsm
);
264 switch (MatchResult
) {
267 Out
.emitInstruction(Inst
, STI
);
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");
277 ErrorLoc
= ((MSP430Operand
&)*Operands
[ErrorInfo
]).getStartLoc();
278 if (ErrorLoc
== SMLoc())
281 return Error(ErrorLoc
, "invalid operand for instruction");
288 // Auto-generated by TableGen
289 static unsigned MatchRegisterName(StringRef Name
);
290 static unsigned MatchRegisterAltName(StringRef Name
);
292 bool MSP430AsmParser::parseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
,
294 ParseStatus Res
= tryParseRegister(Reg
, StartLoc
, EndLoc
);
296 return Error(StartLoc
, "invalid register name");
302 llvm_unreachable("unknown parse status");
305 ParseStatus
MSP430AsmParser::tryParseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
,
307 if (getLexer().getKind() == AsmToken::Identifier
) {
308 auto Name
= getLexer().getTok().getIdentifier().lower();
309 Reg
= MatchRegisterName(Name
);
310 if (Reg
== MSP430::NoRegister
) {
311 Reg
= MatchRegisterAltName(Name
);
312 if (Reg
== MSP430::NoRegister
)
313 return ParseStatus::NoMatch
;
316 AsmToken
const &T
= getParser().getTok();
317 StartLoc
= T
.getLoc();
318 EndLoc
= T
.getEndLoc();
319 getLexer().Lex(); // eat register token
321 return ParseStatus::Success
;
324 return ParseStatus::Failure
;
327 bool MSP430AsmParser::parseJccInstruction(ParseInstructionInfo
&Info
,
328 StringRef Name
, SMLoc NameLoc
,
329 OperandVector
&Operands
) {
330 if (!Name
.starts_with_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 (void)parseOptionalToken(AsmToken::Dollar
);
366 SMLoc ExprLoc
= getLexer().getLoc();
367 if (getParser().parseExpression(Val
))
368 return Error(ExprLoc
, "expected expression operand");
371 if (Val
->evaluateAsAbsolute(Res
))
372 if (Res
< -512 || Res
> 511)
373 return Error(ExprLoc
, "invalid jump offset");
375 Operands
.push_back(MSP430Operand::CreateImm(Val
, ExprLoc
,
376 getLexer().getLoc()));
378 if (getLexer().isNot(AsmToken::EndOfStatement
)) {
379 SMLoc Loc
= getLexer().getLoc();
380 getParser().eatToEndOfStatement();
381 return Error(Loc
, "unexpected token");
384 getParser().Lex(); // Consume the EndOfStatement.
388 bool MSP430AsmParser::ParseInstruction(ParseInstructionInfo
&Info
,
389 StringRef Name
, SMLoc NameLoc
,
390 OperandVector
&Operands
) {
392 if (Name
.ends_with_insensitive(".w"))
393 Name
= Name
.drop_back(2);
395 if (!parseJccInstruction(Info
, Name
, NameLoc
, Operands
))
398 // First operand is instruction mnemonic
399 Operands
.push_back(MSP430Operand::CreateToken(Name
, NameLoc
));
401 // If there are no more operands, then finish
402 if (getLexer().is(AsmToken::EndOfStatement
))
405 // Parse first operand
406 if (ParseOperand(Operands
))
409 // Parse second operand if any
410 if (parseOptionalToken(AsmToken::Comma
) && ParseOperand(Operands
))
413 if (getLexer().isNot(AsmToken::EndOfStatement
)) {
414 SMLoc Loc
= getLexer().getLoc();
415 getParser().eatToEndOfStatement();
416 return Error(Loc
, "unexpected token");
419 getParser().Lex(); // Consume the EndOfStatement.
423 bool MSP430AsmParser::ParseDirectiveRefSym(AsmToken DirectiveID
) {
425 if (getParser().parseIdentifier(Name
))
426 return TokError("expected identifier in directive");
428 MCSymbol
*Sym
= getContext().getOrCreateSymbol(Name
);
429 getStreamer().emitSymbolAttribute(Sym
, MCSA_Global
);
433 ParseStatus
MSP430AsmParser::parseDirective(AsmToken DirectiveID
) {
434 StringRef IDVal
= DirectiveID
.getIdentifier();
435 if (IDVal
.lower() == ".long")
436 return ParseLiteralValues(4, DirectiveID
.getLoc());
437 if (IDVal
.lower() == ".word" || IDVal
.lower() == ".short")
438 return ParseLiteralValues(2, DirectiveID
.getLoc());
439 if (IDVal
.lower() == ".byte")
440 return ParseLiteralValues(1, DirectiveID
.getLoc());
441 if (IDVal
.lower() == ".refsym")
442 return ParseDirectiveRefSym(DirectiveID
);
443 return ParseStatus::NoMatch
;
446 bool MSP430AsmParser::ParseOperand(OperandVector
&Operands
) {
447 switch (getLexer().getKind()) {
448 default: return true;
449 case AsmToken::Identifier
: {
452 SMLoc StartLoc
, EndLoc
;
453 if (!parseRegister(RegNo
, StartLoc
, EndLoc
)) {
454 Operands
.push_back(MSP430Operand::CreateReg(RegNo
, StartLoc
, EndLoc
));
459 case AsmToken::Integer
:
461 case AsmToken::Minus
: {
462 SMLoc StartLoc
= getParser().getTok().getLoc();
464 // Try constexpr[(rN)]
465 if (!getParser().parseExpression(Val
)) {
466 MCRegister RegNo
= MSP430::PC
;
467 SMLoc EndLoc
= getParser().getTok().getLoc();
469 if (parseOptionalToken(AsmToken::LParen
)) {
471 if (parseRegister(RegNo
, RegStartLoc
, EndLoc
))
473 EndLoc
= getParser().getTok().getEndLoc();
474 if (!parseOptionalToken(AsmToken::RParen
))
477 Operands
.push_back(MSP430Operand::CreateMem(RegNo
, Val
, StartLoc
,
483 case AsmToken::Amp
: {
485 SMLoc StartLoc
= getParser().getTok().getLoc();
486 getLexer().Lex(); // Eat '&'
488 if (!getParser().parseExpression(Val
)) {
489 SMLoc EndLoc
= getParser().getTok().getLoc();
490 Operands
.push_back(MSP430Operand::CreateMem(MSP430::SR
, Val
, StartLoc
,
498 SMLoc StartLoc
= getParser().getTok().getLoc();
499 getLexer().Lex(); // Eat '@'
501 SMLoc RegStartLoc
, EndLoc
;
502 if (parseRegister(RegNo
, RegStartLoc
, EndLoc
))
504 if (parseOptionalToken(AsmToken::Plus
)) {
505 Operands
.push_back(MSP430Operand::CreatePostIndReg(RegNo
, StartLoc
, EndLoc
));
508 if (Operands
.size() > 1) // Emulate @rd in destination position as 0(rd)
509 Operands
.push_back(MSP430Operand::CreateMem(RegNo
,
510 MCConstantExpr::create(0, getContext()), StartLoc
, EndLoc
));
512 Operands
.push_back(MSP430Operand::CreateIndReg(RegNo
, StartLoc
, EndLoc
));
517 SMLoc StartLoc
= getParser().getTok().getLoc();
518 getLexer().Lex(); // Eat '#'
520 if (!getParser().parseExpression(Val
)) {
521 SMLoc EndLoc
= getParser().getTok().getLoc();
522 Operands
.push_back(MSP430Operand::CreateImm(Val
, StartLoc
, EndLoc
));
529 bool MSP430AsmParser::ParseLiteralValues(unsigned Size
, SMLoc L
) {
530 auto parseOne
= [&]() -> bool {
532 if (getParser().parseExpression(Value
))
534 getParser().getStreamer().emitValue(Value
, Size
, L
);
537 return (parseMany(parseOne
));
540 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeMSP430AsmParser() {
541 RegisterMCAsmParser
<MSP430AsmParser
> X(getTheMSP430Target());
544 #define GET_REGISTER_MATCHER
545 #define GET_MATCHER_IMPLEMENTATION
546 #include "MSP430GenAsmMatcher.inc"
548 static unsigned convertGR16ToGR8(unsigned Reg
) {
551 llvm_unreachable("Unknown GR16 register");
552 case MSP430::PC
: return MSP430::PCB
;
553 case MSP430::SP
: return MSP430::SPB
;
554 case MSP430::SR
: return MSP430::SRB
;
555 case MSP430::CG
: return MSP430::CGB
;
556 case MSP430::R4
: return MSP430::R4B
;
557 case MSP430::R5
: return MSP430::R5B
;
558 case MSP430::R6
: return MSP430::R6B
;
559 case MSP430::R7
: return MSP430::R7B
;
560 case MSP430::R8
: return MSP430::R8B
;
561 case MSP430::R9
: return MSP430::R9B
;
562 case MSP430::R10
: return MSP430::R10B
;
563 case MSP430::R11
: return MSP430::R11B
;
564 case MSP430::R12
: return MSP430::R12B
;
565 case MSP430::R13
: return MSP430::R13B
;
566 case MSP430::R14
: return MSP430::R14B
;
567 case MSP430::R15
: return MSP430::R15B
;
571 unsigned MSP430AsmParser::validateTargetOperandClass(MCParsedAsmOperand
&AsmOp
,
573 MSP430Operand
&Op
= static_cast<MSP430Operand
&>(AsmOp
);
576 return Match_InvalidOperand
;
578 unsigned Reg
= Op
.getReg();
580 MSP430MCRegisterClasses
[MSP430::GR16RegClassID
].contains(Reg
);
582 if (isGR16
&& (Kind
== MCK_GR8
)) {
583 Op
.setReg(convertGR16ToGR8(Reg
));
584 return Match_Success
;
587 return Match_InvalidOperand
;