Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp
35294 views
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
MCAsmParser &getParser() const { return Parser; }
69
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
: 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:
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,
124
SMLoc const &E)
125
: Kind(k_Mem), Mem({Reg, Expr}), Start(S), End(E) {}
126
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!");
131
132
Inst.addOperand(MCOperand::createReg(Reg));
133
}
134
135
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
145
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
152
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
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; }
166
167
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
181
StringRef getToken() const {
182
assert(Kind == k_Tok && "Invalid access!");
183
return Tok;
184
}
185
186
MCRegister getReg() const override {
187
assert(Kind == k_Reg && "Invalid access!");
188
return Reg;
189
}
190
191
void setReg(unsigned RegNo) {
192
assert(Kind == k_Reg && "Invalid access!");
193
Reg = RegNo;
194
}
195
196
static std::unique_ptr<MSP430Operand> CreateToken(StringRef Str, SMLoc S) {
197
return std::make_unique<MSP430Operand>(Str, S);
198
}
199
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
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
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
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
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
226
SMLoc getStartLoc() const override { return Start; }
227
SMLoc getEndLoc() const override { return End; }
228
229
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
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 MCRegister MatchRegisterName(StringRef Name);
290
static MCRegister MatchRegisterAltName(StringRef Name);
291
292
bool MSP430AsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
293
SMLoc &EndLoc) {
294
ParseStatus Res = tryParseRegister(Reg, StartLoc, EndLoc);
295
if (Res.isFailure())
296
return Error(StartLoc, "invalid register name");
297
if (Res.isSuccess())
298
return false;
299
if (Res.isNoMatch())
300
return true;
301
302
llvm_unreachable("unknown parse status");
303
}
304
305
ParseStatus MSP430AsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
306
SMLoc &EndLoc) {
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;
314
}
315
316
AsmToken const &T = getParser().getTok();
317
StartLoc = T.getLoc();
318
EndLoc = T.getEndLoc();
319
getLexer().Lex(); // eat register token
320
321
return ParseStatus::Success;
322
}
323
324
return ParseStatus::Failure;
325
}
326
327
bool MSP430AsmParser::parseJccInstruction(ParseInstructionInfo &Info,
328
StringRef Name, SMLoc NameLoc,
329
OperandVector &Operands) {
330
if (!Name.starts_with_insensitive("j"))
331
return true;
332
333
auto CC = Name.drop_front().lower();
334
unsigned CondCode;
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;
343
else if (CC == "n")
344
CondCode = MSP430CC::COND_N;
345
else if (CC == "ge")
346
CondCode = MSP430CC::COND_GE;
347
else if (CC == "l")
348
CondCode = MSP430CC::COND_L;
349
else if (CC == "mp")
350
CondCode = MSP430CC::COND_NONE;
351
else
352
return Error(NameLoc, "unknown instruction");
353
354
if (CondCode == (unsigned)MSP430CC::COND_NONE)
355
Operands.push_back(MSP430Operand::CreateToken("jmp", NameLoc));
356
else {
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()));
360
}
361
362
// Skip optional '$' sign.
363
(void)parseOptionalToken(AsmToken::Dollar);
364
365
const MCExpr *Val;
366
SMLoc ExprLoc = getLexer().getLoc();
367
if (getParser().parseExpression(Val))
368
return Error(ExprLoc, "expected expression operand");
369
370
int64_t Res;
371
if (Val->evaluateAsAbsolute(Res))
372
if (Res < -512 || Res > 511)
373
return Error(ExprLoc, "invalid jump offset");
374
375
Operands.push_back(MSP430Operand::CreateImm(Val, ExprLoc,
376
getLexer().getLoc()));
377
378
if (getLexer().isNot(AsmToken::EndOfStatement)) {
379
SMLoc Loc = getLexer().getLoc();
380
getParser().eatToEndOfStatement();
381
return Error(Loc, "unexpected token");
382
}
383
384
getParser().Lex(); // Consume the EndOfStatement.
385
return false;
386
}
387
388
bool MSP430AsmParser::ParseInstruction(ParseInstructionInfo &Info,
389
StringRef Name, SMLoc NameLoc,
390
OperandVector &Operands) {
391
// Drop .w suffix
392
if (Name.ends_with_insensitive(".w"))
393
Name = Name.drop_back(2);
394
395
if (!parseJccInstruction(Info, Name, NameLoc, Operands))
396
return false;
397
398
// First operand is instruction mnemonic
399
Operands.push_back(MSP430Operand::CreateToken(Name, NameLoc));
400
401
// If there are no more operands, then finish
402
if (getLexer().is(AsmToken::EndOfStatement))
403
return false;
404
405
// Parse first operand
406
if (ParseOperand(Operands))
407
return true;
408
409
// Parse second operand if any
410
if (parseOptionalToken(AsmToken::Comma) && ParseOperand(Operands))
411
return true;
412
413
if (getLexer().isNot(AsmToken::EndOfStatement)) {
414
SMLoc Loc = getLexer().getLoc();
415
getParser().eatToEndOfStatement();
416
return Error(Loc, "unexpected token");
417
}
418
419
getParser().Lex(); // Consume the EndOfStatement.
420
return false;
421
}
422
423
bool MSP430AsmParser::ParseDirectiveRefSym(AsmToken DirectiveID) {
424
StringRef Name;
425
if (getParser().parseIdentifier(Name))
426
return TokError("expected identifier in directive");
427
428
MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
429
getStreamer().emitSymbolAttribute(Sym, MCSA_Global);
430
return parseEOL();
431
}
432
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;
444
}
445
446
bool MSP430AsmParser::ParseOperand(OperandVector &Operands) {
447
switch (getLexer().getKind()) {
448
default: return true;
449
case AsmToken::Identifier: {
450
// try rN
451
MCRegister RegNo;
452
SMLoc StartLoc, EndLoc;
453
if (!parseRegister(RegNo, StartLoc, EndLoc)) {
454
Operands.push_back(MSP430Operand::CreateReg(RegNo, StartLoc, EndLoc));
455
return false;
456
}
457
[[fallthrough]];
458
}
459
case AsmToken::Integer:
460
case AsmToken::Plus:
461
case AsmToken::Minus: {
462
SMLoc StartLoc = getParser().getTok().getLoc();
463
const MCExpr *Val;
464
// Try constexpr[(rN)]
465
if (!getParser().parseExpression(Val)) {
466
MCRegister RegNo = MSP430::PC;
467
SMLoc EndLoc = getParser().getTok().getLoc();
468
// Try (rN)
469
if (parseOptionalToken(AsmToken::LParen)) {
470
SMLoc RegStartLoc;
471
if (parseRegister(RegNo, RegStartLoc, EndLoc))
472
return true;
473
EndLoc = getParser().getTok().getEndLoc();
474
if (!parseOptionalToken(AsmToken::RParen))
475
return true;
476
}
477
Operands.push_back(MSP430Operand::CreateMem(RegNo, Val, StartLoc,
478
EndLoc));
479
return false;
480
}
481
return true;
482
}
483
case AsmToken::Amp: {
484
// Try &constexpr
485
SMLoc StartLoc = getParser().getTok().getLoc();
486
getLexer().Lex(); // Eat '&'
487
const MCExpr *Val;
488
if (!getParser().parseExpression(Val)) {
489
SMLoc EndLoc = getParser().getTok().getLoc();
490
Operands.push_back(MSP430Operand::CreateMem(MSP430::SR, Val, StartLoc,
491
EndLoc));
492
return false;
493
}
494
return true;
495
}
496
case AsmToken::At: {
497
// Try @rN[+]
498
SMLoc StartLoc = getParser().getTok().getLoc();
499
getLexer().Lex(); // Eat '@'
500
MCRegister RegNo;
501
SMLoc RegStartLoc, EndLoc;
502
if (parseRegister(RegNo, RegStartLoc, EndLoc))
503
return true;
504
if (parseOptionalToken(AsmToken::Plus)) {
505
Operands.push_back(MSP430Operand::CreatePostIndReg(RegNo, StartLoc, EndLoc));
506
return false;
507
}
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));
511
else
512
Operands.push_back(MSP430Operand::CreateIndReg(RegNo, StartLoc, EndLoc));
513
return false;
514
}
515
case AsmToken::Hash:
516
// Try #constexpr
517
SMLoc StartLoc = getParser().getTok().getLoc();
518
getLexer().Lex(); // Eat '#'
519
const MCExpr *Val;
520
if (!getParser().parseExpression(Val)) {
521
SMLoc EndLoc = getParser().getTok().getLoc();
522
Operands.push_back(MSP430Operand::CreateImm(Val, StartLoc, EndLoc));
523
return false;
524
}
525
return true;
526
}
527
}
528
529
bool MSP430AsmParser::ParseLiteralValues(unsigned Size, SMLoc L) {
530
auto parseOne = [&]() -> bool {
531
const MCExpr *Value;
532
if (getParser().parseExpression(Value))
533
return true;
534
getParser().getStreamer().emitValue(Value, Size, L);
535
return false;
536
};
537
return (parseMany(parseOne));
538
}
539
540
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMSP430AsmParser() {
541
RegisterMCAsmParser<MSP430AsmParser> X(getTheMSP430Target());
542
}
543
544
#define GET_REGISTER_MATCHER
545
#define GET_MATCHER_IMPLEMENTATION
546
#include "MSP430GenAsmMatcher.inc"
547
548
static unsigned convertGR16ToGR8(unsigned Reg) {
549
switch (Reg) {
550
default:
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;
568
}
569
}
570
571
unsigned MSP430AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
572
unsigned Kind) {
573
MSP430Operand &Op = static_cast<MSP430Operand &>(AsmOp);
574
575
if (!Op.isReg())
576
return Match_InvalidOperand;
577
578
unsigned Reg = Op.getReg();
579
bool isGR16 =
580
MSP430MCRegisterClasses[MSP430::GR16RegClassID].contains(Reg);
581
582
if (isGR16 && (Kind == MCK_GR8)) {
583
Op.setReg(convertGR16ToGR8(Reg));
584
return Match_Success;
585
}
586
587
return Match_InvalidOperand;
588
}
589
590