blob: 0ea3d1e715210adeca1f42f01bda62895b82e128 [file] [log] [blame]
Tom Stellard45bb48e2015-06-13 03:28:10 +00001//===-- AMDGPUAsmParser.cpp - Parse SI asm to MCInst instructions ----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
Tom Stellard347ac792015-06-26 21:15:07 +000011#include "MCTargetDesc/AMDGPUTargetStreamer.h"
12#include "Utils/AMDGPUBaseInfo.h"
Tom Stellardff7416b2015-06-26 21:58:31 +000013#include "AMDKernelCodeT.h"
Tom Stellard45bb48e2015-06-13 03:28:10 +000014#include "SIDefines.h"
15#include "llvm/ADT/APFloat.h"
16#include "llvm/ADT/SmallString.h"
17#include "llvm/ADT/SmallVector.h"
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/StringSwitch.h"
20#include "llvm/ADT/Twine.h"
21#include "llvm/MC/MCContext.h"
22#include "llvm/MC/MCExpr.h"
23#include "llvm/MC/MCInst.h"
24#include "llvm/MC/MCInstrInfo.h"
25#include "llvm/MC/MCParser/MCAsmLexer.h"
26#include "llvm/MC/MCParser/MCAsmParser.h"
27#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
28#include "llvm/MC/MCRegisterInfo.h"
29#include "llvm/MC/MCStreamer.h"
30#include "llvm/MC/MCSubtargetInfo.h"
31#include "llvm/MC/MCTargetAsmParser.h"
32#include "llvm/Support/SourceMgr.h"
33#include "llvm/Support/TargetRegistry.h"
34#include "llvm/Support/raw_ostream.h"
35#include "llvm/Support/Debug.h"
36
37using namespace llvm;
38
39namespace {
40
41struct OptionalOperand;
42
43class AMDGPUOperand : public MCParsedAsmOperand {
44 enum KindTy {
45 Token,
46 Immediate,
47 Register,
48 Expression
49 } Kind;
50
51 SMLoc StartLoc, EndLoc;
52
53public:
54 AMDGPUOperand(enum KindTy K) : MCParsedAsmOperand(), Kind(K) {}
55
56 MCContext *Ctx;
57
58 enum ImmTy {
59 ImmTyNone,
60 ImmTyDSOffset0,
61 ImmTyDSOffset1,
62 ImmTyGDS,
63 ImmTyOffset,
64 ImmTyGLC,
65 ImmTySLC,
66 ImmTyTFE,
67 ImmTyClamp,
68 ImmTyOMod
69 };
70
71 struct TokOp {
72 const char *Data;
73 unsigned Length;
74 };
75
76 struct ImmOp {
77 bool IsFPImm;
78 ImmTy Type;
79 int64_t Val;
80 };
81
82 struct RegOp {
83 unsigned RegNo;
84 int Modifiers;
85 const MCRegisterInfo *TRI;
86 bool IsForcedVOP3;
87 };
88
89 union {
90 TokOp Tok;
91 ImmOp Imm;
92 RegOp Reg;
93 const MCExpr *Expr;
94 };
95
96 void addImmOperands(MCInst &Inst, unsigned N) const {
97 Inst.addOperand(MCOperand::createImm(getImm()));
98 }
99
100 StringRef getToken() const {
101 return StringRef(Tok.Data, Tok.Length);
102 }
103
104 void addRegOperands(MCInst &Inst, unsigned N) const {
105 Inst.addOperand(MCOperand::createReg(getReg()));
106 }
107
108 void addRegOrImmOperands(MCInst &Inst, unsigned N) const {
109 if (isReg())
110 addRegOperands(Inst, N);
111 else
112 addImmOperands(Inst, N);
113 }
114
115 void addRegWithInputModsOperands(MCInst &Inst, unsigned N) const {
116 Inst.addOperand(MCOperand::createImm(
117 Reg.Modifiers == -1 ? 0 : Reg.Modifiers));
118 addRegOperands(Inst, N);
119 }
120
121 void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const {
122 if (isImm())
123 addImmOperands(Inst, N);
124 else {
125 assert(isExpr());
126 Inst.addOperand(MCOperand::createExpr(Expr));
127 }
128 }
129
130 bool defaultTokenHasSuffix() const {
131 StringRef Token(Tok.Data, Tok.Length);
132
133 return Token.endswith("_e32") || Token.endswith("_e64");
134 }
135
136 bool isToken() const override {
137 return Kind == Token;
138 }
139
140 bool isImm() const override {
141 return Kind == Immediate;
142 }
143
144 bool isInlineImm() const {
145 float F = BitsToFloat(Imm.Val);
146 // TODO: Add 0.5pi for VI
147 return isImm() && ((Imm.Val <= 64 && Imm.Val >= -16) ||
148 (F == 0.0 || F == 0.5 || F == -0.5 || F == 1.0 || F == -1.0 ||
149 F == 2.0 || F == -2.0 || F == 4.0 || F == -4.0));
150 }
151
152 bool isDSOffset0() const {
153 assert(isImm());
154 return Imm.Type == ImmTyDSOffset0;
155 }
156
157 bool isDSOffset1() const {
158 assert(isImm());
159 return Imm.Type == ImmTyDSOffset1;
160 }
161
162 int64_t getImm() const {
163 return Imm.Val;
164 }
165
166 enum ImmTy getImmTy() const {
167 assert(isImm());
168 return Imm.Type;
169 }
170
171 bool isRegKind() const {
172 return Kind == Register;
173 }
174
175 bool isReg() const override {
176 return Kind == Register && Reg.Modifiers == -1;
177 }
178
179 bool isRegWithInputMods() const {
180 return Kind == Register && (Reg.IsForcedVOP3 || Reg.Modifiers != -1);
181 }
182
183 void setModifiers(unsigned Mods) {
184 assert(isReg());
185 Reg.Modifiers = Mods;
186 }
187
188 bool hasModifiers() const {
189 assert(isRegKind());
190 return Reg.Modifiers != -1;
191 }
192
193 unsigned getReg() const override {
194 return Reg.RegNo;
195 }
196
197 bool isRegOrImm() const {
198 return isReg() || isImm();
199 }
200
201 bool isRegClass(unsigned RCID) const {
202 return Reg.TRI->getRegClass(RCID).contains(getReg());
203 }
204
205 bool isSCSrc32() const {
206 return isInlineImm() || (isReg() && isRegClass(AMDGPU::SReg_32RegClassID));
207 }
208
209 bool isSSrc32() const {
210 return isImm() || (isReg() && isRegClass(AMDGPU::SReg_32RegClassID));
211 }
212
213 bool isSSrc64() const {
214 return isImm() || isInlineImm() ||
215 (isReg() && isRegClass(AMDGPU::SReg_64RegClassID));
216 }
217
218 bool isVCSrc32() const {
219 return isInlineImm() || (isReg() && isRegClass(AMDGPU::VS_32RegClassID));
220 }
221
222 bool isVCSrc64() const {
223 return isInlineImm() || (isReg() && isRegClass(AMDGPU::VS_64RegClassID));
224 }
225
226 bool isVSrc32() const {
227 return isImm() || (isReg() && isRegClass(AMDGPU::VS_32RegClassID));
228 }
229
230 bool isVSrc64() const {
231 return isImm() || (isReg() && isRegClass(AMDGPU::VS_64RegClassID));
232 }
233
234 bool isMem() const override {
235 return false;
236 }
237
238 bool isExpr() const {
239 return Kind == Expression;
240 }
241
242 bool isSoppBrTarget() const {
243 return isExpr() || isImm();
244 }
245
246 SMLoc getStartLoc() const override {
247 return StartLoc;
248 }
249
250 SMLoc getEndLoc() const override {
251 return EndLoc;
252 }
253
254 void print(raw_ostream &OS) const override { }
255
256 static std::unique_ptr<AMDGPUOperand> CreateImm(int64_t Val, SMLoc Loc,
257 enum ImmTy Type = ImmTyNone,
258 bool IsFPImm = false) {
259 auto Op = llvm::make_unique<AMDGPUOperand>(Immediate);
260 Op->Imm.Val = Val;
261 Op->Imm.IsFPImm = IsFPImm;
262 Op->Imm.Type = Type;
263 Op->StartLoc = Loc;
264 Op->EndLoc = Loc;
265 return Op;
266 }
267
268 static std::unique_ptr<AMDGPUOperand> CreateToken(StringRef Str, SMLoc Loc,
269 bool HasExplicitEncodingSize = true) {
270 auto Res = llvm::make_unique<AMDGPUOperand>(Token);
271 Res->Tok.Data = Str.data();
272 Res->Tok.Length = Str.size();
273 Res->StartLoc = Loc;
274 Res->EndLoc = Loc;
275 return Res;
276 }
277
278 static std::unique_ptr<AMDGPUOperand> CreateReg(unsigned RegNo, SMLoc S,
279 SMLoc E,
280 const MCRegisterInfo *TRI,
281 bool ForceVOP3) {
282 auto Op = llvm::make_unique<AMDGPUOperand>(Register);
283 Op->Reg.RegNo = RegNo;
284 Op->Reg.TRI = TRI;
285 Op->Reg.Modifiers = -1;
286 Op->Reg.IsForcedVOP3 = ForceVOP3;
287 Op->StartLoc = S;
288 Op->EndLoc = E;
289 return Op;
290 }
291
292 static std::unique_ptr<AMDGPUOperand> CreateExpr(const class MCExpr *Expr, SMLoc S) {
293 auto Op = llvm::make_unique<AMDGPUOperand>(Expression);
294 Op->Expr = Expr;
295 Op->StartLoc = S;
296 Op->EndLoc = S;
297 return Op;
298 }
299
300 bool isDSOffset() const;
301 bool isDSOffset01() const;
302 bool isSWaitCnt() const;
303 bool isMubufOffset() const;
Tom Stellard217361c2015-08-06 19:28:38 +0000304 bool isSMRDOffset() const;
305 bool isSMRDLiteralOffset() const;
Tom Stellard45bb48e2015-06-13 03:28:10 +0000306};
307
308class AMDGPUAsmParser : public MCTargetAsmParser {
309 MCSubtargetInfo &STI;
310 const MCInstrInfo &MII;
311 MCAsmParser &Parser;
312
313 unsigned ForcedEncodingSize;
314 /// @name Auto-generated Match Functions
315 /// {
316
317#define GET_ASSEMBLER_HEADER
318#include "AMDGPUGenAsmMatcher.inc"
319
320 /// }
321
Tom Stellard347ac792015-06-26 21:15:07 +0000322private:
323 bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor);
324 bool ParseDirectiveHSACodeObjectVersion();
325 bool ParseDirectiveHSACodeObjectISA();
Tom Stellardff7416b2015-06-26 21:58:31 +0000326 bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header);
327 bool ParseDirectiveAMDKernelCodeT();
Tom Stellard347ac792015-06-26 21:15:07 +0000328
Tom Stellard45bb48e2015-06-13 03:28:10 +0000329public:
330 AMDGPUAsmParser(MCSubtargetInfo &STI, MCAsmParser &_Parser,
331 const MCInstrInfo &MII,
332 const MCTargetOptions &Options)
Colin LeMahieufe2c8b82015-07-27 21:56:53 +0000333 : MCTargetAsmParser(Options), STI(STI), MII(MII), Parser(_Parser),
Tom Stellard45bb48e2015-06-13 03:28:10 +0000334 ForcedEncodingSize(0){
335
336 if (STI.getFeatureBits().none()) {
337 // Set default features.
338 STI.ToggleFeature("SOUTHERN_ISLANDS");
339 }
340
341 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
342 }
343
Tom Stellard347ac792015-06-26 21:15:07 +0000344 AMDGPUTargetStreamer &getTargetStreamer() {
345 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
346 return static_cast<AMDGPUTargetStreamer &>(TS);
347 }
348
Tom Stellard45bb48e2015-06-13 03:28:10 +0000349 unsigned getForcedEncodingSize() const {
350 return ForcedEncodingSize;
351 }
352
353 void setForcedEncodingSize(unsigned Size) {
354 ForcedEncodingSize = Size;
355 }
356
357 bool isForcedVOP3() const {
358 return ForcedEncodingSize == 64;
359 }
360
361 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
362 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
363 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
364 OperandVector &Operands, MCStreamer &Out,
365 uint64_t &ErrorInfo,
366 bool MatchingInlineAsm) override;
367 bool ParseDirective(AsmToken DirectiveID) override;
368 OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic);
369 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
370 SMLoc NameLoc, OperandVector &Operands) override;
371
372 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int,
373 int64_t Default = 0);
374 OperandMatchResultTy parseIntWithPrefix(const char *Prefix,
375 OperandVector &Operands,
376 enum AMDGPUOperand::ImmTy ImmTy =
377 AMDGPUOperand::ImmTyNone);
378 OperandMatchResultTy parseNamedBit(const char *Name, OperandVector &Operands,
379 enum AMDGPUOperand::ImmTy ImmTy =
380 AMDGPUOperand::ImmTyNone);
381 OperandMatchResultTy parseOptionalOps(
382 const ArrayRef<OptionalOperand> &OptionalOps,
383 OperandVector &Operands);
384
385
386 void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands);
387 void cvtDS(MCInst &Inst, const OperandVector &Operands);
388 OperandMatchResultTy parseDSOptionalOps(OperandVector &Operands);
389 OperandMatchResultTy parseDSOff01OptionalOps(OperandVector &Operands);
390 OperandMatchResultTy parseDSOffsetOptional(OperandVector &Operands);
391
392 bool parseCnt(int64_t &IntVal);
393 OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);
394 OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands);
395
396 OperandMatchResultTy parseFlatOptionalOps(OperandVector &Operands);
397 OperandMatchResultTy parseFlatAtomicOptionalOps(OperandVector &Operands);
398 void cvtFlat(MCInst &Inst, const OperandVector &Operands);
399
400 void cvtMubuf(MCInst &Inst, const OperandVector &Operands);
401 OperandMatchResultTy parseOffset(OperandVector &Operands);
402 OperandMatchResultTy parseMubufOptionalOps(OperandVector &Operands);
403 OperandMatchResultTy parseGLC(OperandVector &Operands);
404 OperandMatchResultTy parseSLC(OperandVector &Operands);
405 OperandMatchResultTy parseTFE(OperandVector &Operands);
406
407 OperandMatchResultTy parseDMask(OperandVector &Operands);
408 OperandMatchResultTy parseUNorm(OperandVector &Operands);
409 OperandMatchResultTy parseR128(OperandVector &Operands);
410
411 void cvtVOP3(MCInst &Inst, const OperandVector &Operands);
412 OperandMatchResultTy parseVOP3OptionalOps(OperandVector &Operands);
413};
414
415struct OptionalOperand {
416 const char *Name;
417 AMDGPUOperand::ImmTy Type;
418 bool IsBit;
419 int64_t Default;
420 bool (*ConvertResult)(int64_t&);
421};
422
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000423}
Tom Stellard45bb48e2015-06-13 03:28:10 +0000424
425static unsigned getRegClass(bool IsVgpr, unsigned RegWidth) {
426 if (IsVgpr) {
427 switch (RegWidth) {
428 default: llvm_unreachable("Unknown register width");
429 case 1: return AMDGPU::VGPR_32RegClassID;
430 case 2: return AMDGPU::VReg_64RegClassID;
431 case 3: return AMDGPU::VReg_96RegClassID;
432 case 4: return AMDGPU::VReg_128RegClassID;
433 case 8: return AMDGPU::VReg_256RegClassID;
434 case 16: return AMDGPU::VReg_512RegClassID;
435 }
436 }
437
438 switch (RegWidth) {
439 default: llvm_unreachable("Unknown register width");
440 case 1: return AMDGPU::SGPR_32RegClassID;
441 case 2: return AMDGPU::SGPR_64RegClassID;
442 case 4: return AMDGPU::SReg_128RegClassID;
443 case 8: return AMDGPU::SReg_256RegClassID;
444 case 16: return AMDGPU::SReg_512RegClassID;
445 }
446}
447
448static unsigned getRegForName(const StringRef &RegName) {
449
450 return StringSwitch<unsigned>(RegName)
451 .Case("exec", AMDGPU::EXEC)
452 .Case("vcc", AMDGPU::VCC)
453 .Case("flat_scr", AMDGPU::FLAT_SCR)
454 .Case("m0", AMDGPU::M0)
455 .Case("scc", AMDGPU::SCC)
456 .Case("flat_scr_lo", AMDGPU::FLAT_SCR_LO)
457 .Case("flat_scr_hi", AMDGPU::FLAT_SCR_HI)
458 .Case("vcc_lo", AMDGPU::VCC_LO)
459 .Case("vcc_hi", AMDGPU::VCC_HI)
460 .Case("exec_lo", AMDGPU::EXEC_LO)
461 .Case("exec_hi", AMDGPU::EXEC_HI)
462 .Default(0);
463}
464
465bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) {
466 const AsmToken Tok = Parser.getTok();
467 StartLoc = Tok.getLoc();
468 EndLoc = Tok.getEndLoc();
469 const StringRef &RegName = Tok.getString();
470 RegNo = getRegForName(RegName);
471
472 if (RegNo) {
473 Parser.Lex();
474 return false;
475 }
476
477 // Match vgprs and sgprs
478 if (RegName[0] != 's' && RegName[0] != 'v')
479 return true;
480
481 bool IsVgpr = RegName[0] == 'v';
482 unsigned RegWidth;
483 unsigned RegIndexInClass;
484 if (RegName.size() > 1) {
485 // We have a 32-bit register
486 RegWidth = 1;
487 if (RegName.substr(1).getAsInteger(10, RegIndexInClass))
488 return true;
489 Parser.Lex();
490 } else {
491 // We have a register greater than 32-bits.
492
493 int64_t RegLo, RegHi;
494 Parser.Lex();
495 if (getLexer().isNot(AsmToken::LBrac))
496 return true;
497
498 Parser.Lex();
499 if (getParser().parseAbsoluteExpression(RegLo))
500 return true;
501
502 if (getLexer().isNot(AsmToken::Colon))
503 return true;
504
505 Parser.Lex();
506 if (getParser().parseAbsoluteExpression(RegHi))
507 return true;
508
509 if (getLexer().isNot(AsmToken::RBrac))
510 return true;
511
512 Parser.Lex();
513 RegWidth = (RegHi - RegLo) + 1;
514 if (IsVgpr) {
515 // VGPR registers aren't aligned.
516 RegIndexInClass = RegLo;
517 } else {
518 // SGPR registers are aligned. Max alignment is 4 dwords.
519 RegIndexInClass = RegLo / std::min(RegWidth, 4u);
520 }
521 }
522
523 const MCRegisterInfo *TRC = getContext().getRegisterInfo();
524 unsigned RC = getRegClass(IsVgpr, RegWidth);
525 if (RegIndexInClass > TRC->getRegClass(RC).getNumRegs())
526 return true;
527 RegNo = TRC->getRegClass(RC).getRegister(RegIndexInClass);
528 return false;
529}
530
531unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
532
533 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
534
535 if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) ||
536 (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3)))
537 return Match_InvalidOperand;
538
539 return Match_Success;
540}
541
542
543bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
544 OperandVector &Operands,
545 MCStreamer &Out,
546 uint64_t &ErrorInfo,
547 bool MatchingInlineAsm) {
548 MCInst Inst;
549
Ranjeet Singh86ecbb72015-06-30 12:32:53 +0000550 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
Tom Stellard45bb48e2015-06-13 03:28:10 +0000551 default: break;
552 case Match_Success:
553 Inst.setLoc(IDLoc);
554 Out.EmitInstruction(Inst, STI);
555 return false;
556 case Match_MissingFeature:
557 return Error(IDLoc, "instruction not supported on this GPU");
558
559 case Match_MnemonicFail:
560 return Error(IDLoc, "unrecognized instruction mnemonic");
561
562 case Match_InvalidOperand: {
563 SMLoc ErrorLoc = IDLoc;
564 if (ErrorInfo != ~0ULL) {
565 if (ErrorInfo >= Operands.size()) {
566 if (isForcedVOP3()) {
567 // If 64-bit encoding has been forced we can end up with no
568 // clamp or omod operands if none of the registers have modifiers,
569 // so we need to add these to the operand list.
570 AMDGPUOperand &LastOp =
571 ((AMDGPUOperand &)*Operands[Operands.size() - 1]);
572 if (LastOp.isRegKind() ||
573 (LastOp.isImm() &&
574 LastOp.getImmTy() != AMDGPUOperand::ImmTyNone)) {
575 SMLoc S = Parser.getTok().getLoc();
576 Operands.push_back(AMDGPUOperand::CreateImm(0, S,
577 AMDGPUOperand::ImmTyClamp));
578 Operands.push_back(AMDGPUOperand::CreateImm(0, S,
579 AMDGPUOperand::ImmTyOMod));
580 bool Res = MatchAndEmitInstruction(IDLoc, Opcode, Operands,
581 Out, ErrorInfo,
582 MatchingInlineAsm);
583 if (!Res)
584 return Res;
585 }
586
587 }
588 return Error(IDLoc, "too few operands for instruction");
589 }
590
591 ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc();
592 if (ErrorLoc == SMLoc())
593 ErrorLoc = IDLoc;
594 }
595 return Error(ErrorLoc, "invalid operand for instruction");
596 }
597 }
598 llvm_unreachable("Implement any new match types added!");
599}
600
Tom Stellard347ac792015-06-26 21:15:07 +0000601bool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major,
602 uint32_t &Minor) {
603 if (getLexer().isNot(AsmToken::Integer))
604 return TokError("invalid major version");
605
606 Major = getLexer().getTok().getIntVal();
607 Lex();
608
609 if (getLexer().isNot(AsmToken::Comma))
610 return TokError("minor version number required, comma expected");
611 Lex();
612
613 if (getLexer().isNot(AsmToken::Integer))
614 return TokError("invalid minor version");
615
616 Minor = getLexer().getTok().getIntVal();
617 Lex();
618
619 return false;
620}
621
622bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() {
623
624 uint32_t Major;
625 uint32_t Minor;
626
627 if (ParseDirectiveMajorMinor(Major, Minor))
628 return true;
629
630 getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor);
631 return false;
632}
633
634bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() {
635
636 uint32_t Major;
637 uint32_t Minor;
638 uint32_t Stepping;
639 StringRef VendorName;
640 StringRef ArchName;
641
642 // If this directive has no arguments, then use the ISA version for the
643 // targeted GPU.
644 if (getLexer().is(AsmToken::EndOfStatement)) {
645 AMDGPU::IsaVersion Isa = AMDGPU::getIsaVersion(STI.getFeatureBits());
646 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Isa.Major, Isa.Minor,
647 Isa.Stepping,
648 "AMD", "AMDGPU");
649 return false;
650 }
651
652
653 if (ParseDirectiveMajorMinor(Major, Minor))
654 return true;
655
656 if (getLexer().isNot(AsmToken::Comma))
657 return TokError("stepping version number required, comma expected");
658 Lex();
659
660 if (getLexer().isNot(AsmToken::Integer))
661 return TokError("invalid stepping version");
662
663 Stepping = getLexer().getTok().getIntVal();
664 Lex();
665
666 if (getLexer().isNot(AsmToken::Comma))
667 return TokError("vendor name required, comma expected");
668 Lex();
669
670 if (getLexer().isNot(AsmToken::String))
671 return TokError("invalid vendor name");
672
673 VendorName = getLexer().getTok().getStringContents();
674 Lex();
675
676 if (getLexer().isNot(AsmToken::Comma))
677 return TokError("arch name required, comma expected");
678 Lex();
679
680 if (getLexer().isNot(AsmToken::String))
681 return TokError("invalid arch name");
682
683 ArchName = getLexer().getTok().getStringContents();
684 Lex();
685
686 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping,
687 VendorName, ArchName);
688 return false;
689}
690
Tom Stellardff7416b2015-06-26 21:58:31 +0000691bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID,
692 amd_kernel_code_t &Header) {
693
694 if (getLexer().isNot(AsmToken::Equal))
695 return TokError("expected '='");
696 Lex();
697
698 if (getLexer().isNot(AsmToken::Integer))
699 return TokError("amd_kernel_code_t values must be integers");
700
701 uint64_t Value = getLexer().getTok().getIntVal();
702 Lex();
703
704 if (ID == "kernel_code_version_major")
705 Header.amd_kernel_code_version_major = Value;
706 else if (ID == "kernel_code_version_minor")
707 Header.amd_kernel_code_version_minor = Value;
708 else if (ID == "machine_kind")
709 Header.amd_machine_kind = Value;
710 else if (ID == "machine_version_major")
711 Header.amd_machine_version_major = Value;
712 else if (ID == "machine_version_minor")
713 Header.amd_machine_version_minor = Value;
714 else if (ID == "machine_version_stepping")
715 Header.amd_machine_version_stepping = Value;
716 else if (ID == "kernel_code_entry_byte_offset")
717 Header.kernel_code_entry_byte_offset = Value;
718 else if (ID == "kernel_code_prefetch_byte_size")
719 Header.kernel_code_prefetch_byte_size = Value;
720 else if (ID == "max_scratch_backing_memory_byte_size")
721 Header.max_scratch_backing_memory_byte_size = Value;
722 else if (ID == "compute_pgm_rsrc1_vgprs")
723 Header.compute_pgm_resource_registers |= S_00B848_VGPRS(Value);
724 else if (ID == "compute_pgm_rsrc1_sgprs")
725 Header.compute_pgm_resource_registers |= S_00B848_SGPRS(Value);
726 else if (ID == "compute_pgm_rsrc1_priority")
727 Header.compute_pgm_resource_registers |= S_00B848_PRIORITY(Value);
728 else if (ID == "compute_pgm_rsrc1_float_mode")
729 Header.compute_pgm_resource_registers |= S_00B848_FLOAT_MODE(Value);
730 else if (ID == "compute_pgm_rsrc1_priv")
731 Header.compute_pgm_resource_registers |= S_00B848_PRIV(Value);
732 else if (ID == "compute_pgm_rsrc1_dx10_clamp")
733 Header.compute_pgm_resource_registers |= S_00B848_DX10_CLAMP(Value);
734 else if (ID == "compute_pgm_rsrc1_debug_mode")
735 Header.compute_pgm_resource_registers |= S_00B848_DEBUG_MODE(Value);
736 else if (ID == "compute_pgm_rsrc1_ieee_mode")
737 Header.compute_pgm_resource_registers |= S_00B848_IEEE_MODE(Value);
738 else if (ID == "compute_pgm_rsrc2_scratch_en")
739 Header.compute_pgm_resource_registers |= (S_00B84C_SCRATCH_EN(Value) << 32);
740 else if (ID == "compute_pgm_rsrc2_user_sgpr")
741 Header.compute_pgm_resource_registers |= (S_00B84C_USER_SGPR(Value) << 32);
742 else if (ID == "compute_pgm_rsrc2_tgid_x_en")
743 Header.compute_pgm_resource_registers |= (S_00B84C_TGID_X_EN(Value) << 32);
744 else if (ID == "compute_pgm_rsrc2_tgid_y_en")
745 Header.compute_pgm_resource_registers |= (S_00B84C_TGID_Y_EN(Value) << 32);
746 else if (ID == "compute_pgm_rsrc2_tgid_z_en")
747 Header.compute_pgm_resource_registers |= (S_00B84C_TGID_Z_EN(Value) << 32);
748 else if (ID == "compute_pgm_rsrc2_tg_size_en")
749 Header.compute_pgm_resource_registers |= (S_00B84C_TG_SIZE_EN(Value) << 32);
750 else if (ID == "compute_pgm_rsrc2_tidig_comp_cnt")
751 Header.compute_pgm_resource_registers |=
752 (S_00B84C_TIDIG_COMP_CNT(Value) << 32);
753 else if (ID == "compute_pgm_rsrc2_excp_en_msb")
754 Header.compute_pgm_resource_registers |=
755 (S_00B84C_EXCP_EN_MSB(Value) << 32);
756 else if (ID == "compute_pgm_rsrc2_lds_size")
757 Header.compute_pgm_resource_registers |= (S_00B84C_LDS_SIZE(Value) << 32);
758 else if (ID == "compute_pgm_rsrc2_excp_en")
759 Header.compute_pgm_resource_registers |= (S_00B84C_EXCP_EN(Value) << 32);
760 else if (ID == "compute_pgm_resource_registers")
761 Header.compute_pgm_resource_registers = Value;
762 else if (ID == "enable_sgpr_private_segment_buffer")
763 Header.code_properties |=
764 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER_SHIFT);
765 else if (ID == "enable_sgpr_dispatch_ptr")
766 Header.code_properties |=
767 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR_SHIFT);
768 else if (ID == "enable_sgpr_queue_ptr")
769 Header.code_properties |=
770 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR_SHIFT);
771 else if (ID == "enable_sgpr_kernarg_segment_ptr")
772 Header.code_properties |=
773 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR_SHIFT);
774 else if (ID == "enable_sgpr_dispatch_id")
775 Header.code_properties |=
776 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID_SHIFT);
777 else if (ID == "enable_sgpr_flat_scratch_init")
778 Header.code_properties |=
779 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT_SHIFT);
780 else if (ID == "enable_sgpr_private_segment_size")
781 Header.code_properties |=
782 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE_SHIFT);
783 else if (ID == "enable_sgpr_grid_workgroup_count_x")
784 Header.code_properties |=
785 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_GRID_WORKGROUP_COUNT_X_SHIFT);
786 else if (ID == "enable_sgpr_grid_workgroup_count_y")
787 Header.code_properties |=
788 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_GRID_WORKGROUP_COUNT_Y_SHIFT);
789 else if (ID == "enable_sgpr_grid_workgroup_count_z")
790 Header.code_properties |=
791 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_GRID_WORKGROUP_COUNT_Z_SHIFT);
792 else if (ID == "enable_ordered_append_gds")
793 Header.code_properties |=
794 (Value << AMD_CODE_PROPERTY_ENABLE_ORDERED_APPEND_GDS_SHIFT);
795 else if (ID == "private_element_size")
796 Header.code_properties |=
797 (Value << AMD_CODE_PROPERTY_PRIVATE_ELEMENT_SIZE_SHIFT);
798 else if (ID == "is_ptr64")
799 Header.code_properties |=
800 (Value << AMD_CODE_PROPERTY_IS_PTR64_SHIFT);
801 else if (ID == "is_dynamic_callstack")
802 Header.code_properties |=
803 (Value << AMD_CODE_PROPERTY_IS_DYNAMIC_CALLSTACK_SHIFT);
804 else if (ID == "is_debug_enabled")
805 Header.code_properties |=
806 (Value << AMD_CODE_PROPERTY_IS_DEBUG_SUPPORTED_SHIFT);
807 else if (ID == "is_xnack_enabled")
808 Header.code_properties |=
809 (Value << AMD_CODE_PROPERTY_IS_XNACK_SUPPORTED_SHIFT);
810 else if (ID == "workitem_private_segment_byte_size")
811 Header.workitem_private_segment_byte_size = Value;
812 else if (ID == "workgroup_group_segment_byte_size")
813 Header.workgroup_group_segment_byte_size = Value;
814 else if (ID == "gds_segment_byte_size")
815 Header.gds_segment_byte_size = Value;
816 else if (ID == "kernarg_segment_byte_size")
817 Header.kernarg_segment_byte_size = Value;
818 else if (ID == "workgroup_fbarrier_count")
819 Header.workgroup_fbarrier_count = Value;
820 else if (ID == "wavefront_sgpr_count")
821 Header.wavefront_sgpr_count = Value;
822 else if (ID == "workitem_vgpr_count")
823 Header.workitem_vgpr_count = Value;
824 else if (ID == "reserved_vgpr_first")
825 Header.reserved_vgpr_first = Value;
826 else if (ID == "reserved_vgpr_count")
827 Header.reserved_vgpr_count = Value;
828 else if (ID == "reserved_sgpr_first")
829 Header.reserved_sgpr_first = Value;
830 else if (ID == "reserved_sgpr_count")
831 Header.reserved_sgpr_count = Value;
832 else if (ID == "debug_wavefront_private_segment_offset_sgpr")
833 Header.debug_wavefront_private_segment_offset_sgpr = Value;
834 else if (ID == "debug_private_segment_buffer_sgpr")
835 Header.debug_private_segment_buffer_sgpr = Value;
836 else if (ID == "kernarg_segment_alignment")
837 Header.kernarg_segment_alignment = Value;
838 else if (ID == "group_segment_alignment")
839 Header.group_segment_alignment = Value;
840 else if (ID == "private_segment_alignment")
841 Header.private_segment_alignment = Value;
842 else if (ID == "wavefront_size")
843 Header.wavefront_size = Value;
844 else if (ID == "call_convention")
845 Header.call_convention = Value;
846 else if (ID == "runtime_loader_kernel_symbol")
847 Header.runtime_loader_kernel_symbol = Value;
848 else
849 return TokError("amd_kernel_code_t value not recognized.");
850
851 return false;
852}
853
854bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() {
855
856 amd_kernel_code_t Header;
857 AMDGPU::initDefaultAMDKernelCodeT(Header, STI.getFeatureBits());
858
859 while (true) {
860
861 if (getLexer().isNot(AsmToken::EndOfStatement))
862 return TokError("amd_kernel_code_t values must begin on a new line");
863
864 // Lex EndOfStatement. This is in a while loop, because lexing a comment
865 // will set the current token to EndOfStatement.
866 while(getLexer().is(AsmToken::EndOfStatement))
867 Lex();
868
869 if (getLexer().isNot(AsmToken::Identifier))
870 return TokError("expected value identifier or .end_amd_kernel_code_t");
871
872 StringRef ID = getLexer().getTok().getIdentifier();
873 Lex();
874
875 if (ID == ".end_amd_kernel_code_t")
876 break;
877
878 if (ParseAMDKernelCodeTValue(ID, Header))
879 return true;
880 }
881
882 getTargetStreamer().EmitAMDKernelCodeT(Header);
883
884 return false;
885}
886
Tom Stellard45bb48e2015-06-13 03:28:10 +0000887bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
Tom Stellard347ac792015-06-26 21:15:07 +0000888 StringRef IDVal = DirectiveID.getString();
889
890 if (IDVal == ".hsa_code_object_version")
891 return ParseDirectiveHSACodeObjectVersion();
892
893 if (IDVal == ".hsa_code_object_isa")
894 return ParseDirectiveHSACodeObjectISA();
895
Tom Stellardff7416b2015-06-26 21:58:31 +0000896 if (IDVal == ".amd_kernel_code_t")
897 return ParseDirectiveAMDKernelCodeT();
898
Tom Stellard45bb48e2015-06-13 03:28:10 +0000899 return true;
900}
901
902static bool operandsHaveModifiers(const OperandVector &Operands) {
903
904 for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
905 const AMDGPUOperand &Op = ((AMDGPUOperand&)*Operands[i]);
906 if (Op.isRegKind() && Op.hasModifiers())
907 return true;
908 if (Op.isImm() && (Op.getImmTy() == AMDGPUOperand::ImmTyOMod ||
909 Op.getImmTy() == AMDGPUOperand::ImmTyClamp))
910 return true;
911 }
912 return false;
913}
914
915AMDGPUAsmParser::OperandMatchResultTy
916AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
917
918 // Try to parse with a custom parser
919 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
920
921 // If we successfully parsed the operand or if there as an error parsing,
922 // we are done.
923 //
924 // If we are parsing after we reach EndOfStatement then this means we
925 // are appending default values to the Operands list. This is only done
926 // by custom parser, so we shouldn't continue on to the generic parsing.
927 if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail ||
928 getLexer().is(AsmToken::EndOfStatement))
929 return ResTy;
930
931 bool Negate = false, Abs = false;
932 if (getLexer().getKind()== AsmToken::Minus) {
933 Parser.Lex();
934 Negate = true;
935 }
936
937 if (getLexer().getKind() == AsmToken::Pipe) {
938 Parser.Lex();
939 Abs = true;
940 }
941
942 switch(getLexer().getKind()) {
943 case AsmToken::Integer: {
944 SMLoc S = Parser.getTok().getLoc();
945 int64_t IntVal;
946 if (getParser().parseAbsoluteExpression(IntVal))
947 return MatchOperand_ParseFail;
948 APInt IntVal32(32, IntVal);
949 if (IntVal32.getSExtValue() != IntVal) {
950 Error(S, "invalid immediate: only 32-bit values are legal");
951 return MatchOperand_ParseFail;
952 }
953
954 IntVal = IntVal32.getSExtValue();
955 if (Negate)
956 IntVal *= -1;
957 Operands.push_back(AMDGPUOperand::CreateImm(IntVal, S));
958 return MatchOperand_Success;
959 }
960 case AsmToken::Real: {
961 // FIXME: We should emit an error if a double precisions floating-point
962 // value is used. I'm not sure the best way to detect this.
963 SMLoc S = Parser.getTok().getLoc();
964 int64_t IntVal;
965 if (getParser().parseAbsoluteExpression(IntVal))
966 return MatchOperand_ParseFail;
967
968 APFloat F((float)BitsToDouble(IntVal));
969 if (Negate)
970 F.changeSign();
971 Operands.push_back(
972 AMDGPUOperand::CreateImm(F.bitcastToAPInt().getZExtValue(), S));
973 return MatchOperand_Success;
974 }
975 case AsmToken::Identifier: {
976 SMLoc S, E;
977 unsigned RegNo;
978 if (!ParseRegister(RegNo, S, E)) {
979
980 bool HasModifiers = operandsHaveModifiers(Operands);
981 unsigned Modifiers = 0;
982
983 if (Negate)
984 Modifiers |= 0x1;
985
986 if (Abs) {
987 if (getLexer().getKind() != AsmToken::Pipe)
988 return MatchOperand_ParseFail;
989 Parser.Lex();
990 Modifiers |= 0x2;
991 }
992
993 if (Modifiers && !HasModifiers) {
994 // We are adding a modifier to src1 or src2 and previous sources
995 // don't have modifiers, so we need to go back and empty modifers
996 // for each previous source.
997 for (unsigned PrevRegIdx = Operands.size() - 1; PrevRegIdx > 1;
998 --PrevRegIdx) {
999
1000 AMDGPUOperand &RegOp = ((AMDGPUOperand&)*Operands[PrevRegIdx]);
1001 RegOp.setModifiers(0);
1002 }
1003 }
1004
1005
1006 Operands.push_back(AMDGPUOperand::CreateReg(
1007 RegNo, S, E, getContext().getRegisterInfo(),
1008 isForcedVOP3()));
1009
1010 if (HasModifiers || Modifiers) {
1011 AMDGPUOperand &RegOp = ((AMDGPUOperand&)*Operands[Operands.size() - 1]);
1012 RegOp.setModifiers(Modifiers);
1013
1014 }
1015 } else {
1016 Operands.push_back(AMDGPUOperand::CreateToken(Parser.getTok().getString(),
1017 S));
1018 Parser.Lex();
1019 }
1020 return MatchOperand_Success;
1021 }
1022 default:
1023 return MatchOperand_NoMatch;
1024 }
1025}
1026
1027bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info,
1028 StringRef Name,
1029 SMLoc NameLoc, OperandVector &Operands) {
1030
1031 // Clear any forced encodings from the previous instruction.
1032 setForcedEncodingSize(0);
1033
1034 if (Name.endswith("_e64"))
1035 setForcedEncodingSize(64);
1036 else if (Name.endswith("_e32"))
1037 setForcedEncodingSize(32);
1038
1039 // Add the instruction mnemonic
1040 Operands.push_back(AMDGPUOperand::CreateToken(Name, NameLoc));
1041
1042 while (!getLexer().is(AsmToken::EndOfStatement)) {
1043 AMDGPUAsmParser::OperandMatchResultTy Res = parseOperand(Operands, Name);
1044
1045 // Eat the comma or space if there is one.
1046 if (getLexer().is(AsmToken::Comma))
1047 Parser.Lex();
1048
1049 switch (Res) {
1050 case MatchOperand_Success: break;
1051 case MatchOperand_ParseFail: return Error(getLexer().getLoc(),
1052 "failed parsing operand.");
1053 case MatchOperand_NoMatch: return Error(getLexer().getLoc(),
1054 "not a valid operand.");
1055 }
1056 }
1057
1058 // Once we reach end of statement, continue parsing so we can add default
1059 // values for optional arguments.
1060 AMDGPUAsmParser::OperandMatchResultTy Res;
1061 while ((Res = parseOperand(Operands, Name)) != MatchOperand_NoMatch) {
1062 if (Res != MatchOperand_Success)
1063 return Error(getLexer().getLoc(), "failed parsing operand.");
1064 }
1065 return false;
1066}
1067
1068//===----------------------------------------------------------------------===//
1069// Utility functions
1070//===----------------------------------------------------------------------===//
1071
1072AMDGPUAsmParser::OperandMatchResultTy
1073AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &Int,
1074 int64_t Default) {
1075
1076 // We are at the end of the statement, and this is a default argument, so
1077 // use a default value.
1078 if (getLexer().is(AsmToken::EndOfStatement)) {
1079 Int = Default;
1080 return MatchOperand_Success;
1081 }
1082
1083 switch(getLexer().getKind()) {
1084 default: return MatchOperand_NoMatch;
1085 case AsmToken::Identifier: {
1086 StringRef OffsetName = Parser.getTok().getString();
1087 if (!OffsetName.equals(Prefix))
1088 return MatchOperand_NoMatch;
1089
1090 Parser.Lex();
1091 if (getLexer().isNot(AsmToken::Colon))
1092 return MatchOperand_ParseFail;
1093
1094 Parser.Lex();
1095 if (getLexer().isNot(AsmToken::Integer))
1096 return MatchOperand_ParseFail;
1097
1098 if (getParser().parseAbsoluteExpression(Int))
1099 return MatchOperand_ParseFail;
1100 break;
1101 }
1102 }
1103 return MatchOperand_Success;
1104}
1105
1106AMDGPUAsmParser::OperandMatchResultTy
1107AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
1108 enum AMDGPUOperand::ImmTy ImmTy) {
1109
1110 SMLoc S = Parser.getTok().getLoc();
1111 int64_t Offset = 0;
1112
1113 AMDGPUAsmParser::OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Offset);
1114 if (Res != MatchOperand_Success)
1115 return Res;
1116
1117 Operands.push_back(AMDGPUOperand::CreateImm(Offset, S, ImmTy));
1118 return MatchOperand_Success;
1119}
1120
1121AMDGPUAsmParser::OperandMatchResultTy
1122AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands,
1123 enum AMDGPUOperand::ImmTy ImmTy) {
1124 int64_t Bit = 0;
1125 SMLoc S = Parser.getTok().getLoc();
1126
1127 // We are at the end of the statement, and this is a default argument, so
1128 // use a default value.
1129 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1130 switch(getLexer().getKind()) {
1131 case AsmToken::Identifier: {
1132 StringRef Tok = Parser.getTok().getString();
1133 if (Tok == Name) {
1134 Bit = 1;
1135 Parser.Lex();
1136 } else if (Tok.startswith("no") && Tok.endswith(Name)) {
1137 Bit = 0;
1138 Parser.Lex();
1139 } else {
1140 return MatchOperand_NoMatch;
1141 }
1142 break;
1143 }
1144 default:
1145 return MatchOperand_NoMatch;
1146 }
1147 }
1148
1149 Operands.push_back(AMDGPUOperand::CreateImm(Bit, S, ImmTy));
1150 return MatchOperand_Success;
1151}
1152
1153static bool operandsHasOptionalOp(const OperandVector &Operands,
1154 const OptionalOperand &OOp) {
1155 for (unsigned i = 0; i < Operands.size(); i++) {
1156 const AMDGPUOperand &ParsedOp = ((const AMDGPUOperand &)*Operands[i]);
1157 if ((ParsedOp.isImm() && ParsedOp.getImmTy() == OOp.Type) ||
1158 (ParsedOp.isToken() && ParsedOp.getToken() == OOp.Name))
1159 return true;
1160
1161 }
1162 return false;
1163}
1164
1165AMDGPUAsmParser::OperandMatchResultTy
1166AMDGPUAsmParser::parseOptionalOps(const ArrayRef<OptionalOperand> &OptionalOps,
1167 OperandVector &Operands) {
1168 SMLoc S = Parser.getTok().getLoc();
1169 for (const OptionalOperand &Op : OptionalOps) {
1170 if (operandsHasOptionalOp(Operands, Op))
1171 continue;
1172 AMDGPUAsmParser::OperandMatchResultTy Res;
1173 int64_t Value;
1174 if (Op.IsBit) {
1175 Res = parseNamedBit(Op.Name, Operands, Op.Type);
1176 if (Res == MatchOperand_NoMatch)
1177 continue;
1178 return Res;
1179 }
1180
1181 Res = parseIntWithPrefix(Op.Name, Value, Op.Default);
1182
1183 if (Res == MatchOperand_NoMatch)
1184 continue;
1185
1186 if (Res != MatchOperand_Success)
1187 return Res;
1188
1189 if (Op.ConvertResult && !Op.ConvertResult(Value)) {
1190 return MatchOperand_ParseFail;
1191 }
1192
1193 Operands.push_back(AMDGPUOperand::CreateImm(Value, S, Op.Type));
1194 return MatchOperand_Success;
1195 }
1196 return MatchOperand_NoMatch;
1197}
1198
1199//===----------------------------------------------------------------------===//
1200// ds
1201//===----------------------------------------------------------------------===//
1202
1203static const OptionalOperand DSOptionalOps [] = {
1204 {"offset", AMDGPUOperand::ImmTyOffset, false, 0, nullptr},
1205 {"gds", AMDGPUOperand::ImmTyGDS, true, 0, nullptr}
1206};
1207
1208static const OptionalOperand DSOptionalOpsOff01 [] = {
1209 {"offset0", AMDGPUOperand::ImmTyDSOffset0, false, 0, nullptr},
1210 {"offset1", AMDGPUOperand::ImmTyDSOffset1, false, 0, nullptr},
1211 {"gds", AMDGPUOperand::ImmTyGDS, true, 0, nullptr}
1212};
1213
1214AMDGPUAsmParser::OperandMatchResultTy
1215AMDGPUAsmParser::parseDSOptionalOps(OperandVector &Operands) {
1216 return parseOptionalOps(DSOptionalOps, Operands);
1217}
1218AMDGPUAsmParser::OperandMatchResultTy
1219AMDGPUAsmParser::parseDSOff01OptionalOps(OperandVector &Operands) {
1220 return parseOptionalOps(DSOptionalOpsOff01, Operands);
1221}
1222
1223AMDGPUAsmParser::OperandMatchResultTy
1224AMDGPUAsmParser::parseDSOffsetOptional(OperandVector &Operands) {
1225 SMLoc S = Parser.getTok().getLoc();
1226 AMDGPUAsmParser::OperandMatchResultTy Res =
1227 parseIntWithPrefix("offset", Operands, AMDGPUOperand::ImmTyOffset);
1228 if (Res == MatchOperand_NoMatch) {
1229 Operands.push_back(AMDGPUOperand::CreateImm(0, S,
1230 AMDGPUOperand::ImmTyOffset));
1231 Res = MatchOperand_Success;
1232 }
1233 return Res;
1234}
1235
1236bool AMDGPUOperand::isDSOffset() const {
1237 return isImm() && isUInt<16>(getImm());
1238}
1239
1240bool AMDGPUOperand::isDSOffset01() const {
1241 return isImm() && isUInt<8>(getImm());
1242}
1243
1244void AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst,
1245 const OperandVector &Operands) {
1246
1247 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx;
1248
1249 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
1250 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
1251
1252 // Add the register arguments
1253 if (Op.isReg()) {
1254 Op.addRegOperands(Inst, 1);
1255 continue;
1256 }
1257
1258 // Handle optional arguments
1259 OptionalIdx[Op.getImmTy()] = i;
1260 }
1261
1262 unsigned Offset0Idx = OptionalIdx[AMDGPUOperand::ImmTyDSOffset0];
1263 unsigned Offset1Idx = OptionalIdx[AMDGPUOperand::ImmTyDSOffset1];
1264 unsigned GDSIdx = OptionalIdx[AMDGPUOperand::ImmTyGDS];
1265
1266 ((AMDGPUOperand &)*Operands[Offset0Idx]).addImmOperands(Inst, 1); // offset0
1267 ((AMDGPUOperand &)*Operands[Offset1Idx]).addImmOperands(Inst, 1); // offset1
1268 ((AMDGPUOperand &)*Operands[GDSIdx]).addImmOperands(Inst, 1); // gds
1269 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
1270}
1271
1272void AMDGPUAsmParser::cvtDS(MCInst &Inst, const OperandVector &Operands) {
1273
1274 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx;
1275 bool GDSOnly = false;
1276
1277 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
1278 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
1279
1280 // Add the register arguments
1281 if (Op.isReg()) {
1282 Op.addRegOperands(Inst, 1);
1283 continue;
1284 }
1285
1286 if (Op.isToken() && Op.getToken() == "gds") {
1287 GDSOnly = true;
1288 continue;
1289 }
1290
1291 // Handle optional arguments
1292 OptionalIdx[Op.getImmTy()] = i;
1293 }
1294
1295 unsigned OffsetIdx = OptionalIdx[AMDGPUOperand::ImmTyOffset];
1296 ((AMDGPUOperand &)*Operands[OffsetIdx]).addImmOperands(Inst, 1); // offset
1297
1298 if (!GDSOnly) {
1299 unsigned GDSIdx = OptionalIdx[AMDGPUOperand::ImmTyGDS];
1300 ((AMDGPUOperand &)*Operands[GDSIdx]).addImmOperands(Inst, 1); // gds
1301 }
1302 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
1303}
1304
1305
1306//===----------------------------------------------------------------------===//
1307// s_waitcnt
1308//===----------------------------------------------------------------------===//
1309
1310bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
1311 StringRef CntName = Parser.getTok().getString();
1312 int64_t CntVal;
1313
1314 Parser.Lex();
1315 if (getLexer().isNot(AsmToken::LParen))
1316 return true;
1317
1318 Parser.Lex();
1319 if (getLexer().isNot(AsmToken::Integer))
1320 return true;
1321
1322 if (getParser().parseAbsoluteExpression(CntVal))
1323 return true;
1324
1325 if (getLexer().isNot(AsmToken::RParen))
1326 return true;
1327
1328 Parser.Lex();
1329 if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma))
1330 Parser.Lex();
1331
1332 int CntShift;
1333 int CntMask;
1334
1335 if (CntName == "vmcnt") {
1336 CntMask = 0xf;
1337 CntShift = 0;
1338 } else if (CntName == "expcnt") {
1339 CntMask = 0x7;
1340 CntShift = 4;
1341 } else if (CntName == "lgkmcnt") {
1342 CntMask = 0x7;
1343 CntShift = 8;
1344 } else {
1345 return true;
1346 }
1347
1348 IntVal &= ~(CntMask << CntShift);
1349 IntVal |= (CntVal << CntShift);
1350 return false;
1351}
1352
1353AMDGPUAsmParser::OperandMatchResultTy
1354AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) {
1355 // Disable all counters by default.
1356 // vmcnt [3:0]
1357 // expcnt [6:4]
1358 // lgkmcnt [10:8]
1359 int64_t CntVal = 0x77f;
1360 SMLoc S = Parser.getTok().getLoc();
1361
1362 switch(getLexer().getKind()) {
1363 default: return MatchOperand_ParseFail;
1364 case AsmToken::Integer:
1365 // The operand can be an integer value.
1366 if (getParser().parseAbsoluteExpression(CntVal))
1367 return MatchOperand_ParseFail;
1368 break;
1369
1370 case AsmToken::Identifier:
1371 do {
1372 if (parseCnt(CntVal))
1373 return MatchOperand_ParseFail;
1374 } while(getLexer().isNot(AsmToken::EndOfStatement));
1375 break;
1376 }
1377 Operands.push_back(AMDGPUOperand::CreateImm(CntVal, S));
1378 return MatchOperand_Success;
1379}
1380
1381bool AMDGPUOperand::isSWaitCnt() const {
1382 return isImm();
1383}
1384
1385//===----------------------------------------------------------------------===//
1386// sopp branch targets
1387//===----------------------------------------------------------------------===//
1388
1389AMDGPUAsmParser::OperandMatchResultTy
1390AMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) {
1391 SMLoc S = Parser.getTok().getLoc();
1392
1393 switch (getLexer().getKind()) {
1394 default: return MatchOperand_ParseFail;
1395 case AsmToken::Integer: {
1396 int64_t Imm;
1397 if (getParser().parseAbsoluteExpression(Imm))
1398 return MatchOperand_ParseFail;
1399 Operands.push_back(AMDGPUOperand::CreateImm(Imm, S));
1400 return MatchOperand_Success;
1401 }
1402
1403 case AsmToken::Identifier:
1404 Operands.push_back(AMDGPUOperand::CreateExpr(
1405 MCSymbolRefExpr::create(getContext().getOrCreateSymbol(
1406 Parser.getTok().getString()), getContext()), S));
1407 Parser.Lex();
1408 return MatchOperand_Success;
1409 }
1410}
1411
1412//===----------------------------------------------------------------------===//
1413// flat
1414//===----------------------------------------------------------------------===//
1415
1416static const OptionalOperand FlatOptionalOps [] = {
1417 {"glc", AMDGPUOperand::ImmTyGLC, true, 0, nullptr},
1418 {"slc", AMDGPUOperand::ImmTySLC, true, 0, nullptr},
1419 {"tfe", AMDGPUOperand::ImmTyTFE, true, 0, nullptr}
1420};
1421
1422static const OptionalOperand FlatAtomicOptionalOps [] = {
1423 {"slc", AMDGPUOperand::ImmTySLC, true, 0, nullptr},
1424 {"tfe", AMDGPUOperand::ImmTyTFE, true, 0, nullptr}
1425};
1426
1427AMDGPUAsmParser::OperandMatchResultTy
1428AMDGPUAsmParser::parseFlatOptionalOps(OperandVector &Operands) {
1429 return parseOptionalOps(FlatOptionalOps, Operands);
1430}
1431
1432AMDGPUAsmParser::OperandMatchResultTy
1433AMDGPUAsmParser::parseFlatAtomicOptionalOps(OperandVector &Operands) {
1434 return parseOptionalOps(FlatAtomicOptionalOps, Operands);
1435}
1436
1437void AMDGPUAsmParser::cvtFlat(MCInst &Inst,
1438 const OperandVector &Operands) {
1439 std::map<AMDGPUOperand::ImmTy, unsigned> OptionalIdx;
1440
1441 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
1442 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
1443
1444 // Add the register arguments
1445 if (Op.isReg()) {
1446 Op.addRegOperands(Inst, 1);
1447 continue;
1448 }
1449
1450 // Handle 'glc' token which is sometimes hard-coded into the
1451 // asm string. There are no MCInst operands for these.
1452 if (Op.isToken())
1453 continue;
1454
1455 // Handle optional arguments
1456 OptionalIdx[Op.getImmTy()] = i;
1457
1458 }
1459
1460 // flat atomic instructions don't have a glc argument.
1461 if (OptionalIdx.count(AMDGPUOperand::ImmTyGLC)) {
1462 unsigned GLCIdx = OptionalIdx[AMDGPUOperand::ImmTyGLC];
1463 ((AMDGPUOperand &)*Operands[GLCIdx]).addImmOperands(Inst, 1);
1464 }
1465
1466 unsigned SLCIdx = OptionalIdx[AMDGPUOperand::ImmTySLC];
1467 unsigned TFEIdx = OptionalIdx[AMDGPUOperand::ImmTyTFE];
1468
1469 ((AMDGPUOperand &)*Operands[SLCIdx]).addImmOperands(Inst, 1);
1470 ((AMDGPUOperand &)*Operands[TFEIdx]).addImmOperands(Inst, 1);
1471}
1472
1473//===----------------------------------------------------------------------===//
1474// mubuf
1475//===----------------------------------------------------------------------===//
1476
1477static const OptionalOperand MubufOptionalOps [] = {
1478 {"offset", AMDGPUOperand::ImmTyOffset, false, 0, nullptr},
1479 {"glc", AMDGPUOperand::ImmTyGLC, true, 0, nullptr},
1480 {"slc", AMDGPUOperand::ImmTySLC, true, 0, nullptr},
1481 {"tfe", AMDGPUOperand::ImmTyTFE, true, 0, nullptr}
1482};
1483
1484AMDGPUAsmParser::OperandMatchResultTy
1485AMDGPUAsmParser::parseMubufOptionalOps(OperandVector &Operands) {
1486 return parseOptionalOps(MubufOptionalOps, Operands);
1487}
1488
1489AMDGPUAsmParser::OperandMatchResultTy
1490AMDGPUAsmParser::parseOffset(OperandVector &Operands) {
1491 return parseIntWithPrefix("offset", Operands);
1492}
1493
1494AMDGPUAsmParser::OperandMatchResultTy
1495AMDGPUAsmParser::parseGLC(OperandVector &Operands) {
1496 return parseNamedBit("glc", Operands);
1497}
1498
1499AMDGPUAsmParser::OperandMatchResultTy
1500AMDGPUAsmParser::parseSLC(OperandVector &Operands) {
1501 return parseNamedBit("slc", Operands);
1502}
1503
1504AMDGPUAsmParser::OperandMatchResultTy
1505AMDGPUAsmParser::parseTFE(OperandVector &Operands) {
1506 return parseNamedBit("tfe", Operands);
1507}
1508
1509bool AMDGPUOperand::isMubufOffset() const {
1510 return isImm() && isUInt<12>(getImm());
1511}
1512
1513void AMDGPUAsmParser::cvtMubuf(MCInst &Inst,
1514 const OperandVector &Operands) {
1515 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx;
1516
1517 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
1518 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
1519
1520 // Add the register arguments
1521 if (Op.isReg()) {
1522 Op.addRegOperands(Inst, 1);
1523 continue;
1524 }
1525
1526 // Handle the case where soffset is an immediate
1527 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
1528 Op.addImmOperands(Inst, 1);
1529 continue;
1530 }
1531
1532 // Handle tokens like 'offen' which are sometimes hard-coded into the
1533 // asm string. There are no MCInst operands for these.
1534 if (Op.isToken()) {
1535 continue;
1536 }
1537 assert(Op.isImm());
1538
1539 // Handle optional arguments
1540 OptionalIdx[Op.getImmTy()] = i;
1541 }
1542
1543 assert(OptionalIdx.size() == 4);
1544
1545 unsigned OffsetIdx = OptionalIdx[AMDGPUOperand::ImmTyOffset];
1546 unsigned GLCIdx = OptionalIdx[AMDGPUOperand::ImmTyGLC];
1547 unsigned SLCIdx = OptionalIdx[AMDGPUOperand::ImmTySLC];
1548 unsigned TFEIdx = OptionalIdx[AMDGPUOperand::ImmTyTFE];
1549
1550 ((AMDGPUOperand &)*Operands[OffsetIdx]).addImmOperands(Inst, 1);
1551 ((AMDGPUOperand &)*Operands[GLCIdx]).addImmOperands(Inst, 1);
1552 ((AMDGPUOperand &)*Operands[SLCIdx]).addImmOperands(Inst, 1);
1553 ((AMDGPUOperand &)*Operands[TFEIdx]).addImmOperands(Inst, 1);
1554}
1555
1556//===----------------------------------------------------------------------===//
1557// mimg
1558//===----------------------------------------------------------------------===//
1559
1560AMDGPUAsmParser::OperandMatchResultTy
1561AMDGPUAsmParser::parseDMask(OperandVector &Operands) {
1562 return parseIntWithPrefix("dmask", Operands);
1563}
1564
1565AMDGPUAsmParser::OperandMatchResultTy
1566AMDGPUAsmParser::parseUNorm(OperandVector &Operands) {
1567 return parseNamedBit("unorm", Operands);
1568}
1569
1570AMDGPUAsmParser::OperandMatchResultTy
1571AMDGPUAsmParser::parseR128(OperandVector &Operands) {
1572 return parseNamedBit("r128", Operands);
1573}
1574
1575//===----------------------------------------------------------------------===//
Tom Stellard217361c2015-08-06 19:28:38 +00001576// smrd
1577//===----------------------------------------------------------------------===//
1578
1579bool AMDGPUOperand::isSMRDOffset() const {
1580
1581 // FIXME: Support 20-bit offsets on VI. We need to to pass subtarget
1582 // information here.
1583 return isImm() && isUInt<8>(getImm());
1584}
1585
1586bool AMDGPUOperand::isSMRDLiteralOffset() const {
1587 // 32-bit literals are only supported on CI and we only want to use them
1588 // when the offset is > 8-bits.
1589 return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm());
1590}
1591
1592//===----------------------------------------------------------------------===//
Tom Stellard45bb48e2015-06-13 03:28:10 +00001593// vop3
1594//===----------------------------------------------------------------------===//
1595
1596static bool ConvertOmodMul(int64_t &Mul) {
1597 if (Mul != 1 && Mul != 2 && Mul != 4)
1598 return false;
1599
1600 Mul >>= 1;
1601 return true;
1602}
1603
1604static bool ConvertOmodDiv(int64_t &Div) {
1605 if (Div == 1) {
1606 Div = 0;
1607 return true;
1608 }
1609
1610 if (Div == 2) {
1611 Div = 3;
1612 return true;
1613 }
1614
1615 return false;
1616}
1617
1618static const OptionalOperand VOP3OptionalOps [] = {
1619 {"clamp", AMDGPUOperand::ImmTyClamp, true, 0, nullptr},
1620 {"mul", AMDGPUOperand::ImmTyOMod, false, 1, ConvertOmodMul},
1621 {"div", AMDGPUOperand::ImmTyOMod, false, 1, ConvertOmodDiv},
1622};
1623
1624static bool isVOP3(OperandVector &Operands) {
1625 if (operandsHaveModifiers(Operands))
1626 return true;
1627
1628 AMDGPUOperand &DstOp = ((AMDGPUOperand&)*Operands[1]);
1629
1630 if (DstOp.isReg() && DstOp.isRegClass(AMDGPU::SGPR_64RegClassID))
1631 return true;
1632
1633 if (Operands.size() >= 5)
1634 return true;
1635
1636 if (Operands.size() > 3) {
1637 AMDGPUOperand &Src1Op = ((AMDGPUOperand&)*Operands[3]);
1638 if (Src1Op.getReg() && (Src1Op.isRegClass(AMDGPU::SReg_32RegClassID) ||
1639 Src1Op.isRegClass(AMDGPU::SReg_64RegClassID)))
1640 return true;
1641 }
1642 return false;
1643}
1644
1645AMDGPUAsmParser::OperandMatchResultTy
1646AMDGPUAsmParser::parseVOP3OptionalOps(OperandVector &Operands) {
1647
1648 // The value returned by this function may change after parsing
1649 // an operand so store the original value here.
1650 bool HasModifiers = operandsHaveModifiers(Operands);
1651
1652 bool IsVOP3 = isVOP3(Operands);
1653 if (HasModifiers || IsVOP3 ||
1654 getLexer().isNot(AsmToken::EndOfStatement) ||
1655 getForcedEncodingSize() == 64) {
1656
1657 AMDGPUAsmParser::OperandMatchResultTy Res =
1658 parseOptionalOps(VOP3OptionalOps, Operands);
1659
1660 if (!HasModifiers && Res == MatchOperand_Success) {
1661 // We have added a modifier operation, so we need to make sure all
1662 // previous register operands have modifiers
1663 for (unsigned i = 2, e = Operands.size(); i != e; ++i) {
1664 AMDGPUOperand &Op = ((AMDGPUOperand&)*Operands[i]);
1665 if (Op.isReg())
1666 Op.setModifiers(0);
1667 }
1668 }
1669 return Res;
1670 }
1671 return MatchOperand_NoMatch;
1672}
1673
1674void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) {
1675 ((AMDGPUOperand &)*Operands[1]).addRegOperands(Inst, 1);
1676 unsigned i = 2;
1677
1678 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx;
1679
1680 if (operandsHaveModifiers(Operands)) {
1681 for (unsigned e = Operands.size(); i != e; ++i) {
1682 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
1683
1684 if (Op.isRegWithInputMods()) {
1685 ((AMDGPUOperand &)*Operands[i]).addRegWithInputModsOperands(Inst, 2);
1686 continue;
1687 }
1688 OptionalIdx[Op.getImmTy()] = i;
1689 }
1690
1691 unsigned ClampIdx = OptionalIdx[AMDGPUOperand::ImmTyClamp];
1692 unsigned OModIdx = OptionalIdx[AMDGPUOperand::ImmTyOMod];
1693
1694 ((AMDGPUOperand &)*Operands[ClampIdx]).addImmOperands(Inst, 1);
1695 ((AMDGPUOperand &)*Operands[OModIdx]).addImmOperands(Inst, 1);
1696 } else {
1697 for (unsigned e = Operands.size(); i != e; ++i)
1698 ((AMDGPUOperand &)*Operands[i]).addRegOrImmOperands(Inst, 1);
1699 }
1700}
1701
1702/// Force static initialization.
1703extern "C" void LLVMInitializeAMDGPUAsmParser() {
1704 RegisterMCAsmParser<AMDGPUAsmParser> A(TheAMDGPUTarget);
1705 RegisterMCAsmParser<AMDGPUAsmParser> B(TheGCNTarget);
1706}
1707
1708#define GET_REGISTER_MATCHER
1709#define GET_MATCHER_IMPLEMENTATION
1710#include "AMDGPUGenAsmMatcher.inc"
1711