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/ADT/StringSwitch.h"
16 #include "llvm/MC/MCContext.h"
17 #include "llvm/MC/MCExpr.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/MC/MCInstBuilder.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/Support/Debug.h"
28 #include "llvm/Support/MathExtras.h"
29 #include "llvm/Support/TargetRegistry.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(unsigned &RegNo
, SMLoc
&StartLoc
, SMLoc
&EndLoc
) override
;
50 bool ParseInstruction(ParseInstructionInfo
&Info
, StringRef Name
,
51 SMLoc NameLoc
, OperandVector
&Operands
) override
;
53 bool ParseDirective(AsmToken DirectiveID
) override
;
54 bool ParseDirectiveRefSym(AsmToken DirectiveID
);
56 unsigned validateTargetOperandClass(MCParsedAsmOperand
&Op
,
57 unsigned Kind
) override
;
59 bool parseJccInstruction(ParseInstructionInfo
&Info
, StringRef Name
,
60 SMLoc NameLoc
, OperandVector
&Operands
);
62 bool ParseOperand(OperandVector
&Operands
);
64 bool ParseLiteralValues(unsigned Size
, SMLoc L
);
66 MCAsmParser
&getParser() const { return Parser
; }
67 MCAsmLexer
&getLexer() const { return Parser
.getLexer(); }
69 /// @name Auto-generated Matcher Functions
72 #define GET_ASSEMBLER_HEADER
73 #include "MSP430GenAsmMatcher.inc"
78 MSP430AsmParser(const MCSubtargetInfo
&STI
, MCAsmParser
&Parser
,
79 const MCInstrInfo
&MII
, const MCTargetOptions
&Options
)
80 : MCTargetAsmParser(Options
, STI
, MII
), STI(STI
), Parser(Parser
) {
81 MCAsmParserExtension::Initialize(Parser
);
82 MRI
= getContext().getRegisterInfo();
84 setAvailableFeatures(ComputeAvailableFeatures(STI
.getFeatureBits()));
88 /// A parsed MSP430 assembly operand.
89 class MSP430Operand
: public MCParsedAsmOperand
{
90 typedef MCParsedAsmOperand Base
;
103 const MCExpr
*Offset
;
115 MSP430Operand(StringRef Tok
, SMLoc
const &S
)
116 : Base(), Kind(k_Tok
), Tok(Tok
), Start(S
), End(S
) {}
117 MSP430Operand(KindTy Kind
, unsigned Reg
, SMLoc
const &S
, SMLoc
const &E
)
118 : Base(), Kind(Kind
), Reg(Reg
), Start(S
), End(E
) {}
119 MSP430Operand(MCExpr
const *Imm
, SMLoc
const &S
, SMLoc
const &E
)
120 : Base(), Kind(k_Imm
), Imm(Imm
), Start(S
), End(E
) {}
121 MSP430Operand(unsigned Reg
, MCExpr
const *Expr
, SMLoc
const &S
, SMLoc
const &E
)
122 : Base(), Kind(k_Mem
), Mem({Reg
, Expr
}), Start(S
), End(E
) {}
124 void addRegOperands(MCInst
&Inst
, unsigned N
) const {
125 assert((Kind
== k_Reg
|| Kind
== k_IndReg
|| Kind
== k_PostIndReg
) &&
126 "Unexpected operand kind");
127 assert(N
== 1 && "Invalid number of operands!");
129 Inst
.addOperand(MCOperand::createReg(Reg
));
132 void addExprOperand(MCInst
&Inst
, const MCExpr
*Expr
) const {
133 // Add as immediate when possible
135 Inst
.addOperand(MCOperand::createImm(0));
136 else if (const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(Expr
))
137 Inst
.addOperand(MCOperand::createImm(CE
->getValue()));
139 Inst
.addOperand(MCOperand::createExpr(Expr
));
142 void addImmOperands(MCInst
&Inst
, unsigned N
) const {
143 assert(Kind
== k_Imm
&& "Unexpected operand kind");
144 assert(N
== 1 && "Invalid number of operands!");
146 addExprOperand(Inst
, Imm
);
149 void addMemOperands(MCInst
&Inst
, unsigned N
) const {
150 assert(Kind
== k_Mem
&& "Unexpected operand kind");
151 assert(N
== 2 && "Invalid number of operands");
153 Inst
.addOperand(MCOperand::createReg(Mem
.Reg
));
154 addExprOperand(Inst
, Mem
.Offset
);
157 bool isReg() const { return Kind
== k_Reg
; }
158 bool isImm() const { return Kind
== k_Imm
; }
159 bool isToken() const { return Kind
== k_Tok
; }
160 bool isMem() const { return Kind
== k_Mem
; }
161 bool isIndReg() const { return Kind
== k_IndReg
; }
162 bool isPostIndReg() const { return Kind
== k_PostIndReg
; }
164 bool isCGImm() const {
169 if (!Imm
->evaluateAsAbsolute(Val
))
172 if (Val
== 0 || Val
== 1 || Val
== 2 || Val
== 4 || Val
== 8 || Val
== -1)
178 StringRef
getToken() const {
179 assert(Kind
== k_Tok
&& "Invalid access!");
183 unsigned getReg() const {
184 assert(Kind
== k_Reg
&& "Invalid access!");
188 void setReg(unsigned RegNo
) {
189 assert(Kind
== k_Reg
&& "Invalid access!");
193 static std::unique_ptr
<MSP430Operand
> CreateToken(StringRef Str
, SMLoc S
) {
194 return std::make_unique
<MSP430Operand
>(Str
, S
);
197 static std::unique_ptr
<MSP430Operand
> CreateReg(unsigned RegNum
, SMLoc S
,
199 return std::make_unique
<MSP430Operand
>(k_Reg
, RegNum
, S
, E
);
202 static std::unique_ptr
<MSP430Operand
> CreateImm(const MCExpr
*Val
, SMLoc S
,
204 return std::make_unique
<MSP430Operand
>(Val
, S
, E
);
207 static std::unique_ptr
<MSP430Operand
> CreateMem(unsigned RegNum
,
210 return std::make_unique
<MSP430Operand
>(RegNum
, Val
, S
, E
);
213 static std::unique_ptr
<MSP430Operand
> CreateIndReg(unsigned RegNum
, SMLoc S
,
215 return std::make_unique
<MSP430Operand
>(k_IndReg
, RegNum
, S
, E
);
218 static std::unique_ptr
<MSP430Operand
> CreatePostIndReg(unsigned RegNum
, SMLoc S
,
220 return std::make_unique
<MSP430Operand
>(k_PostIndReg
, RegNum
, S
, E
);
223 SMLoc
getStartLoc() const { return Start
; }
224 SMLoc
getEndLoc() const { return End
; }
226 virtual void print(raw_ostream
&O
) const {
229 O
<< "Token " << Tok
;
232 O
<< "Register " << Reg
;
235 O
<< "Immediate " << *Imm
;
239 O
<< *Mem
.Offset
<< "(" << Reg
<< ")";
242 O
<< "RegInd " << Reg
;
245 O
<< "PostInc " << Reg
;
250 } // end anonymous namespace
252 bool MSP430AsmParser::MatchAndEmitInstruction(SMLoc Loc
, unsigned &Opcode
,
253 OperandVector
&Operands
,
256 bool MatchingInlineAsm
) {
258 unsigned MatchResult
=
259 MatchInstructionImpl(Operands
, Inst
, ErrorInfo
, MatchingInlineAsm
);
261 switch (MatchResult
) {
264 Out
.EmitInstruction(Inst
, STI
);
266 case Match_MnemonicFail
:
267 return Error(Loc
, "invalid instruction mnemonic");
268 case Match_InvalidOperand
: {
269 SMLoc ErrorLoc
= Loc
;
270 if (ErrorInfo
!= ~0U) {
271 if (ErrorInfo
>= Operands
.size())
272 return Error(ErrorLoc
, "too few operands for instruction");
274 ErrorLoc
= ((MSP430Operand
&)*Operands
[ErrorInfo
]).getStartLoc();
275 if (ErrorLoc
== SMLoc())
278 return Error(ErrorLoc
, "invalid operand for instruction");
285 // Auto-generated by TableGen
286 static unsigned MatchRegisterName(StringRef Name
);
287 static unsigned MatchRegisterAltName(StringRef Name
);
289 bool MSP430AsmParser::ParseRegister(unsigned &RegNo
, SMLoc
&StartLoc
,
291 if (getLexer().getKind() == AsmToken::Identifier
) {
292 auto Name
= getLexer().getTok().getIdentifier().lower();
293 RegNo
= MatchRegisterName(Name
);
294 if (RegNo
== MSP430::NoRegister
) {
295 RegNo
= MatchRegisterAltName(Name
);
296 if (RegNo
== MSP430::NoRegister
)
300 AsmToken
const &T
= getParser().getTok();
301 StartLoc
= T
.getLoc();
302 EndLoc
= T
.getEndLoc();
303 getLexer().Lex(); // eat register token
308 return Error(StartLoc
, "invalid register name");
311 bool MSP430AsmParser::parseJccInstruction(ParseInstructionInfo
&Info
,
312 StringRef Name
, SMLoc NameLoc
,
313 OperandVector
&Operands
) {
314 if (!Name
.startswith_lower("j"))
317 auto CC
= Name
.drop_front().lower();
319 if (CC
== "ne" || CC
== "nz")
320 CondCode
= MSP430CC::COND_NE
;
321 else if (CC
== "eq" || CC
== "z")
322 CondCode
= MSP430CC::COND_E
;
323 else if (CC
== "lo" || CC
== "nc")
324 CondCode
= MSP430CC::COND_LO
;
325 else if (CC
== "hs" || CC
== "c")
326 CondCode
= MSP430CC::COND_HS
;
328 CondCode
= MSP430CC::COND_N
;
330 CondCode
= MSP430CC::COND_GE
;
332 CondCode
= MSP430CC::COND_L
;
334 CondCode
= MSP430CC::COND_NONE
;
336 return Error(NameLoc
, "unknown instruction");
338 if (CondCode
== (unsigned)MSP430CC::COND_NONE
)
339 Operands
.push_back(MSP430Operand::CreateToken("jmp", NameLoc
));
341 Operands
.push_back(MSP430Operand::CreateToken("j", NameLoc
));
342 const MCExpr
*CCode
= MCConstantExpr::create(CondCode
, getContext());
343 Operands
.push_back(MSP430Operand::CreateImm(CCode
, SMLoc(), SMLoc()));
346 // Skip optional '$' sign.
347 if (getLexer().getKind() == AsmToken::Dollar
)
348 getLexer().Lex(); // Eat '$'
351 SMLoc ExprLoc
= getLexer().getLoc();
352 if (getParser().parseExpression(Val
))
353 return Error(ExprLoc
, "expected expression operand");
356 if (Val
->evaluateAsAbsolute(Res
))
357 if (Res
< -512 || Res
> 511)
358 return Error(ExprLoc
, "invalid jump offset");
360 Operands
.push_back(MSP430Operand::CreateImm(Val
, ExprLoc
,
361 getLexer().getLoc()));
363 if (getLexer().isNot(AsmToken::EndOfStatement
)) {
364 SMLoc Loc
= getLexer().getLoc();
365 getParser().eatToEndOfStatement();
366 return Error(Loc
, "unexpected token");
369 getParser().Lex(); // Consume the EndOfStatement.
373 bool MSP430AsmParser::ParseInstruction(ParseInstructionInfo
&Info
,
374 StringRef Name
, SMLoc NameLoc
,
375 OperandVector
&Operands
) {
377 if (Name
.endswith_lower(".w"))
378 Name
= Name
.drop_back(2);
380 if (!parseJccInstruction(Info
, Name
, NameLoc
, Operands
))
383 // First operand is instruction mnemonic
384 Operands
.push_back(MSP430Operand::CreateToken(Name
, NameLoc
));
386 // If there are no more operands, then finish
387 if (getLexer().is(AsmToken::EndOfStatement
))
390 // Parse first operand
391 if (ParseOperand(Operands
))
394 // Parse second operand if any
395 if (getLexer().is(AsmToken::Comma
)) {
396 getLexer().Lex(); // Eat ','
397 if (ParseOperand(Operands
))
401 if (getLexer().isNot(AsmToken::EndOfStatement
)) {
402 SMLoc Loc
= getLexer().getLoc();
403 getParser().eatToEndOfStatement();
404 return Error(Loc
, "unexpected token");
407 getParser().Lex(); // Consume the EndOfStatement.
411 bool MSP430AsmParser::ParseDirectiveRefSym(AsmToken DirectiveID
) {
413 if (getParser().parseIdentifier(Name
))
414 return TokError("expected identifier in directive");
416 MCSymbol
*Sym
= getContext().getOrCreateSymbol(Name
);
417 getStreamer().EmitSymbolAttribute(Sym
, MCSA_Global
);
421 bool MSP430AsmParser::ParseDirective(AsmToken DirectiveID
) {
422 StringRef IDVal
= DirectiveID
.getIdentifier();
423 if (IDVal
.lower() == ".long") {
424 ParseLiteralValues(4, DirectiveID
.getLoc());
425 } else if (IDVal
.lower() == ".word" || IDVal
.lower() == ".short") {
426 ParseLiteralValues(2, DirectiveID
.getLoc());
427 } else if (IDVal
.lower() == ".byte") {
428 ParseLiteralValues(1, DirectiveID
.getLoc());
429 } else if (IDVal
.lower() == ".refsym") {
430 return ParseDirectiveRefSym(DirectiveID
);
435 bool MSP430AsmParser::ParseOperand(OperandVector
&Operands
) {
436 switch (getLexer().getKind()) {
437 default: return true;
438 case AsmToken::Identifier
: {
441 SMLoc StartLoc
, EndLoc
;
442 if (!ParseRegister(RegNo
, StartLoc
, EndLoc
)) {
443 Operands
.push_back(MSP430Operand::CreateReg(RegNo
, StartLoc
, EndLoc
));
448 case AsmToken::Integer
:
450 case AsmToken::Minus
: {
451 SMLoc StartLoc
= getParser().getTok().getLoc();
453 // Try constexpr[(rN)]
454 if (!getParser().parseExpression(Val
)) {
455 unsigned RegNo
= MSP430::PC
;
456 SMLoc EndLoc
= getParser().getTok().getLoc();
458 if (getLexer().getKind() == AsmToken::LParen
) {
459 getLexer().Lex(); // Eat '('
461 if (ParseRegister(RegNo
, RegStartLoc
, EndLoc
))
463 if (getLexer().getKind() != AsmToken::RParen
)
465 EndLoc
= getParser().getTok().getEndLoc();
466 getLexer().Lex(); // Eat ')'
468 Operands
.push_back(MSP430Operand::CreateMem(RegNo
, Val
, StartLoc
,
474 case AsmToken::Amp
: {
476 SMLoc StartLoc
= getParser().getTok().getLoc();
477 getLexer().Lex(); // Eat '&'
479 if (!getParser().parseExpression(Val
)) {
480 SMLoc EndLoc
= getParser().getTok().getLoc();
481 Operands
.push_back(MSP430Operand::CreateMem(MSP430::SR
, Val
, StartLoc
,
489 SMLoc StartLoc
= getParser().getTok().getLoc();
490 getLexer().Lex(); // Eat '@'
492 SMLoc RegStartLoc
, EndLoc
;
493 if (ParseRegister(RegNo
, RegStartLoc
, EndLoc
))
495 if (getLexer().getKind() == AsmToken::Plus
) {
496 Operands
.push_back(MSP430Operand::CreatePostIndReg(RegNo
, StartLoc
, EndLoc
));
497 getLexer().Lex(); // Eat '+'
500 if (Operands
.size() > 1) // Emulate @rd in destination position as 0(rd)
501 Operands
.push_back(MSP430Operand::CreateMem(RegNo
,
502 MCConstantExpr::create(0, getContext()), StartLoc
, EndLoc
));
504 Operands
.push_back(MSP430Operand::CreateIndReg(RegNo
, StartLoc
, EndLoc
));
509 SMLoc StartLoc
= getParser().getTok().getLoc();
510 getLexer().Lex(); // Eat '#'
512 if (!getParser().parseExpression(Val
)) {
513 SMLoc EndLoc
= getParser().getTok().getLoc();
514 Operands
.push_back(MSP430Operand::CreateImm(Val
, StartLoc
, EndLoc
));
521 bool MSP430AsmParser::ParseLiteralValues(unsigned Size
, SMLoc L
) {
522 auto parseOne
= [&]() -> bool {
524 if (getParser().parseExpression(Value
))
526 getParser().getStreamer().EmitValue(Value
, Size
, L
);
529 return (parseMany(parseOne
));
532 extern "C" void LLVMInitializeMSP430AsmParser() {
533 RegisterMCAsmParser
<MSP430AsmParser
> X(getTheMSP430Target());
536 #define GET_REGISTER_MATCHER
537 #define GET_MATCHER_IMPLEMENTATION
538 #include "MSP430GenAsmMatcher.inc"
540 static unsigned convertGR16ToGR8(unsigned Reg
) {
543 llvm_unreachable("Unknown GR16 register");
544 case MSP430::PC
: return MSP430::PCB
;
545 case MSP430::SP
: return MSP430::SPB
;
546 case MSP430::SR
: return MSP430::SRB
;
547 case MSP430::CG
: return MSP430::CGB
;
548 case MSP430::FP
: return MSP430::FPB
;
549 case MSP430::R5
: return MSP430::R5B
;
550 case MSP430::R6
: return MSP430::R6B
;
551 case MSP430::R7
: return MSP430::R7B
;
552 case MSP430::R8
: return MSP430::R8B
;
553 case MSP430::R9
: return MSP430::R9B
;
554 case MSP430::R10
: return MSP430::R10B
;
555 case MSP430::R11
: return MSP430::R11B
;
556 case MSP430::R12
: return MSP430::R12B
;
557 case MSP430::R13
: return MSP430::R13B
;
558 case MSP430::R14
: return MSP430::R14B
;
559 case MSP430::R15
: return MSP430::R15B
;
563 unsigned MSP430AsmParser::validateTargetOperandClass(MCParsedAsmOperand
&AsmOp
,
565 MSP430Operand
&Op
= static_cast<MSP430Operand
&>(AsmOp
);
568 return Match_InvalidOperand
;
570 unsigned Reg
= Op
.getReg();
572 MSP430MCRegisterClasses
[MSP430::GR16RegClassID
].contains(Reg
);
574 if (isGR16
&& (Kind
== MCK_GR8
)) {
575 Op
.setReg(convertGR16ToGR8(Reg
));
576 return Match_Success
;
579 return Match_InvalidOperand
;