blob: 78ac9dda03573772d95bdcbc293ed3f9ee9a2a0b [file] [log] [blame]
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001//===- AMDGPUAsmParser.cpp - Parse SI asm to MCInst instructions ----------===//
Tom Stellard45bb48e2015-06-13 03:28:10 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Tom Stellard45bb48e2015-06-13 03:28:10 +00006//
7//===----------------------------------------------------------------------===//
8
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00009#include "AMDGPU.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000010#include "AMDKernelCodeT.h"
Tom Stellard45bb48e2015-06-13 03:28:10 +000011#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
Tom Stellard347ac792015-06-26 21:15:07 +000012#include "MCTargetDesc/AMDGPUTargetStreamer.h"
Tom Stellard45bb48e2015-06-13 03:28:10 +000013#include "SIDefines.h"
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +000014#include "SIInstrInfo.h"
Richard Trieu8ce2ee92019-05-14 21:54:37 +000015#include "TargetInfo/AMDGPUTargetInfo.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000016#include "Utils/AMDGPUAsmUtils.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000017#include "Utils/AMDGPUBaseInfo.h"
Valery Pykhtindc110542016-03-06 20:25:36 +000018#include "Utils/AMDKernelCodeTUtils.h"
Tom Stellard45bb48e2015-06-13 03:28:10 +000019#include "llvm/ADT/APFloat.h"
Eugene Zelenko2bc2f332016-12-09 22:06:55 +000020#include "llvm/ADT/APInt.h"
Eugene Zelenko66203762017-01-21 00:53:49 +000021#include "llvm/ADT/ArrayRef.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000022#include "llvm/ADT/STLExtras.h"
Sam Kolton5f10a132016-05-06 11:31:17 +000023#include "llvm/ADT/SmallBitVector.h"
Tom Stellard45bb48e2015-06-13 03:28:10 +000024#include "llvm/ADT/SmallString.h"
Eugene Zelenko2bc2f332016-12-09 22:06:55 +000025#include "llvm/ADT/StringRef.h"
Tom Stellard45bb48e2015-06-13 03:28:10 +000026#include "llvm/ADT/StringSwitch.h"
27#include "llvm/ADT/Twine.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000028#include "llvm/BinaryFormat/ELF.h"
Sam Kolton69c8aa22016-12-19 11:43:15 +000029#include "llvm/MC/MCAsmInfo.h"
Tom Stellard45bb48e2015-06-13 03:28:10 +000030#include "llvm/MC/MCContext.h"
31#include "llvm/MC/MCExpr.h"
32#include "llvm/MC/MCInst.h"
Eugene Zelenko2bc2f332016-12-09 22:06:55 +000033#include "llvm/MC/MCInstrDesc.h"
Tom Stellard45bb48e2015-06-13 03:28:10 +000034#include "llvm/MC/MCInstrInfo.h"
35#include "llvm/MC/MCParser/MCAsmLexer.h"
36#include "llvm/MC/MCParser/MCAsmParser.h"
Eugene Zelenko2bc2f332016-12-09 22:06:55 +000037#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Tom Stellard45bb48e2015-06-13 03:28:10 +000038#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000039#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Tom Stellard45bb48e2015-06-13 03:28:10 +000040#include "llvm/MC/MCRegisterInfo.h"
41#include "llvm/MC/MCStreamer.h"
42#include "llvm/MC/MCSubtargetInfo.h"
Eugene Zelenko2bc2f332016-12-09 22:06:55 +000043#include "llvm/MC/MCSymbol.h"
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +000044#include "llvm/Support/AMDGPUMetadata.h"
Scott Linder1e8c2c72018-06-21 19:38:56 +000045#include "llvm/Support/AMDHSAKernelDescriptor.h"
Eugene Zelenko2bc2f332016-12-09 22:06:55 +000046#include "llvm/Support/Casting.h"
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +000047#include "llvm/Support/Compiler.h"
Eugene Zelenko2bc2f332016-12-09 22:06:55 +000048#include "llvm/Support/ErrorHandling.h"
David Blaikie13e77db2018-03-23 23:58:25 +000049#include "llvm/Support/MachineValueType.h"
Artem Tamazov6edc1352016-05-26 17:00:33 +000050#include "llvm/Support/MathExtras.h"
Eugene Zelenko2bc2f332016-12-09 22:06:55 +000051#include "llvm/Support/SMLoc.h"
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +000052#include "llvm/Support/TargetParser.h"
Eugene Zelenko2bc2f332016-12-09 22:06:55 +000053#include "llvm/Support/TargetRegistry.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000054#include "llvm/Support/raw_ostream.h"
Eugene Zelenko2bc2f332016-12-09 22:06:55 +000055#include <algorithm>
56#include <cassert>
57#include <cstdint>
58#include <cstring>
59#include <iterator>
60#include <map>
61#include <memory>
62#include <string>
Artem Tamazovebe71ce2016-05-06 17:48:48 +000063
Tom Stellard45bb48e2015-06-13 03:28:10 +000064using namespace llvm;
Konstantin Zhuravlyov836cbff2016-09-30 17:01:40 +000065using namespace llvm::AMDGPU;
Scott Linder1e8c2c72018-06-21 19:38:56 +000066using namespace llvm::amdhsa;
Tom Stellard45bb48e2015-06-13 03:28:10 +000067
68namespace {
69
Sam Kolton1eeb11b2016-09-09 14:44:04 +000070class AMDGPUAsmParser;
Tom Stellard45bb48e2015-06-13 03:28:10 +000071
Nikolay Haustovfb5c3072016-04-20 09:34:48 +000072enum RegisterKind { IS_UNKNOWN, IS_VGPR, IS_SGPR, IS_TTMP, IS_SPECIAL };
73
Sam Kolton1eeb11b2016-09-09 14:44:04 +000074//===----------------------------------------------------------------------===//
75// Operand
76//===----------------------------------------------------------------------===//
77
Tom Stellard45bb48e2015-06-13 03:28:10 +000078class AMDGPUOperand : public MCParsedAsmOperand {
79 enum KindTy {
80 Token,
81 Immediate,
82 Register,
83 Expression
84 } Kind;
85
86 SMLoc StartLoc, EndLoc;
Sam Kolton1eeb11b2016-09-09 14:44:04 +000087 const AMDGPUAsmParser *AsmParser;
Tom Stellard45bb48e2015-06-13 03:28:10 +000088
89public:
Matt Arsenaultf15da6c2017-02-03 20:49:51 +000090 AMDGPUOperand(KindTy Kind_, const AMDGPUAsmParser *AsmParser_)
Sam Kolton1eeb11b2016-09-09 14:44:04 +000091 : MCParsedAsmOperand(), Kind(Kind_), AsmParser(AsmParser_) {}
Tom Stellard45bb48e2015-06-13 03:28:10 +000092
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +000093 using Ptr = std::unique_ptr<AMDGPUOperand>;
Sam Kolton5f10a132016-05-06 11:31:17 +000094
Sam Kolton945231a2016-06-10 09:57:59 +000095 struct Modifiers {
Matt Arsenaultb55f6202016-12-03 18:22:49 +000096 bool Abs = false;
97 bool Neg = false;
98 bool Sext = false;
Sam Kolton945231a2016-06-10 09:57:59 +000099
100 bool hasFPModifiers() const { return Abs || Neg; }
101 bool hasIntModifiers() const { return Sext; }
102 bool hasModifiers() const { return hasFPModifiers() || hasIntModifiers(); }
103
104 int64_t getFPModifiersOperand() const {
105 int64_t Operand = 0;
Stanislav Mekhanoshinda644c02019-03-13 21:15:52 +0000106 Operand |= Abs ? SISrcMods::ABS : 0u;
107 Operand |= Neg ? SISrcMods::NEG : 0u;
Sam Kolton945231a2016-06-10 09:57:59 +0000108 return Operand;
109 }
110
111 int64_t getIntModifiersOperand() const {
112 int64_t Operand = 0;
Stanislav Mekhanoshinda644c02019-03-13 21:15:52 +0000113 Operand |= Sext ? SISrcMods::SEXT : 0u;
Sam Kolton945231a2016-06-10 09:57:59 +0000114 return Operand;
115 }
116
117 int64_t getModifiersOperand() const {
118 assert(!(hasFPModifiers() && hasIntModifiers())
119 && "fp and int modifiers should not be used simultaneously");
120 if (hasFPModifiers()) {
121 return getFPModifiersOperand();
122 } else if (hasIntModifiers()) {
123 return getIntModifiersOperand();
124 } else {
125 return 0;
126 }
127 }
128
129 friend raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods);
130 };
131
Tom Stellard45bb48e2015-06-13 03:28:10 +0000132 enum ImmTy {
133 ImmTyNone,
Tom Stellard45bb48e2015-06-13 03:28:10 +0000134 ImmTyGDS,
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +0000135 ImmTyLDS,
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000136 ImmTyOffen,
137 ImmTyIdxen,
138 ImmTyAddr64,
Tom Stellard45bb48e2015-06-13 03:28:10 +0000139 ImmTyOffset,
Dmitry Preobrazhenskydd2f1c92017-11-24 13:22:38 +0000140 ImmTyInstOffset,
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000141 ImmTyOffset0,
142 ImmTyOffset1,
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +0000143 ImmTyDLC,
Tom Stellard45bb48e2015-06-13 03:28:10 +0000144 ImmTyGLC,
145 ImmTySLC,
146 ImmTyTFE,
Dmitry Preobrazhensky4f321ae2018-01-29 14:20:42 +0000147 ImmTyD16,
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000148 ImmTyClampSI,
149 ImmTyOModSI,
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +0000150 ImmTyDPP8,
Sam Koltondfa29f72016-03-09 12:29:31 +0000151 ImmTyDppCtrl,
152 ImmTyDppRowMask,
153 ImmTyDppBankMask,
154 ImmTyDppBoundCtrl,
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +0000155 ImmTyDppFi,
Sam Kolton05ef1c92016-06-03 10:27:37 +0000156 ImmTySdwaDstSel,
157 ImmTySdwaSrc0Sel,
158 ImmTySdwaSrc1Sel,
Sam Kolton3025e7f2016-04-26 13:33:56 +0000159 ImmTySdwaDstUnused,
Nikolay Haustov2f684f12016-02-26 09:51:05 +0000160 ImmTyDMask,
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +0000161 ImmTyDim,
Nikolay Haustov2f684f12016-02-26 09:51:05 +0000162 ImmTyUNorm,
163 ImmTyDA,
Ryan Taylor1f334d02018-08-28 15:07:30 +0000164 ImmTyR128A16,
Nikolay Haustov2f684f12016-02-26 09:51:05 +0000165 ImmTyLWE,
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +0000166 ImmTyExpTgt,
Matt Arsenault8a63cb92016-12-05 20:31:49 +0000167 ImmTyExpCompr,
168 ImmTyExpVM,
Tim Renouf35484c92018-08-21 11:06:05 +0000169 ImmTyFORMAT,
Artem Tamazovd6468662016-04-25 14:13:51 +0000170 ImmTyHwreg,
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +0000171 ImmTyOff,
Artem Tamazovebe71ce2016-05-06 17:48:48 +0000172 ImmTySendMsg,
Matt Arsenault0e8a2992016-12-15 20:40:20 +0000173 ImmTyInterpSlot,
174 ImmTyInterpAttr,
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000175 ImmTyAttrChan,
176 ImmTyOpSel,
177 ImmTyOpSelHi,
178 ImmTyNegLo,
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +0000179 ImmTyNegHi,
Dmitry Preobrazhensky50805a02017-08-07 13:14:12 +0000180 ImmTySwizzle,
Dmitry Preobrazhenskyef920352019-02-27 13:12:12 +0000181 ImmTyGprIdxMode,
David Stuttard20ea21c2019-03-12 09:52:58 +0000182 ImmTyEndpgm,
Dmitry Preobrazhensky50805a02017-08-07 13:14:12 +0000183 ImmTyHigh
Tom Stellard45bb48e2015-06-13 03:28:10 +0000184 };
185
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +0000186private:
Tom Stellard45bb48e2015-06-13 03:28:10 +0000187 struct TokOp {
188 const char *Data;
189 unsigned Length;
190 };
191
192 struct ImmOp {
Tom Stellard45bb48e2015-06-13 03:28:10 +0000193 int64_t Val;
Matt Arsenault7f192982016-08-16 20:28:06 +0000194 ImmTy Type;
195 bool IsFPImm;
Sam Kolton945231a2016-06-10 09:57:59 +0000196 Modifiers Mods;
Tom Stellard45bb48e2015-06-13 03:28:10 +0000197 };
198
199 struct RegOp {
Matt Arsenault7f192982016-08-16 20:28:06 +0000200 unsigned RegNo;
Matt Arsenault7f192982016-08-16 20:28:06 +0000201 Modifiers Mods;
Tom Stellard45bb48e2015-06-13 03:28:10 +0000202 };
203
204 union {
205 TokOp Tok;
206 ImmOp Imm;
207 RegOp Reg;
208 const MCExpr *Expr;
209 };
210
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +0000211public:
Tom Stellard45bb48e2015-06-13 03:28:10 +0000212 bool isToken() const override {
Tom Stellard89049702016-06-15 02:54:14 +0000213 if (Kind == Token)
214 return true;
215
216 if (Kind != Expression || !Expr)
217 return false;
218
219 // When parsing operands, we can't always tell if something was meant to be
220 // a token, like 'gds', or an expression that references a global variable.
221 // In this case, we assume the string is an expression, and if we need to
222 // interpret is a token, then we treat the symbol name as the token.
223 return isa<MCSymbolRefExpr>(Expr);
Tom Stellard45bb48e2015-06-13 03:28:10 +0000224 }
225
226 bool isImm() const override {
227 return Kind == Immediate;
228 }
229
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000230 bool isInlinableImm(MVT type) const;
231 bool isLiteralImm(MVT type) const;
Tom Stellard45bb48e2015-06-13 03:28:10 +0000232
Tom Stellard45bb48e2015-06-13 03:28:10 +0000233 bool isRegKind() const {
234 return Kind == Register;
235 }
236
237 bool isReg() const override {
Sam Kolton9772eb32017-01-11 11:46:30 +0000238 return isRegKind() && !hasModifiers();
Tom Stellard45bb48e2015-06-13 03:28:10 +0000239 }
240
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +0000241 bool isRegOrImmWithInputMods(unsigned RCID, MVT type) const {
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +0000242 return isRegClass(RCID) || isInlinableImm(type) || isLiteralImm(type);
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000243 }
244
Matt Arsenault4bd72362016-12-10 00:39:12 +0000245 bool isRegOrImmWithInt16InputMods() const {
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +0000246 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::i16);
Matt Arsenault4bd72362016-12-10 00:39:12 +0000247 }
248
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000249 bool isRegOrImmWithInt32InputMods() const {
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +0000250 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::i32);
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000251 }
252
253 bool isRegOrImmWithInt64InputMods() const {
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +0000254 return isRegOrImmWithInputMods(AMDGPU::VS_64RegClassID, MVT::i64);
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000255 }
256
Matt Arsenault4bd72362016-12-10 00:39:12 +0000257 bool isRegOrImmWithFP16InputMods() const {
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +0000258 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::f16);
Matt Arsenault4bd72362016-12-10 00:39:12 +0000259 }
260
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000261 bool isRegOrImmWithFP32InputMods() const {
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +0000262 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::f32);
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000263 }
264
265 bool isRegOrImmWithFP64InputMods() const {
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +0000266 return isRegOrImmWithInputMods(AMDGPU::VS_64RegClassID, MVT::f64);
Tom Stellarda90b9522016-02-11 03:28:15 +0000267 }
268
Sam Kolton9772eb32017-01-11 11:46:30 +0000269 bool isVReg() const {
270 return isRegClass(AMDGPU::VGPR_32RegClassID) ||
271 isRegClass(AMDGPU::VReg_64RegClassID) ||
272 isRegClass(AMDGPU::VReg_96RegClassID) ||
273 isRegClass(AMDGPU::VReg_128RegClassID) ||
274 isRegClass(AMDGPU::VReg_256RegClassID) ||
275 isRegClass(AMDGPU::VReg_512RegClassID);
276 }
277
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +0000278 bool isVReg32() const {
279 return isRegClass(AMDGPU::VGPR_32RegClassID);
280 }
281
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +0000282 bool isVReg32OrOff() const {
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +0000283 return isOff() || isVReg32();
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +0000284 }
285
Dmitry Preobrazhensky6b65f7c2018-01-17 14:00:48 +0000286 bool isSDWAOperand(MVT type) const;
287 bool isSDWAFP16Operand() const;
288 bool isSDWAFP32Operand() const;
289 bool isSDWAInt16Operand() const;
290 bool isSDWAInt32Operand() const;
Sam Kolton549c89d2017-06-21 08:53:38 +0000291
Nikolay Haustov2f684f12016-02-26 09:51:05 +0000292 bool isImmTy(ImmTy ImmT) const {
293 return isImm() && Imm.Type == ImmT;
294 }
Matt Arsenaultf3dd8632016-11-01 00:55:14 +0000295
Nikolay Haustov2f684f12016-02-26 09:51:05 +0000296 bool isImmModifier() const {
Sam Kolton945231a2016-06-10 09:57:59 +0000297 return isImm() && Imm.Type != ImmTyNone;
Nikolay Haustov2f684f12016-02-26 09:51:05 +0000298 }
Matt Arsenaultf3dd8632016-11-01 00:55:14 +0000299
Sam Kolton945231a2016-06-10 09:57:59 +0000300 bool isClampSI() const { return isImmTy(ImmTyClampSI); }
301 bool isOModSI() const { return isImmTy(ImmTyOModSI); }
302 bool isDMask() const { return isImmTy(ImmTyDMask); }
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +0000303 bool isDim() const { return isImmTy(ImmTyDim); }
Nikolay Haustov2f684f12016-02-26 09:51:05 +0000304 bool isUNorm() const { return isImmTy(ImmTyUNorm); }
305 bool isDA() const { return isImmTy(ImmTyDA); }
Ryan Taylor1f334d02018-08-28 15:07:30 +0000306 bool isR128A16() const { return isImmTy(ImmTyR128A16); }
Nikolay Haustov2f684f12016-02-26 09:51:05 +0000307 bool isLWE() const { return isImmTy(ImmTyLWE); }
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +0000308 bool isOff() const { return isImmTy(ImmTyOff); }
309 bool isExpTgt() const { return isImmTy(ImmTyExpTgt); }
Matt Arsenault8a63cb92016-12-05 20:31:49 +0000310 bool isExpVM() const { return isImmTy(ImmTyExpVM); }
311 bool isExpCompr() const { return isImmTy(ImmTyExpCompr); }
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000312 bool isOffen() const { return isImmTy(ImmTyOffen); }
313 bool isIdxen() const { return isImmTy(ImmTyIdxen); }
314 bool isAddr64() const { return isImmTy(ImmTyAddr64); }
315 bool isOffset() const { return isImmTy(ImmTyOffset) && isUInt<16>(getImm()); }
Dmitry Preobrazhensky04bd1182019-03-20 17:13:58 +0000316 bool isOffset0() const { return isImmTy(ImmTyOffset0) && isUInt<8>(getImm()); }
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000317 bool isOffset1() const { return isImmTy(ImmTyOffset1) && isUInt<8>(getImm()); }
Matt Arsenaultfd023142017-06-12 15:55:58 +0000318
Dmitry Preobrazhenskydd2f1c92017-11-24 13:22:38 +0000319 bool isOffsetU12() const { return (isImmTy(ImmTyOffset) || isImmTy(ImmTyInstOffset)) && isUInt<12>(getImm()); }
320 bool isOffsetS13() const { return (isImmTy(ImmTyOffset) || isImmTy(ImmTyInstOffset)) && isInt<13>(getImm()); }
Nikolay Haustovea8febd2016-03-01 08:34:43 +0000321 bool isGDS() const { return isImmTy(ImmTyGDS); }
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +0000322 bool isLDS() const { return isImmTy(ImmTyLDS); }
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +0000323 bool isDLC() const { return isImmTy(ImmTyDLC); }
Nikolay Haustovea8febd2016-03-01 08:34:43 +0000324 bool isGLC() const { return isImmTy(ImmTyGLC); }
325 bool isSLC() const { return isImmTy(ImmTySLC); }
326 bool isTFE() const { return isImmTy(ImmTyTFE); }
Dmitry Preobrazhensky4f321ae2018-01-29 14:20:42 +0000327 bool isD16() const { return isImmTy(ImmTyD16); }
Tim Renouf35484c92018-08-21 11:06:05 +0000328 bool isFORMAT() const { return isImmTy(ImmTyFORMAT) && isUInt<8>(getImm()); }
Sam Kolton945231a2016-06-10 09:57:59 +0000329 bool isBankMask() const { return isImmTy(ImmTyDppBankMask); }
330 bool isRowMask() const { return isImmTy(ImmTyDppRowMask); }
331 bool isBoundCtrl() const { return isImmTy(ImmTyDppBoundCtrl); }
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +0000332 bool isFI() const { return isImmTy(ImmTyDppFi); }
Sam Kolton945231a2016-06-10 09:57:59 +0000333 bool isSDWADstSel() const { return isImmTy(ImmTySdwaDstSel); }
334 bool isSDWASrc0Sel() const { return isImmTy(ImmTySdwaSrc0Sel); }
335 bool isSDWASrc1Sel() const { return isImmTy(ImmTySdwaSrc1Sel); }
336 bool isSDWADstUnused() const { return isImmTy(ImmTySdwaDstUnused); }
Matt Arsenault0e8a2992016-12-15 20:40:20 +0000337 bool isInterpSlot() const { return isImmTy(ImmTyInterpSlot); }
338 bool isInterpAttr() const { return isImmTy(ImmTyInterpAttr); }
339 bool isAttrChan() const { return isImmTy(ImmTyAttrChan); }
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000340 bool isOpSel() const { return isImmTy(ImmTyOpSel); }
341 bool isOpSelHi() const { return isImmTy(ImmTyOpSelHi); }
342 bool isNegLo() const { return isImmTy(ImmTyNegLo); }
343 bool isNegHi() const { return isImmTy(ImmTyNegHi); }
Dmitry Preobrazhensky50805a02017-08-07 13:14:12 +0000344 bool isHigh() const { return isImmTy(ImmTyHigh); }
Matt Arsenaultf3dd8632016-11-01 00:55:14 +0000345
Sam Kolton945231a2016-06-10 09:57:59 +0000346 bool isMod() const {
347 return isClampSI() || isOModSI();
Tom Stellard45bb48e2015-06-13 03:28:10 +0000348 }
349
350 bool isRegOrImm() const {
351 return isReg() || isImm();
352 }
353
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000354 bool isRegClass(unsigned RCID) const;
355
Dmitry Preobrazhensky137976f2019-03-20 15:40:52 +0000356 bool isInlineValue() const;
357
Sam Kolton9772eb32017-01-11 11:46:30 +0000358 bool isRegOrInlineNoMods(unsigned RCID, MVT type) const {
359 return (isRegClass(RCID) || isInlinableImm(type)) && !hasModifiers();
360 }
361
Matt Arsenault4bd72362016-12-10 00:39:12 +0000362 bool isSCSrcB16() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000363 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i16);
Matt Arsenault4bd72362016-12-10 00:39:12 +0000364 }
365
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000366 bool isSCSrcV2B16() const {
367 return isSCSrcB16();
368 }
369
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000370 bool isSCSrcB32() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000371 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i32);
Tom Stellard45bb48e2015-06-13 03:28:10 +0000372 }
373
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000374 bool isSCSrcB64() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000375 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::i64);
Tom Stellard45bb48e2015-06-13 03:28:10 +0000376 }
377
Matt Arsenault4bd72362016-12-10 00:39:12 +0000378 bool isSCSrcF16() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000379 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f16);
Matt Arsenault4bd72362016-12-10 00:39:12 +0000380 }
381
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000382 bool isSCSrcV2F16() const {
383 return isSCSrcF16();
384 }
385
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000386 bool isSCSrcF32() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000387 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f32);
Tom Stellardd93a34f2016-02-22 19:17:56 +0000388 }
389
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000390 bool isSCSrcF64() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000391 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::f64);
Tom Stellardd93a34f2016-02-22 19:17:56 +0000392 }
393
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000394 bool isSSrcB32() const {
395 return isSCSrcB32() || isLiteralImm(MVT::i32) || isExpr();
396 }
397
Matt Arsenault4bd72362016-12-10 00:39:12 +0000398 bool isSSrcB16() const {
399 return isSCSrcB16() || isLiteralImm(MVT::i16);
400 }
401
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000402 bool isSSrcV2B16() const {
403 llvm_unreachable("cannot happen");
404 return isSSrcB16();
405 }
406
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000407 bool isSSrcB64() const {
Tom Stellardd93a34f2016-02-22 19:17:56 +0000408 // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits.
409 // See isVSrc64().
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000410 return isSCSrcB64() || isLiteralImm(MVT::i64);
Matt Arsenault86d336e2015-09-08 21:15:00 +0000411 }
412
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000413 bool isSSrcF32() const {
414 return isSCSrcB32() || isLiteralImm(MVT::f32) || isExpr();
Tom Stellard45bb48e2015-06-13 03:28:10 +0000415 }
416
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000417 bool isSSrcF64() const {
418 return isSCSrcB64() || isLiteralImm(MVT::f64);
Tom Stellard45bb48e2015-06-13 03:28:10 +0000419 }
420
Matt Arsenault4bd72362016-12-10 00:39:12 +0000421 bool isSSrcF16() const {
422 return isSCSrcB16() || isLiteralImm(MVT::f16);
423 }
424
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000425 bool isSSrcV2F16() const {
426 llvm_unreachable("cannot happen");
427 return isSSrcF16();
428 }
429
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +0000430 bool isSSrcOrLdsB32() const {
431 return isRegOrInlineNoMods(AMDGPU::SRegOrLds_32RegClassID, MVT::i32) ||
432 isLiteralImm(MVT::i32) || isExpr();
433 }
434
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000435 bool isVCSrcB32() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000436 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i32);
Tom Stellard45bb48e2015-06-13 03:28:10 +0000437 }
438
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000439 bool isVCSrcB64() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000440 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::i64);
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000441 }
Matt Arsenaultf3dd8632016-11-01 00:55:14 +0000442
Matt Arsenault4bd72362016-12-10 00:39:12 +0000443 bool isVCSrcB16() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000444 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i16);
Matt Arsenault4bd72362016-12-10 00:39:12 +0000445 }
446
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000447 bool isVCSrcV2B16() const {
448 return isVCSrcB16();
449 }
450
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000451 bool isVCSrcF32() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000452 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f32);
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000453 }
454
455 bool isVCSrcF64() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000456 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::f64);
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000457 }
458
Matt Arsenault4bd72362016-12-10 00:39:12 +0000459 bool isVCSrcF16() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000460 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f16);
Matt Arsenault4bd72362016-12-10 00:39:12 +0000461 }
462
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000463 bool isVCSrcV2F16() const {
464 return isVCSrcF16();
465 }
466
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000467 bool isVSrcB32() const {
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +0000468 return isVCSrcF32() || isLiteralImm(MVT::i32) || isExpr();
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000469 }
470
471 bool isVSrcB64() const {
472 return isVCSrcF64() || isLiteralImm(MVT::i64);
473 }
474
Matt Arsenault4bd72362016-12-10 00:39:12 +0000475 bool isVSrcB16() const {
476 return isVCSrcF16() || isLiteralImm(MVT::i16);
477 }
478
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000479 bool isVSrcV2B16() const {
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +0000480 return isVSrcB16() || isLiteralImm(MVT::v2i16);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000481 }
482
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000483 bool isVSrcF32() const {
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +0000484 return isVCSrcF32() || isLiteralImm(MVT::f32) || isExpr();
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000485 }
486
487 bool isVSrcF64() const {
488 return isVCSrcF64() || isLiteralImm(MVT::f64);
489 }
490
Matt Arsenault4bd72362016-12-10 00:39:12 +0000491 bool isVSrcF16() const {
492 return isVCSrcF16() || isLiteralImm(MVT::f16);
493 }
494
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000495 bool isVSrcV2F16() const {
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +0000496 return isVSrcF16() || isLiteralImm(MVT::v2f16);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000497 }
498
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000499 bool isKImmFP32() const {
500 return isLiteralImm(MVT::f32);
Tom Stellard45bb48e2015-06-13 03:28:10 +0000501 }
502
Matt Arsenault4bd72362016-12-10 00:39:12 +0000503 bool isKImmFP16() const {
504 return isLiteralImm(MVT::f16);
505 }
506
Tom Stellard45bb48e2015-06-13 03:28:10 +0000507 bool isMem() const override {
508 return false;
509 }
510
511 bool isExpr() const {
512 return Kind == Expression;
513 }
514
515 bool isSoppBrTarget() const {
516 return isExpr() || isImm();
517 }
518
Sam Kolton945231a2016-06-10 09:57:59 +0000519 bool isSWaitCnt() const;
520 bool isHwreg() const;
521 bool isSendMsg() const;
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +0000522 bool isSwizzle() const;
Artem Tamazov54bfd542016-10-31 16:07:39 +0000523 bool isSMRDOffset8() const;
524 bool isSMRDOffset20() const;
Sam Kolton945231a2016-06-10 09:57:59 +0000525 bool isSMRDLiteralOffset() const;
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +0000526 bool isDPP8() const;
Sam Kolton945231a2016-06-10 09:57:59 +0000527 bool isDPPCtrl() const;
Matt Arsenaultcc88ce32016-10-12 18:00:51 +0000528 bool isGPRIdxMode() const;
Dmitry Preobrazhenskyc7d35a02017-04-26 15:34:19 +0000529 bool isS16Imm() const;
530 bool isU16Imm() const;
David Stuttard20ea21c2019-03-12 09:52:58 +0000531 bool isEndpgm() const;
Sam Kolton945231a2016-06-10 09:57:59 +0000532
Tom Stellard89049702016-06-15 02:54:14 +0000533 StringRef getExpressionAsToken() const {
534 assert(isExpr());
535 const MCSymbolRefExpr *S = cast<MCSymbolRefExpr>(Expr);
536 return S->getSymbol().getName();
537 }
538
Sam Kolton945231a2016-06-10 09:57:59 +0000539 StringRef getToken() const {
Tom Stellard89049702016-06-15 02:54:14 +0000540 assert(isToken());
541
542 if (Kind == Expression)
543 return getExpressionAsToken();
544
Sam Kolton945231a2016-06-10 09:57:59 +0000545 return StringRef(Tok.Data, Tok.Length);
546 }
547
548 int64_t getImm() const {
549 assert(isImm());
550 return Imm.Val;
551 }
552
Matt Arsenaultf15da6c2017-02-03 20:49:51 +0000553 ImmTy getImmTy() const {
Sam Kolton945231a2016-06-10 09:57:59 +0000554 assert(isImm());
555 return Imm.Type;
556 }
557
558 unsigned getReg() const override {
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +0000559 assert(isRegKind());
Sam Kolton945231a2016-06-10 09:57:59 +0000560 return Reg.RegNo;
561 }
562
Tom Stellard45bb48e2015-06-13 03:28:10 +0000563 SMLoc getStartLoc() const override {
564 return StartLoc;
565 }
566
Peter Collingbourne0da86302016-10-10 22:49:37 +0000567 SMLoc getEndLoc() const override {
Tom Stellard45bb48e2015-06-13 03:28:10 +0000568 return EndLoc;
569 }
570
Matt Arsenaultf7f59b52017-12-20 18:52:57 +0000571 SMRange getLocRange() const {
572 return SMRange(StartLoc, EndLoc);
573 }
574
Sam Kolton945231a2016-06-10 09:57:59 +0000575 Modifiers getModifiers() const {
576 assert(isRegKind() || isImmTy(ImmTyNone));
577 return isRegKind() ? Reg.Mods : Imm.Mods;
578 }
579
580 void setModifiers(Modifiers Mods) {
581 assert(isRegKind() || isImmTy(ImmTyNone));
582 if (isRegKind())
583 Reg.Mods = Mods;
584 else
585 Imm.Mods = Mods;
586 }
587
588 bool hasModifiers() const {
589 return getModifiers().hasModifiers();
590 }
Matt Arsenaultf3dd8632016-11-01 00:55:14 +0000591
Sam Kolton945231a2016-06-10 09:57:59 +0000592 bool hasFPModifiers() const {
593 return getModifiers().hasFPModifiers();
594 }
595
596 bool hasIntModifiers() const {
597 return getModifiers().hasIntModifiers();
598 }
599
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +0000600 uint64_t applyInputFPModifiers(uint64_t Val, unsigned Size) const;
601
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000602 void addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers = true) const;
Sam Kolton945231a2016-06-10 09:57:59 +0000603
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +0000604 void addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const;
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000605
Matt Arsenault4bd72362016-12-10 00:39:12 +0000606 template <unsigned Bitwidth>
607 void addKImmFPOperands(MCInst &Inst, unsigned N) const;
608
609 void addKImmFP16Operands(MCInst &Inst, unsigned N) const {
610 addKImmFPOperands<16>(Inst, N);
611 }
612
613 void addKImmFP32Operands(MCInst &Inst, unsigned N) const {
614 addKImmFPOperands<32>(Inst, N);
615 }
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000616
617 void addRegOperands(MCInst &Inst, unsigned N) const;
Sam Kolton945231a2016-06-10 09:57:59 +0000618
619 void addRegOrImmOperands(MCInst &Inst, unsigned N) const {
620 if (isRegKind())
621 addRegOperands(Inst, N);
Tom Stellard89049702016-06-15 02:54:14 +0000622 else if (isExpr())
623 Inst.addOperand(MCOperand::createExpr(Expr));
Sam Kolton945231a2016-06-10 09:57:59 +0000624 else
625 addImmOperands(Inst, N);
626 }
627
628 void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const {
629 Modifiers Mods = getModifiers();
630 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
631 if (isRegKind()) {
632 addRegOperands(Inst, N);
633 } else {
634 addImmOperands(Inst, N, false);
635 }
636 }
637
638 void addRegOrImmWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
639 assert(!hasIntModifiers());
640 addRegOrImmWithInputModsOperands(Inst, N);
641 }
642
643 void addRegOrImmWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
644 assert(!hasFPModifiers());
645 addRegOrImmWithInputModsOperands(Inst, N);
646 }
647
Sam Kolton9772eb32017-01-11 11:46:30 +0000648 void addRegWithInputModsOperands(MCInst &Inst, unsigned N) const {
649 Modifiers Mods = getModifiers();
650 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
651 assert(isRegKind());
652 addRegOperands(Inst, N);
653 }
654
655 void addRegWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
656 assert(!hasIntModifiers());
657 addRegWithInputModsOperands(Inst, N);
658 }
659
660 void addRegWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
661 assert(!hasFPModifiers());
662 addRegWithInputModsOperands(Inst, N);
663 }
664
Sam Kolton945231a2016-06-10 09:57:59 +0000665 void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const {
666 if (isImm())
667 addImmOperands(Inst, N);
668 else {
669 assert(isExpr());
670 Inst.addOperand(MCOperand::createExpr(Expr));
671 }
672 }
673
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +0000674 static void printImmTy(raw_ostream& OS, ImmTy Type) {
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000675 switch (Type) {
676 case ImmTyNone: OS << "None"; break;
677 case ImmTyGDS: OS << "GDS"; break;
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +0000678 case ImmTyLDS: OS << "LDS"; break;
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000679 case ImmTyOffen: OS << "Offen"; break;
680 case ImmTyIdxen: OS << "Idxen"; break;
681 case ImmTyAddr64: OS << "Addr64"; break;
682 case ImmTyOffset: OS << "Offset"; break;
Dmitry Preobrazhenskydd2f1c92017-11-24 13:22:38 +0000683 case ImmTyInstOffset: OS << "InstOffset"; break;
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000684 case ImmTyOffset0: OS << "Offset0"; break;
685 case ImmTyOffset1: OS << "Offset1"; break;
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +0000686 case ImmTyDLC: OS << "DLC"; break;
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000687 case ImmTyGLC: OS << "GLC"; break;
688 case ImmTySLC: OS << "SLC"; break;
689 case ImmTyTFE: OS << "TFE"; break;
Dmitry Preobrazhensky4f321ae2018-01-29 14:20:42 +0000690 case ImmTyD16: OS << "D16"; break;
Tim Renouf35484c92018-08-21 11:06:05 +0000691 case ImmTyFORMAT: OS << "FORMAT"; break;
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000692 case ImmTyClampSI: OS << "ClampSI"; break;
693 case ImmTyOModSI: OS << "OModSI"; break;
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +0000694 case ImmTyDPP8: OS << "DPP8"; break;
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000695 case ImmTyDppCtrl: OS << "DppCtrl"; break;
696 case ImmTyDppRowMask: OS << "DppRowMask"; break;
697 case ImmTyDppBankMask: OS << "DppBankMask"; break;
698 case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break;
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +0000699 case ImmTyDppFi: OS << "FI"; break;
Sam Kolton05ef1c92016-06-03 10:27:37 +0000700 case ImmTySdwaDstSel: OS << "SdwaDstSel"; break;
701 case ImmTySdwaSrc0Sel: OS << "SdwaSrc0Sel"; break;
702 case ImmTySdwaSrc1Sel: OS << "SdwaSrc1Sel"; break;
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000703 case ImmTySdwaDstUnused: OS << "SdwaDstUnused"; break;
704 case ImmTyDMask: OS << "DMask"; break;
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +0000705 case ImmTyDim: OS << "Dim"; break;
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000706 case ImmTyUNorm: OS << "UNorm"; break;
707 case ImmTyDA: OS << "DA"; break;
Ryan Taylor1f334d02018-08-28 15:07:30 +0000708 case ImmTyR128A16: OS << "R128A16"; break;
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000709 case ImmTyLWE: OS << "LWE"; break;
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +0000710 case ImmTyOff: OS << "Off"; break;
711 case ImmTyExpTgt: OS << "ExpTgt"; break;
Matt Arsenault8a63cb92016-12-05 20:31:49 +0000712 case ImmTyExpCompr: OS << "ExpCompr"; break;
713 case ImmTyExpVM: OS << "ExpVM"; break;
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000714 case ImmTyHwreg: OS << "Hwreg"; break;
Artem Tamazovebe71ce2016-05-06 17:48:48 +0000715 case ImmTySendMsg: OS << "SendMsg"; break;
Matt Arsenault0e8a2992016-12-15 20:40:20 +0000716 case ImmTyInterpSlot: OS << "InterpSlot"; break;
717 case ImmTyInterpAttr: OS << "InterpAttr"; break;
718 case ImmTyAttrChan: OS << "AttrChan"; break;
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000719 case ImmTyOpSel: OS << "OpSel"; break;
720 case ImmTyOpSelHi: OS << "OpSelHi"; break;
721 case ImmTyNegLo: OS << "NegLo"; break;
722 case ImmTyNegHi: OS << "NegHi"; break;
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +0000723 case ImmTySwizzle: OS << "Swizzle"; break;
Dmitry Preobrazhenskyef920352019-02-27 13:12:12 +0000724 case ImmTyGprIdxMode: OS << "GprIdxMode"; break;
Dmitry Preobrazhensky50805a02017-08-07 13:14:12 +0000725 case ImmTyHigh: OS << "High"; break;
David Stuttard20ea21c2019-03-12 09:52:58 +0000726 case ImmTyEndpgm:
727 OS << "Endpgm";
728 break;
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000729 }
730 }
731
Matt Arsenaultcbd75372015-08-08 00:41:51 +0000732 void print(raw_ostream &OS) const override {
733 switch (Kind) {
734 case Register:
Sam Kolton945231a2016-06-10 09:57:59 +0000735 OS << "<register " << getReg() << " mods: " << Reg.Mods << '>';
Matt Arsenaultcbd75372015-08-08 00:41:51 +0000736 break;
737 case Immediate:
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000738 OS << '<' << getImm();
739 if (getImmTy() != ImmTyNone) {
740 OS << " type: "; printImmTy(OS, getImmTy());
741 }
Sam Kolton945231a2016-06-10 09:57:59 +0000742 OS << " mods: " << Imm.Mods << '>';
Matt Arsenaultcbd75372015-08-08 00:41:51 +0000743 break;
744 case Token:
745 OS << '\'' << getToken() << '\'';
746 break;
747 case Expression:
748 OS << "<expr " << *Expr << '>';
749 break;
750 }
751 }
Tom Stellard45bb48e2015-06-13 03:28:10 +0000752
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000753 static AMDGPUOperand::Ptr CreateImm(const AMDGPUAsmParser *AsmParser,
754 int64_t Val, SMLoc Loc,
Matt Arsenaultf15da6c2017-02-03 20:49:51 +0000755 ImmTy Type = ImmTyNone,
Sam Kolton5f10a132016-05-06 11:31:17 +0000756 bool IsFPImm = false) {
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000757 auto Op = llvm::make_unique<AMDGPUOperand>(Immediate, AsmParser);
Tom Stellard45bb48e2015-06-13 03:28:10 +0000758 Op->Imm.Val = Val;
759 Op->Imm.IsFPImm = IsFPImm;
760 Op->Imm.Type = Type;
Matt Arsenaultb55f6202016-12-03 18:22:49 +0000761 Op->Imm.Mods = Modifiers();
Tom Stellard45bb48e2015-06-13 03:28:10 +0000762 Op->StartLoc = Loc;
763 Op->EndLoc = Loc;
764 return Op;
765 }
766
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000767 static AMDGPUOperand::Ptr CreateToken(const AMDGPUAsmParser *AsmParser,
768 StringRef Str, SMLoc Loc,
Sam Kolton5f10a132016-05-06 11:31:17 +0000769 bool HasExplicitEncodingSize = true) {
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000770 auto Res = llvm::make_unique<AMDGPUOperand>(Token, AsmParser);
Tom Stellard45bb48e2015-06-13 03:28:10 +0000771 Res->Tok.Data = Str.data();
772 Res->Tok.Length = Str.size();
773 Res->StartLoc = Loc;
774 Res->EndLoc = Loc;
775 return Res;
776 }
777
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000778 static AMDGPUOperand::Ptr CreateReg(const AMDGPUAsmParser *AsmParser,
779 unsigned RegNo, SMLoc S,
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +0000780 SMLoc E) {
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000781 auto Op = llvm::make_unique<AMDGPUOperand>(Register, AsmParser);
Tom Stellard45bb48e2015-06-13 03:28:10 +0000782 Op->Reg.RegNo = RegNo;
Matt Arsenaultb55f6202016-12-03 18:22:49 +0000783 Op->Reg.Mods = Modifiers();
Tom Stellard45bb48e2015-06-13 03:28:10 +0000784 Op->StartLoc = S;
785 Op->EndLoc = E;
786 return Op;
787 }
788
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000789 static AMDGPUOperand::Ptr CreateExpr(const AMDGPUAsmParser *AsmParser,
790 const class MCExpr *Expr, SMLoc S) {
791 auto Op = llvm::make_unique<AMDGPUOperand>(Expression, AsmParser);
Tom Stellard45bb48e2015-06-13 03:28:10 +0000792 Op->Expr = Expr;
793 Op->StartLoc = S;
794 Op->EndLoc = S;
795 return Op;
796 }
Tom Stellard45bb48e2015-06-13 03:28:10 +0000797};
798
Sam Kolton945231a2016-06-10 09:57:59 +0000799raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) {
800 OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext;
801 return OS;
802}
803
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000804//===----------------------------------------------------------------------===//
805// AsmParser
806//===----------------------------------------------------------------------===//
807
Artem Tamazova01cce82016-12-27 16:00:11 +0000808// Holds info related to the current kernel, e.g. count of SGPRs used.
809// Kernel scope begins at .amdgpu_hsa_kernel directive, ends at next
810// .amdgpu_hsa_kernel or at EOF.
811class KernelScopeInfo {
Eugene Zelenko66203762017-01-21 00:53:49 +0000812 int SgprIndexUnusedMin = -1;
813 int VgprIndexUnusedMin = -1;
814 MCContext *Ctx = nullptr;
Artem Tamazova01cce82016-12-27 16:00:11 +0000815
816 void usesSgprAt(int i) {
817 if (i >= SgprIndexUnusedMin) {
818 SgprIndexUnusedMin = ++i;
819 if (Ctx) {
820 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.sgpr_count"));
821 Sym->setVariableValue(MCConstantExpr::create(SgprIndexUnusedMin, *Ctx));
822 }
823 }
824 }
Eugene Zelenko66203762017-01-21 00:53:49 +0000825
Artem Tamazova01cce82016-12-27 16:00:11 +0000826 void usesVgprAt(int i) {
827 if (i >= VgprIndexUnusedMin) {
828 VgprIndexUnusedMin = ++i;
829 if (Ctx) {
830 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count"));
831 Sym->setVariableValue(MCConstantExpr::create(VgprIndexUnusedMin, *Ctx));
832 }
833 }
834 }
Eugene Zelenko66203762017-01-21 00:53:49 +0000835
Artem Tamazova01cce82016-12-27 16:00:11 +0000836public:
Eugene Zelenko66203762017-01-21 00:53:49 +0000837 KernelScopeInfo() = default;
838
Artem Tamazova01cce82016-12-27 16:00:11 +0000839 void initialize(MCContext &Context) {
840 Ctx = &Context;
841 usesSgprAt(SgprIndexUnusedMin = -1);
842 usesVgprAt(VgprIndexUnusedMin = -1);
843 }
Eugene Zelenko66203762017-01-21 00:53:49 +0000844
Artem Tamazova01cce82016-12-27 16:00:11 +0000845 void usesRegister(RegisterKind RegKind, unsigned DwordRegIndex, unsigned RegWidth) {
846 switch (RegKind) {
847 case IS_SGPR: usesSgprAt(DwordRegIndex + RegWidth - 1); break;
848 case IS_VGPR: usesVgprAt(DwordRegIndex + RegWidth - 1); break;
849 default: break;
850 }
851 }
852};
853
Tom Stellard45bb48e2015-06-13 03:28:10 +0000854class AMDGPUAsmParser : public MCTargetAsmParser {
Tom Stellard45bb48e2015-06-13 03:28:10 +0000855 MCAsmParser &Parser;
856
Dmitry Preobrazhensky414e0532017-12-29 13:55:11 +0000857 // Number of extra operands parsed after the first optional operand.
858 // This may be necessary to skip hardcoded mandatory operands.
Dmitry Preobrazhensky4f321ae2018-01-29 14:20:42 +0000859 static const unsigned MAX_OPR_LOOKAHEAD = 8;
Dmitry Preobrazhensky414e0532017-12-29 13:55:11 +0000860
Eugene Zelenko66203762017-01-21 00:53:49 +0000861 unsigned ForcedEncodingSize = 0;
862 bool ForcedDPP = false;
863 bool ForcedSDWA = false;
Artem Tamazova01cce82016-12-27 16:00:11 +0000864 KernelScopeInfo KernelScope;
Matt Arsenault68802d32015-11-05 03:11:27 +0000865
Tom Stellard45bb48e2015-06-13 03:28:10 +0000866 /// @name Auto-generated Match Functions
867 /// {
868
869#define GET_ASSEMBLER_HEADER
870#include "AMDGPUGenAsmMatcher.inc"
871
872 /// }
873
Tom Stellard347ac792015-06-26 21:15:07 +0000874private:
Artem Tamazov25478d82016-12-29 15:41:52 +0000875 bool ParseAsAbsoluteExpression(uint32_t &Ret);
Scott Linder1e8c2c72018-06-21 19:38:56 +0000876 bool OutOfRangeError(SMRange Range);
877 /// Calculate VGPR/SGPR blocks required for given target, reserved
878 /// registers, and user-specified NextFreeXGPR values.
879 ///
880 /// \param Features [in] Target features, used for bug corrections.
881 /// \param VCCUsed [in] Whether VCC special SGPR is reserved.
882 /// \param FlatScrUsed [in] Whether FLAT_SCRATCH special SGPR is reserved.
883 /// \param XNACKUsed [in] Whether XNACK_MASK special SGPR is reserved.
884 /// \param NextFreeVGPR [in] Max VGPR number referenced, plus one.
885 /// \param VGPRRange [in] Token range, used for VGPR diagnostics.
886 /// \param NextFreeSGPR [in] Max SGPR number referenced, plus one.
887 /// \param SGPRRange [in] Token range, used for SGPR diagnostics.
888 /// \param VGPRBlocks [out] Result VGPR block count.
889 /// \param SGPRBlocks [out] Result SGPR block count.
890 bool calculateGPRBlocks(const FeatureBitset &Features, bool VCCUsed,
891 bool FlatScrUsed, bool XNACKUsed,
892 unsigned NextFreeVGPR, SMRange VGPRRange,
893 unsigned NextFreeSGPR, SMRange SGPRRange,
894 unsigned &VGPRBlocks, unsigned &SGPRBlocks);
895 bool ParseDirectiveAMDGCNTarget();
896 bool ParseDirectiveAMDHSAKernel();
Tom Stellard347ac792015-06-26 21:15:07 +0000897 bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor);
898 bool ParseDirectiveHSACodeObjectVersion();
899 bool ParseDirectiveHSACodeObjectISA();
Tom Stellardff7416b2015-06-26 21:58:31 +0000900 bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header);
901 bool ParseDirectiveAMDKernelCodeT();
Matt Arsenault68802d32015-11-05 03:11:27 +0000902 bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const;
Tom Stellard1e1b05d2015-11-06 11:45:14 +0000903 bool ParseDirectiveAMDGPUHsaKernel();
Konstantin Zhuravlyovc3beb6a2017-10-11 22:41:09 +0000904
Konstantin Zhuravlyov9c05b2b2017-10-14 15:40:33 +0000905 bool ParseDirectiveISAVersion();
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +0000906 bool ParseDirectiveHSAMetadata();
Tim Renoufe7bd52f2019-03-20 18:47:21 +0000907 bool ParseDirectivePALMetadataBegin();
Konstantin Zhuravlyovc3beb6a2017-10-11 22:41:09 +0000908 bool ParseDirectivePALMetadata();
909
Tim Renoufe7bd52f2019-03-20 18:47:21 +0000910 /// Common code to parse out a block of text (typically YAML) between start and
911 /// end directives.
912 bool ParseToEndDirective(const char *AssemblerDirectiveBegin,
913 const char *AssemblerDirectiveEnd,
914 std::string &CollectString);
915
Matt Arsenaultf15da6c2017-02-03 20:49:51 +0000916 bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth,
917 RegisterKind RegKind, unsigned Reg1,
918 unsigned RegNum);
919 bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg,
920 unsigned& RegNum, unsigned& RegWidth,
921 unsigned *DwordRegIndex);
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +0000922 bool isRegister();
923 bool isRegister(const AsmToken &Token, const AsmToken &NextToken) const;
Scott Linder1e8c2c72018-06-21 19:38:56 +0000924 Optional<StringRef> getGprCountSymbolName(RegisterKind RegKind);
925 void initializeGprCountSymbol(RegisterKind RegKind);
926 bool updateGprCountSymbols(RegisterKind RegKind, unsigned DwordRegIndex,
927 unsigned RegWidth);
Matt Arsenaultf15da6c2017-02-03 20:49:51 +0000928 void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands,
Dmitry Preobrazhenskyd98c97b2018-03-12 17:29:24 +0000929 bool IsAtomic, bool IsAtomicReturn, bool IsLds = false);
Matt Arsenaultf15da6c2017-02-03 20:49:51 +0000930 void cvtDSImpl(MCInst &Inst, const OperandVector &Operands,
931 bool IsGdsHardcoded);
Tom Stellard347ac792015-06-26 21:15:07 +0000932
Tom Stellard45bb48e2015-06-13 03:28:10 +0000933public:
Tom Stellard88e0b252015-10-06 15:57:53 +0000934 enum AMDGPUMatchResultTy {
935 Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY
936 };
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +0000937 enum OperandMode {
938 OperandMode_Default,
939 OperandMode_NSA,
940 };
Tom Stellard88e0b252015-10-06 15:57:53 +0000941
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +0000942 using OptionalImmIndexMap = std::map<AMDGPUOperand::ImmTy, unsigned>;
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000943
Akira Hatanakab11ef082015-11-14 06:35:56 +0000944 AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser,
Tom Stellard45bb48e2015-06-13 03:28:10 +0000945 const MCInstrInfo &MII,
946 const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000947 : MCTargetAsmParser(Options, STI, MII), Parser(_Parser) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000948 MCAsmParserExtension::Initialize(Parser);
949
Konstantin Zhuravlyov972948b2017-02-27 07:55:17 +0000950 if (getFeatureBits().none()) {
Tom Stellard45bb48e2015-06-13 03:28:10 +0000951 // Set default features.
Matt Arsenault45c165b2019-04-03 00:01:03 +0000952 copySTI().ToggleFeature("southern-islands");
Tom Stellard45bb48e2015-06-13 03:28:10 +0000953 }
954
Konstantin Zhuravlyov972948b2017-02-27 07:55:17 +0000955 setAvailableFeatures(ComputeAvailableFeatures(getFeatureBits()));
Artem Tamazov17091362016-06-14 15:03:59 +0000956
957 {
958 // TODO: make those pre-defined variables read-only.
959 // Currently there is none suitable machinery in the core llvm-mc for this.
960 // MCSymbol::isRedefinable is intended for another purpose, and
961 // AsmParser::parseDirectiveSet() cannot be specialized for specific target.
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +0000962 AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU());
Artem Tamazov17091362016-06-14 15:03:59 +0000963 MCContext &Ctx = getContext();
Scott Linder1e8c2c72018-06-21 19:38:56 +0000964 if (ISA.Major >= 6 && AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) {
965 MCSymbol *Sym =
966 Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_number"));
967 Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx));
Dmitry Preobrazhensky62a03182019-02-08 13:51:31 +0000968 Sym = Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_minor"));
969 Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx));
970 Sym = Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_stepping"));
971 Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx));
Scott Linder1e8c2c72018-06-21 19:38:56 +0000972 } else {
973 MCSymbol *Sym =
974 Ctx.getOrCreateSymbol(Twine(".option.machine_version_major"));
975 Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx));
976 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_minor"));
977 Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx));
978 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_stepping"));
979 Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx));
980 }
981 if (ISA.Major >= 6 && AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) {
982 initializeGprCountSymbol(IS_VGPR);
983 initializeGprCountSymbol(IS_SGPR);
984 } else
985 KernelScope.initialize(getContext());
Artem Tamazov17091362016-06-14 15:03:59 +0000986 }
Tom Stellard45bb48e2015-06-13 03:28:10 +0000987 }
988
Dmitry Preobrazhensky3afbd822018-01-10 14:22:19 +0000989 bool hasXNACK() const {
990 return AMDGPU::hasXNACK(getSTI());
991 }
992
Dmitry Preobrazhenskye3271ae2018-02-05 12:45:43 +0000993 bool hasMIMG_R128() const {
994 return AMDGPU::hasMIMG_R128(getSTI());
995 }
996
Dmitry Preobrazhensky0a1ff462018-02-05 14:18:53 +0000997 bool hasPackedD16() const {
998 return AMDGPU::hasPackedD16(getSTI());
999 }
1000
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001001 bool isSI() const {
1002 return AMDGPU::isSI(getSTI());
1003 }
1004
1005 bool isCI() const {
1006 return AMDGPU::isCI(getSTI());
1007 }
1008
1009 bool isVI() const {
1010 return AMDGPU::isVI(getSTI());
1011 }
1012
Sam Koltonf7659d712017-05-23 10:08:55 +00001013 bool isGFX9() const {
1014 return AMDGPU::isGFX9(getSTI());
1015 }
1016
Stanislav Mekhanoshincee607e2019-04-24 17:03:15 +00001017 bool isGFX10() const {
1018 return AMDGPU::isGFX10(getSTI());
1019 }
1020
Matt Arsenault26faed32016-12-05 22:26:17 +00001021 bool hasInv2PiInlineImm() const {
Konstantin Zhuravlyov972948b2017-02-27 07:55:17 +00001022 return getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm];
Matt Arsenault26faed32016-12-05 22:26:17 +00001023 }
1024
Matt Arsenaultfd023142017-06-12 15:55:58 +00001025 bool hasFlatOffsets() const {
1026 return getFeatureBits()[AMDGPU::FeatureFlatInstOffsets];
1027 }
1028
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001029 bool hasSGPR102_SGPR103() const {
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00001030 return !isVI() && !isGFX9();
1031 }
1032
1033 bool hasSGPR104_SGPR105() const {
1034 return isGFX10();
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001035 }
1036
Dmitry Preobrazhenskyff64aa52017-08-16 13:51:56 +00001037 bool hasIntClamp() const {
1038 return getFeatureBits()[AMDGPU::FeatureIntClamp];
1039 }
1040
Tom Stellard347ac792015-06-26 21:15:07 +00001041 AMDGPUTargetStreamer &getTargetStreamer() {
1042 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
1043 return static_cast<AMDGPUTargetStreamer &>(TS);
1044 }
Matt Arsenault37fefd62016-06-10 02:18:02 +00001045
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001046 const MCRegisterInfo *getMRI() const {
1047 // We need this const_cast because for some reason getContext() is not const
1048 // in MCAsmParser.
1049 return const_cast<AMDGPUAsmParser*>(this)->getContext().getRegisterInfo();
1050 }
1051
1052 const MCInstrInfo *getMII() const {
1053 return &MII;
1054 }
1055
Konstantin Zhuravlyov972948b2017-02-27 07:55:17 +00001056 const FeatureBitset &getFeatureBits() const {
1057 return getSTI().getFeatureBits();
1058 }
1059
Sam Kolton05ef1c92016-06-03 10:27:37 +00001060 void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; }
1061 void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; }
1062 void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; }
Tom Stellard347ac792015-06-26 21:15:07 +00001063
Sam Kolton05ef1c92016-06-03 10:27:37 +00001064 unsigned getForcedEncodingSize() const { return ForcedEncodingSize; }
1065 bool isForcedVOP3() const { return ForcedEncodingSize == 64; }
1066 bool isForcedDPP() const { return ForcedDPP; }
1067 bool isForcedSDWA() const { return ForcedSDWA; }
Matt Arsenault5f45e782017-01-09 18:44:11 +00001068 ArrayRef<unsigned> getMatchedVariants() const;
Tom Stellard45bb48e2015-06-13 03:28:10 +00001069
Valery Pykhtin0f97f172016-03-14 07:43:42 +00001070 std::unique_ptr<AMDGPUOperand> parseRegister();
Tom Stellard45bb48e2015-06-13 03:28:10 +00001071 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
1072 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
Sam Kolton11de3702016-05-24 12:38:33 +00001073 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
1074 unsigned Kind) override;
Tom Stellard45bb48e2015-06-13 03:28:10 +00001075 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1076 OperandVector &Operands, MCStreamer &Out,
1077 uint64_t &ErrorInfo,
1078 bool MatchingInlineAsm) override;
1079 bool ParseDirective(AsmToken DirectiveID) override;
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00001080 OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic,
1081 OperandMode Mode = OperandMode_Default);
Sam Kolton05ef1c92016-06-03 10:27:37 +00001082 StringRef parseMnemonicSuffix(StringRef Name);
Tom Stellard45bb48e2015-06-13 03:28:10 +00001083 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
1084 SMLoc NameLoc, OperandVector &Operands) override;
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001085 //bool ProcessInstruction(MCInst &Inst);
Tom Stellard45bb48e2015-06-13 03:28:10 +00001086
Sam Kolton11de3702016-05-24 12:38:33 +00001087 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001088
Eugene Zelenko2bc2f332016-12-09 22:06:55 +00001089 OperandMatchResultTy
1090 parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
Matt Arsenaultf15da6c2017-02-03 20:49:51 +00001091 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
Eugene Zelenko2bc2f332016-12-09 22:06:55 +00001092 bool (*ConvertResult)(int64_t &) = nullptr);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001093
Dmitry Preobrazhensky7773fc42019-05-22 13:59:01 +00001094 OperandMatchResultTy
1095 parseOperandArrayWithPrefix(const char *Prefix,
1096 OperandVector &Operands,
1097 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
1098 bool (*ConvertResult)(int64_t&) = nullptr);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001099
Eugene Zelenko2bc2f332016-12-09 22:06:55 +00001100 OperandMatchResultTy
1101 parseNamedBit(const char *Name, OperandVector &Operands,
Matt Arsenaultf15da6c2017-02-03 20:49:51 +00001102 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone);
Eugene Zelenko2bc2f332016-12-09 22:06:55 +00001103 OperandMatchResultTy parseStringWithPrefix(StringRef Prefix,
1104 StringRef &Value);
Tom Stellard45bb48e2015-06-13 03:28:10 +00001105
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +00001106 bool isModifier();
1107 bool isOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const;
1108 bool isRegOrOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const;
1109 bool isNamedOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const;
1110 bool isOpcodeModifierWithVal(const AsmToken &Token, const AsmToken &NextToken) const;
Dmitry Preobrazhenskye2707f52019-04-22 14:35:47 +00001111 bool parseSP3NegModifier();
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00001112 OperandMatchResultTy parseImm(OperandVector &Operands, bool HasSP3AbsModifier = false);
Sam Kolton9772eb32017-01-11 11:46:30 +00001113 OperandMatchResultTy parseReg(OperandVector &Operands);
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00001114 OperandMatchResultTy parseRegOrImm(OperandVector &Operands, bool HasSP3AbsMod = false);
Sam Kolton9772eb32017-01-11 11:46:30 +00001115 OperandMatchResultTy parseRegOrImmWithFPInputMods(OperandVector &Operands, bool AllowImm = true);
1116 OperandMatchResultTy parseRegOrImmWithIntInputMods(OperandVector &Operands, bool AllowImm = true);
1117 OperandMatchResultTy parseRegWithFPInputMods(OperandVector &Operands);
1118 OperandMatchResultTy parseRegWithIntInputMods(OperandVector &Operands);
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00001119 OperandMatchResultTy parseVReg32OrOff(OperandVector &Operands);
Tim Renouf35484c92018-08-21 11:06:05 +00001120 OperandMatchResultTy parseDfmtNfmt(OperandVector &Operands);
Sam Kolton1bdcef72016-05-23 09:59:02 +00001121
Tom Stellard45bb48e2015-06-13 03:28:10 +00001122 void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands);
Artem Tamazov43b61562017-02-03 12:47:30 +00001123 void cvtDS(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, false); }
1124 void cvtDSGds(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, true); }
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00001125 void cvtExp(MCInst &Inst, const OperandVector &Operands);
Tom Stellard45bb48e2015-06-13 03:28:10 +00001126
1127 bool parseCnt(int64_t &IntVal);
1128 OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);
Nikolay Haustov4f672a32016-04-29 09:02:30 +00001129 OperandMatchResultTy parseHwreg(OperandVector &Operands);
Sam Kolton11de3702016-05-24 12:38:33 +00001130
Artem Tamazovebe71ce2016-05-06 17:48:48 +00001131private:
1132 struct OperandInfoTy {
1133 int64_t Id;
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001134 bool IsSymbolic = false;
1135
1136 OperandInfoTy(int64_t Id_) : Id(Id_) {}
Artem Tamazovebe71ce2016-05-06 17:48:48 +00001137 };
Sam Kolton11de3702016-05-24 12:38:33 +00001138
Artem Tamazov6edc1352016-05-26 17:00:33 +00001139 bool parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId);
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00001140 bool parseHwregBody(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width);
1141 void validateHwreg(const OperandInfoTy &HwReg,
1142 const int64_t Offset,
1143 const int64_t Width,
1144 const SMLoc Loc);
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00001145
1146 void errorExpTgt();
1147 OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val);
1148
Dmitry Preobrazhenskydc4ac822017-06-21 14:41:34 +00001149 bool validateInstruction(const MCInst &Inst, const SMLoc &IDLoc);
Dmitry Preobrazhensky61105ba2019-01-18 13:57:43 +00001150 bool validateSOPLiteral(const MCInst &Inst) const;
Dmitry Preobrazhenskydc4ac822017-06-21 14:41:34 +00001151 bool validateConstantBusLimitations(const MCInst &Inst);
1152 bool validateEarlyClobberLimitations(const MCInst &Inst);
Dmitry Preobrazhenskyff64aa52017-08-16 13:51:56 +00001153 bool validateIntClampSupported(const MCInst &Inst);
Dmitry Preobrazhensky70682812018-01-26 16:42:51 +00001154 bool validateMIMGAtomicDMask(const MCInst &Inst);
Dmitry Preobrazhenskyda4a7c02018-03-12 15:03:34 +00001155 bool validateMIMGGatherDMask(const MCInst &Inst);
Dmitry Preobrazhensky70682812018-01-26 16:42:51 +00001156 bool validateMIMGDataSize(const MCInst &Inst);
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00001157 bool validateMIMGAddrSize(const MCInst &Inst);
Dmitry Preobrazhenskye3271ae2018-02-05 12:45:43 +00001158 bool validateMIMGD16(const MCInst &Inst);
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00001159 bool validateMIMGDim(const MCInst &Inst);
Dmitry Preobrazhensky942c2732019-02-08 14:57:37 +00001160 bool validateLdsDirect(const MCInst &Inst);
Stanislav Mekhanoshin5f581c92019-06-12 17:52:51 +00001161 bool validateOpSel(const MCInst &Inst);
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00001162 bool validateVOP3Literal(const MCInst &Inst) const;
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00001163 bool usesConstantBus(const MCInst &Inst, unsigned OpIdx);
1164 bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const;
1165 unsigned findImplicitSGPRReadInVOP(const MCInst &Inst) const;
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00001166
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00001167 bool isId(const StringRef Id) const;
1168 bool isId(const AsmToken &Token, const StringRef Id) const;
1169 bool isToken(const AsmToken::TokenKind Kind) const;
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00001170 bool trySkipId(const StringRef Id);
Dmitry Preobrazhensky198611b2019-05-17 16:04:17 +00001171 bool trySkipId(const StringRef Id, const AsmToken::TokenKind Kind);
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00001172 bool trySkipToken(const AsmToken::TokenKind Kind);
1173 bool skipToken(const AsmToken::TokenKind Kind, const StringRef ErrMsg);
1174 bool parseString(StringRef &Val, const StringRef ErrMsg = "expected a string");
Dmitry Preobrazhenskye2707f52019-04-22 14:35:47 +00001175 void peekTokens(MutableArrayRef<AsmToken> Tokens);
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00001176 AsmToken::TokenKind getTokenKind() const;
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00001177 bool parseExpr(int64_t &Imm);
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00001178 StringRef getTokenStr() const;
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00001179 AsmToken peekToken();
1180 AsmToken getToken() const;
1181 SMLoc getLoc() const;
1182 void lex();
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00001183
Artem Tamazovebe71ce2016-05-06 17:48:48 +00001184public:
Sam Kolton11de3702016-05-24 12:38:33 +00001185 OperandMatchResultTy parseOptionalOperand(OperandVector &Operands);
Dmitry Preobrazhensky414e0532017-12-29 13:55:11 +00001186 OperandMatchResultTy parseOptionalOpr(OperandVector &Operands);
Sam Kolton11de3702016-05-24 12:38:33 +00001187
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00001188 OperandMatchResultTy parseExpTgt(OperandVector &Operands);
Artem Tamazovebe71ce2016-05-06 17:48:48 +00001189 OperandMatchResultTy parseSendMsgOp(OperandVector &Operands);
Matt Arsenault0e8a2992016-12-15 20:40:20 +00001190 OperandMatchResultTy parseInterpSlot(OperandVector &Operands);
1191 OperandMatchResultTy parseInterpAttr(OperandVector &Operands);
Tom Stellard45bb48e2015-06-13 03:28:10 +00001192 OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands);
1193
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00001194 bool parseSwizzleOperands(const unsigned OpNum, int64_t* Op,
1195 const unsigned MinVal,
1196 const unsigned MaxVal,
1197 const StringRef ErrMsg);
1198 OperandMatchResultTy parseSwizzleOp(OperandVector &Operands);
1199 bool parseSwizzleOffset(int64_t &Imm);
1200 bool parseSwizzleMacro(int64_t &Imm);
1201 bool parseSwizzleQuadPerm(int64_t &Imm);
1202 bool parseSwizzleBitmaskPerm(int64_t &Imm);
1203 bool parseSwizzleBroadcast(int64_t &Imm);
1204 bool parseSwizzleSwap(int64_t &Imm);
1205 bool parseSwizzleReverse(int64_t &Imm);
1206
Dmitry Preobrazhenskyef920352019-02-27 13:12:12 +00001207 OperandMatchResultTy parseGPRIdxMode(OperandVector &Operands);
1208 int64_t parseGPRIdxMacro();
1209
Artem Tamazov8ce1f712016-05-19 12:22:39 +00001210 void cvtMubuf(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false); }
1211 void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, false); }
1212 void cvtMubufAtomicReturn(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, true); }
Dmitry Preobrazhenskyd98c97b2018-03-12 17:29:24 +00001213 void cvtMubufLds(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false, true); }
David Stuttard70e8bc12017-06-22 16:29:22 +00001214 void cvtMtbuf(MCInst &Inst, const OperandVector &Operands);
1215
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00001216 AMDGPUOperand::Ptr defaultDLC() const;
Sam Kolton5f10a132016-05-06 11:31:17 +00001217 AMDGPUOperand::Ptr defaultGLC() const;
1218 AMDGPUOperand::Ptr defaultSLC() const;
Sam Kolton5f10a132016-05-06 11:31:17 +00001219
Artem Tamazov54bfd542016-10-31 16:07:39 +00001220 AMDGPUOperand::Ptr defaultSMRDOffset8() const;
1221 AMDGPUOperand::Ptr defaultSMRDOffset20() const;
Sam Kolton5f10a132016-05-06 11:31:17 +00001222 AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const;
Matt Arsenaultfd023142017-06-12 15:55:58 +00001223 AMDGPUOperand::Ptr defaultOffsetU12() const;
Matt Arsenault9698f1c2017-06-20 19:54:14 +00001224 AMDGPUOperand::Ptr defaultOffsetS13() const;
Matt Arsenault37fefd62016-06-10 02:18:02 +00001225
Nikolay Haustov4f672a32016-04-29 09:02:30 +00001226 OperandMatchResultTy parseOModOperand(OperandVector &Operands);
1227
Sam Kolton10ac2fd2017-07-07 15:21:52 +00001228 void cvtVOP3(MCInst &Inst, const OperandVector &Operands,
1229 OptionalImmIndexMap &OptionalIdx);
Dmitry Preobrazhenskyabf28392017-07-21 13:54:11 +00001230 void cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands);
Tom Stellard45bb48e2015-06-13 03:28:10 +00001231 void cvtVOP3(MCInst &Inst, const OperandVector &Operands);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001232 void cvtVOP3P(MCInst &Inst, const OperandVector &Operands);
Nikolay Haustov2f684f12016-02-26 09:51:05 +00001233
Dmitry Preobrazhensky50805a02017-08-07 13:14:12 +00001234 void cvtVOP3Interp(MCInst &Inst, const OperandVector &Operands);
1235
Sam Kolton10ac2fd2017-07-07 15:21:52 +00001236 void cvtMIMG(MCInst &Inst, const OperandVector &Operands,
1237 bool IsAtomic = false);
Nikolay Haustov5bf46ac12016-03-04 10:39:50 +00001238 void cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands);
Sam Koltondfa29f72016-03-09 12:29:31 +00001239
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00001240 OperandMatchResultTy parseDim(OperandVector &Operands);
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00001241 OperandMatchResultTy parseDPP8(OperandVector &Operands);
Sam Kolton11de3702016-05-24 12:38:33 +00001242 OperandMatchResultTy parseDPPCtrl(OperandVector &Operands);
Sam Kolton5f10a132016-05-06 11:31:17 +00001243 AMDGPUOperand::Ptr defaultRowMask() const;
1244 AMDGPUOperand::Ptr defaultBankMask() const;
1245 AMDGPUOperand::Ptr defaultBoundCtrl() const;
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00001246 AMDGPUOperand::Ptr defaultFI() const;
1247 void cvtDPP(MCInst &Inst, const OperandVector &Operands, bool IsDPP8 = false);
1248 void cvtDPP8(MCInst &Inst, const OperandVector &Operands) { cvtDPP(Inst, Operands, true); }
Sam Kolton3025e7f2016-04-26 13:33:56 +00001249
Sam Kolton05ef1c92016-06-03 10:27:37 +00001250 OperandMatchResultTy parseSDWASel(OperandVector &Operands, StringRef Prefix,
1251 AMDGPUOperand::ImmTy Type);
Sam Kolton3025e7f2016-04-26 13:33:56 +00001252 OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands);
Sam Kolton945231a2016-06-10 09:57:59 +00001253 void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands);
1254 void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands);
Sam Koltonf7659d712017-05-23 10:08:55 +00001255 void cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands);
Sam Kolton5196b882016-07-01 09:59:21 +00001256 void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands);
1257 void cvtSDWA(MCInst &Inst, const OperandVector &Operands,
Sam Koltonf7659d712017-05-23 10:08:55 +00001258 uint64_t BasicInstType, bool skipVcc = false);
David Stuttard20ea21c2019-03-12 09:52:58 +00001259
1260 OperandMatchResultTy parseEndpgmOp(OperandVector &Operands);
1261 AMDGPUOperand::Ptr defaultEndpgmImmOperands() const;
Tom Stellard45bb48e2015-06-13 03:28:10 +00001262};
1263
1264struct OptionalOperand {
1265 const char *Name;
1266 AMDGPUOperand::ImmTy Type;
1267 bool IsBit;
Tom Stellard45bb48e2015-06-13 03:28:10 +00001268 bool (*ConvertResult)(int64_t&);
1269};
1270
Eugene Zelenko2bc2f332016-12-09 22:06:55 +00001271} // end anonymous namespace
1272
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001273// May be called with integer type with equivalent bitwidth.
Matt Arsenault4bd72362016-12-10 00:39:12 +00001274static const fltSemantics *getFltSemantics(unsigned Size) {
1275 switch (Size) {
1276 case 4:
Stephan Bergmann17c7f702016-12-14 11:57:17 +00001277 return &APFloat::IEEEsingle();
Matt Arsenault4bd72362016-12-10 00:39:12 +00001278 case 8:
Stephan Bergmann17c7f702016-12-14 11:57:17 +00001279 return &APFloat::IEEEdouble();
Matt Arsenault4bd72362016-12-10 00:39:12 +00001280 case 2:
Stephan Bergmann17c7f702016-12-14 11:57:17 +00001281 return &APFloat::IEEEhalf();
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001282 default:
1283 llvm_unreachable("unsupported fp type");
1284 }
1285}
1286
Matt Arsenault4bd72362016-12-10 00:39:12 +00001287static const fltSemantics *getFltSemantics(MVT VT) {
1288 return getFltSemantics(VT.getSizeInBits() / 8);
1289}
1290
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001291static const fltSemantics *getOpFltSemantics(uint8_t OperandType) {
1292 switch (OperandType) {
1293 case AMDGPU::OPERAND_REG_IMM_INT32:
1294 case AMDGPU::OPERAND_REG_IMM_FP32:
1295 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1296 case AMDGPU::OPERAND_REG_INLINE_C_FP32:
1297 return &APFloat::IEEEsingle();
1298 case AMDGPU::OPERAND_REG_IMM_INT64:
1299 case AMDGPU::OPERAND_REG_IMM_FP64:
1300 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
1301 case AMDGPU::OPERAND_REG_INLINE_C_FP64:
1302 return &APFloat::IEEEdouble();
1303 case AMDGPU::OPERAND_REG_IMM_INT16:
1304 case AMDGPU::OPERAND_REG_IMM_FP16:
1305 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1306 case AMDGPU::OPERAND_REG_INLINE_C_FP16:
1307 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1308 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00001309 case AMDGPU::OPERAND_REG_IMM_V2INT16:
1310 case AMDGPU::OPERAND_REG_IMM_V2FP16:
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001311 return &APFloat::IEEEhalf();
1312 default:
1313 llvm_unreachable("unsupported fp type");
1314 }
1315}
1316
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001317//===----------------------------------------------------------------------===//
1318// Operand
1319//===----------------------------------------------------------------------===//
1320
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001321static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT) {
1322 bool Lost;
1323
1324 // Convert literal to single precision
1325 APFloat::opStatus Status = FPLiteral.convert(*getFltSemantics(VT),
1326 APFloat::rmNearestTiesToEven,
1327 &Lost);
1328 // We allow precision lost but not overflow or underflow
1329 if (Status != APFloat::opOK &&
1330 Lost &&
1331 ((Status & APFloat::opOverflow) != 0 ||
1332 (Status & APFloat::opUnderflow) != 0)) {
1333 return false;
1334 }
1335
1336 return true;
1337}
1338
Dmitry Preobrazhenskyd6827ce2019-03-29 14:50:20 +00001339static bool isSafeTruncation(int64_t Val, unsigned Size) {
1340 return isUIntN(Size, Val) || isIntN(Size, Val);
1341}
1342
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001343bool AMDGPUOperand::isInlinableImm(MVT type) const {
Dmitry Preobrazhensky137976f2019-03-20 15:40:52 +00001344
1345 // This is a hack to enable named inline values like
1346 // shared_base with both 32-bit and 64-bit operands.
1347 // Note that these values are defined as
1348 // 32-bit operands only.
1349 if (isInlineValue()) {
1350 return true;
1351 }
1352
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001353 if (!isImmTy(ImmTyNone)) {
1354 // Only plain immediates are inlinable (e.g. "clamp" attribute is not)
1355 return false;
1356 }
1357 // TODO: We should avoid using host float here. It would be better to
1358 // check the float bit values which is what a few other places do.
1359 // We've had bot failures before due to weird NaN support on mips hosts.
1360
1361 APInt Literal(64, Imm.Val);
1362
1363 if (Imm.IsFPImm) { // We got fp literal token
1364 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
Matt Arsenault26faed32016-12-05 22:26:17 +00001365 return AMDGPU::isInlinableLiteral64(Imm.Val,
1366 AsmParser->hasInv2PiInlineImm());
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001367 }
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001368
Stephan Bergmann17c7f702016-12-14 11:57:17 +00001369 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001370 if (!canLosslesslyConvertToFPType(FPLiteral, type))
1371 return false;
1372
Sam Kolton9dffada2017-01-17 15:26:02 +00001373 if (type.getScalarSizeInBits() == 16) {
1374 return AMDGPU::isInlinableLiteral16(
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001375 static_cast<int16_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
Sam Kolton9dffada2017-01-17 15:26:02 +00001376 AsmParser->hasInv2PiInlineImm());
1377 }
1378
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001379 // Check if single precision literal is inlinable
1380 return AMDGPU::isInlinableLiteral32(
1381 static_cast<int32_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
Matt Arsenault26faed32016-12-05 22:26:17 +00001382 AsmParser->hasInv2PiInlineImm());
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001383 }
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001384
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001385 // We got int literal token.
1386 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
Matt Arsenault26faed32016-12-05 22:26:17 +00001387 return AMDGPU::isInlinableLiteral64(Imm.Val,
1388 AsmParser->hasInv2PiInlineImm());
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001389 }
1390
Dmitry Preobrazhenskyd6827ce2019-03-29 14:50:20 +00001391 if (!isSafeTruncation(Imm.Val, type.getScalarSizeInBits())) {
1392 return false;
1393 }
1394
Matt Arsenault4bd72362016-12-10 00:39:12 +00001395 if (type.getScalarSizeInBits() == 16) {
1396 return AMDGPU::isInlinableLiteral16(
1397 static_cast<int16_t>(Literal.getLoBits(16).getSExtValue()),
1398 AsmParser->hasInv2PiInlineImm());
1399 }
1400
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001401 return AMDGPU::isInlinableLiteral32(
1402 static_cast<int32_t>(Literal.getLoBits(32).getZExtValue()),
Matt Arsenault26faed32016-12-05 22:26:17 +00001403 AsmParser->hasInv2PiInlineImm());
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001404}
1405
1406bool AMDGPUOperand::isLiteralImm(MVT type) const {
Hiroshi Inoue7f46baf2017-07-16 08:11:56 +00001407 // Check that this immediate can be added as literal
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001408 if (!isImmTy(ImmTyNone)) {
1409 return false;
1410 }
1411
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001412 if (!Imm.IsFPImm) {
1413 // We got int literal token.
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001414
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +00001415 if (type == MVT::f64 && hasFPModifiers()) {
1416 // Cannot apply fp modifiers to int literals preserving the same semantics
1417 // for VOP1/2/C and VOP3 because of integer truncation. To avoid ambiguity,
1418 // disable these cases.
1419 return false;
1420 }
1421
Matt Arsenault4bd72362016-12-10 00:39:12 +00001422 unsigned Size = type.getSizeInBits();
1423 if (Size == 64)
1424 Size = 32;
1425
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001426 // FIXME: 64-bit operands can zero extend, sign extend, or pad zeroes for FP
1427 // types.
Dmitry Preobrazhenskyd6827ce2019-03-29 14:50:20 +00001428 return isSafeTruncation(Imm.Val, Size);
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001429 }
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001430
1431 // We got fp literal token
1432 if (type == MVT::f64) { // Expected 64-bit fp operand
1433 // We would set low 64-bits of literal to zeroes but we accept this literals
1434 return true;
1435 }
1436
1437 if (type == MVT::i64) { // Expected 64-bit int operand
1438 // We don't allow fp literals in 64-bit integer instructions. It is
1439 // unclear how we should encode them.
1440 return false;
1441 }
1442
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00001443 // We allow fp literals with f16x2 operands assuming that the specified
1444 // literal goes into the lower half and the upper half is zero. We also
1445 // require that the literal may be losslesly converted to f16.
1446 MVT ExpectedType = (type == MVT::v2f16)? MVT::f16 :
1447 (type == MVT::v2i16)? MVT::i16 : type;
1448
Stephan Bergmann17c7f702016-12-14 11:57:17 +00001449 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00001450 return canLosslesslyConvertToFPType(FPLiteral, ExpectedType);
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001451}
1452
1453bool AMDGPUOperand::isRegClass(unsigned RCID) const {
Sam Kolton9772eb32017-01-11 11:46:30 +00001454 return isRegKind() && AsmParser->getMRI()->getRegClass(RCID).contains(getReg());
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001455}
1456
Dmitry Preobrazhensky6b65f7c2018-01-17 14:00:48 +00001457bool AMDGPUOperand::isSDWAOperand(MVT type) const {
Sam Kolton549c89d2017-06-21 08:53:38 +00001458 if (AsmParser->isVI())
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +00001459 return isVReg32();
Stanislav Mekhanoshincee607e2019-04-24 17:03:15 +00001460 else if (AsmParser->isGFX9() || AsmParser->isGFX10())
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +00001461 return isRegClass(AMDGPU::VS_32RegClassID) || isInlinableImm(type);
Sam Kolton549c89d2017-06-21 08:53:38 +00001462 else
1463 return false;
1464}
1465
Dmitry Preobrazhensky6b65f7c2018-01-17 14:00:48 +00001466bool AMDGPUOperand::isSDWAFP16Operand() const {
1467 return isSDWAOperand(MVT::f16);
1468}
1469
1470bool AMDGPUOperand::isSDWAFP32Operand() const {
1471 return isSDWAOperand(MVT::f32);
1472}
1473
1474bool AMDGPUOperand::isSDWAInt16Operand() const {
1475 return isSDWAOperand(MVT::i16);
1476}
1477
1478bool AMDGPUOperand::isSDWAInt32Operand() const {
1479 return isSDWAOperand(MVT::i32);
1480}
1481
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +00001482uint64_t AMDGPUOperand::applyInputFPModifiers(uint64_t Val, unsigned Size) const
1483{
1484 assert(isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
1485 assert(Size == 2 || Size == 4 || Size == 8);
1486
1487 const uint64_t FpSignMask = (1ULL << (Size * 8 - 1));
1488
1489 if (Imm.Mods.Abs) {
1490 Val &= ~FpSignMask;
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001491 }
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +00001492 if (Imm.Mods.Neg) {
1493 Val ^= FpSignMask;
1494 }
1495
1496 return Val;
1497}
1498
1499void AMDGPUOperand::addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers) const {
Matt Arsenault4bd72362016-12-10 00:39:12 +00001500 if (AMDGPU::isSISrcOperand(AsmParser->getMII()->get(Inst.getOpcode()),
1501 Inst.getNumOperands())) {
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +00001502 addLiteralImmOperand(Inst, Imm.Val,
1503 ApplyModifiers &
1504 isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001505 } else {
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +00001506 assert(!isImmTy(ImmTyNone) || !hasModifiers());
1507 Inst.addOperand(MCOperand::createImm(Imm.Val));
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001508 }
1509}
1510
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +00001511void AMDGPUOperand::addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001512 const auto& InstDesc = AsmParser->getMII()->get(Inst.getOpcode());
1513 auto OpNum = Inst.getNumOperands();
1514 // Check that this operand accepts literals
1515 assert(AMDGPU::isSISrcOperand(InstDesc, OpNum));
1516
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +00001517 if (ApplyModifiers) {
1518 assert(AMDGPU::isSISrcFPOperand(InstDesc, OpNum));
1519 const unsigned Size = Imm.IsFPImm ? sizeof(double) : getOperandSize(InstDesc, OpNum);
1520 Val = applyInputFPModifiers(Val, Size);
1521 }
1522
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001523 APInt Literal(64, Val);
1524 uint8_t OpTy = InstDesc.OpInfo[OpNum].OperandType;
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001525
1526 if (Imm.IsFPImm) { // We got fp literal token
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001527 switch (OpTy) {
1528 case AMDGPU::OPERAND_REG_IMM_INT64:
1529 case AMDGPU::OPERAND_REG_IMM_FP64:
1530 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001531 case AMDGPU::OPERAND_REG_INLINE_C_FP64:
Matt Arsenault26faed32016-12-05 22:26:17 +00001532 if (AMDGPU::isInlinableLiteral64(Literal.getZExtValue(),
1533 AsmParser->hasInv2PiInlineImm())) {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001534 Inst.addOperand(MCOperand::createImm(Literal.getZExtValue()));
Matt Arsenault4bd72362016-12-10 00:39:12 +00001535 return;
1536 }
1537
1538 // Non-inlineable
1539 if (AMDGPU::isSISrcFPOperand(InstDesc, OpNum)) { // Expected 64-bit fp operand
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001540 // For fp operands we check if low 32 bits are zeros
1541 if (Literal.getLoBits(32) != 0) {
1542 const_cast<AMDGPUAsmParser *>(AsmParser)->Warning(Inst.getLoc(),
Matt Arsenault4bd72362016-12-10 00:39:12 +00001543 "Can't encode literal as exact 64-bit floating-point operand. "
1544 "Low 32-bits will be set to zero");
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001545 }
Matt Arsenault4bd72362016-12-10 00:39:12 +00001546
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001547 Inst.addOperand(MCOperand::createImm(Literal.lshr(32).getZExtValue()));
Matt Arsenault4bd72362016-12-10 00:39:12 +00001548 return;
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001549 }
Matt Arsenault4bd72362016-12-10 00:39:12 +00001550
1551 // We don't allow fp literals in 64-bit integer instructions. It is
1552 // unclear how we should encode them. This case should be checked earlier
1553 // in predicate methods (isLiteralImm())
1554 llvm_unreachable("fp literal in 64-bit integer instruction.");
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001555
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001556 case AMDGPU::OPERAND_REG_IMM_INT32:
1557 case AMDGPU::OPERAND_REG_IMM_FP32:
1558 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1559 case AMDGPU::OPERAND_REG_INLINE_C_FP32:
1560 case AMDGPU::OPERAND_REG_IMM_INT16:
1561 case AMDGPU::OPERAND_REG_IMM_FP16:
1562 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1563 case AMDGPU::OPERAND_REG_INLINE_C_FP16:
1564 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00001565 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
1566 case AMDGPU::OPERAND_REG_IMM_V2INT16:
1567 case AMDGPU::OPERAND_REG_IMM_V2FP16: {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001568 bool lost;
Stephan Bergmann17c7f702016-12-14 11:57:17 +00001569 APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001570 // Convert literal to single precision
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001571 FPLiteral.convert(*getOpFltSemantics(OpTy),
Matt Arsenault4bd72362016-12-10 00:39:12 +00001572 APFloat::rmNearestTiesToEven, &lost);
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001573 // We allow precision lost but not overflow or underflow. This should be
1574 // checked earlier in isLiteralImm()
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001575
1576 uint64_t ImmVal = FPLiteral.bitcastToAPInt().getZExtValue();
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001577 Inst.addOperand(MCOperand::createImm(ImmVal));
Matt Arsenault4bd72362016-12-10 00:39:12 +00001578 return;
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001579 }
Matt Arsenault4bd72362016-12-10 00:39:12 +00001580 default:
1581 llvm_unreachable("invalid operand size");
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001582 }
Matt Arsenault4bd72362016-12-10 00:39:12 +00001583
1584 return;
1585 }
1586
Dmitry Preobrazhenskyd6827ce2019-03-29 14:50:20 +00001587 // We got int literal token.
Matt Arsenault4bd72362016-12-10 00:39:12 +00001588 // Only sign extend inline immediates.
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001589 switch (OpTy) {
1590 case AMDGPU::OPERAND_REG_IMM_INT32:
1591 case AMDGPU::OPERAND_REG_IMM_FP32:
1592 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001593 case AMDGPU::OPERAND_REG_INLINE_C_FP32:
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00001594 case AMDGPU::OPERAND_REG_IMM_V2INT16:
1595 case AMDGPU::OPERAND_REG_IMM_V2FP16:
Dmitry Preobrazhenskyd6827ce2019-03-29 14:50:20 +00001596 if (isSafeTruncation(Val, 32) &&
Matt Arsenault4bd72362016-12-10 00:39:12 +00001597 AMDGPU::isInlinableLiteral32(static_cast<int32_t>(Val),
1598 AsmParser->hasInv2PiInlineImm())) {
1599 Inst.addOperand(MCOperand::createImm(Val));
1600 return;
1601 }
1602
1603 Inst.addOperand(MCOperand::createImm(Val & 0xffffffff));
1604 return;
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001605
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001606 case AMDGPU::OPERAND_REG_IMM_INT64:
1607 case AMDGPU::OPERAND_REG_IMM_FP64:
1608 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001609 case AMDGPU::OPERAND_REG_INLINE_C_FP64:
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001610 if (AMDGPU::isInlinableLiteral64(Val, AsmParser->hasInv2PiInlineImm())) {
Matt Arsenault4bd72362016-12-10 00:39:12 +00001611 Inst.addOperand(MCOperand::createImm(Val));
1612 return;
1613 }
1614
1615 Inst.addOperand(MCOperand::createImm(Lo_32(Val)));
1616 return;
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001617
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001618 case AMDGPU::OPERAND_REG_IMM_INT16:
1619 case AMDGPU::OPERAND_REG_IMM_FP16:
1620 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001621 case AMDGPU::OPERAND_REG_INLINE_C_FP16:
Dmitry Preobrazhenskyd6827ce2019-03-29 14:50:20 +00001622 if (isSafeTruncation(Val, 16) &&
Matt Arsenault4bd72362016-12-10 00:39:12 +00001623 AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val),
1624 AsmParser->hasInv2PiInlineImm())) {
1625 Inst.addOperand(MCOperand::createImm(Val));
1626 return;
1627 }
1628
1629 Inst.addOperand(MCOperand::createImm(Val & 0xffff));
1630 return;
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001631
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001632 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1633 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: {
Dmitry Preobrazhenskyd6827ce2019-03-29 14:50:20 +00001634 assert(isSafeTruncation(Val, 16));
1635 assert(AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val),
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001636 AsmParser->hasInv2PiInlineImm()));
Eugene Zelenko66203762017-01-21 00:53:49 +00001637
Dmitry Preobrazhenskyd6827ce2019-03-29 14:50:20 +00001638 Inst.addOperand(MCOperand::createImm(Val));
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001639 return;
1640 }
Matt Arsenault4bd72362016-12-10 00:39:12 +00001641 default:
1642 llvm_unreachable("invalid operand size");
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001643 }
1644}
1645
Matt Arsenault4bd72362016-12-10 00:39:12 +00001646template <unsigned Bitwidth>
1647void AMDGPUOperand::addKImmFPOperands(MCInst &Inst, unsigned N) const {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001648 APInt Literal(64, Imm.Val);
Matt Arsenault4bd72362016-12-10 00:39:12 +00001649
1650 if (!Imm.IsFPImm) {
1651 // We got int literal token.
1652 Inst.addOperand(MCOperand::createImm(Literal.getLoBits(Bitwidth).getZExtValue()));
1653 return;
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001654 }
Matt Arsenault4bd72362016-12-10 00:39:12 +00001655
1656 bool Lost;
Stephan Bergmann17c7f702016-12-14 11:57:17 +00001657 APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
Matt Arsenault4bd72362016-12-10 00:39:12 +00001658 FPLiteral.convert(*getFltSemantics(Bitwidth / 8),
1659 APFloat::rmNearestTiesToEven, &Lost);
1660 Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue()));
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001661}
1662
1663void AMDGPUOperand::addRegOperands(MCInst &Inst, unsigned N) const {
1664 Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), AsmParser->getSTI())));
1665}
1666
Dmitry Preobrazhensky137976f2019-03-20 15:40:52 +00001667static bool isInlineValue(unsigned Reg) {
1668 switch (Reg) {
1669 case AMDGPU::SRC_SHARED_BASE:
1670 case AMDGPU::SRC_SHARED_LIMIT:
1671 case AMDGPU::SRC_PRIVATE_BASE:
1672 case AMDGPU::SRC_PRIVATE_LIMIT:
1673 case AMDGPU::SRC_POPS_EXITING_WAVE_ID:
1674 return true;
Dmitry Preobrazhensky9111f352019-06-03 13:51:24 +00001675 case AMDGPU::SRC_VCCZ:
1676 case AMDGPU::SRC_EXECZ:
1677 case AMDGPU::SRC_SCC:
1678 return true;
Dmitry Preobrazhensky137976f2019-03-20 15:40:52 +00001679 default:
1680 return false;
1681 }
1682}
1683
1684bool AMDGPUOperand::isInlineValue() const {
1685 return isRegKind() && ::isInlineValue(getReg());
1686}
1687
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001688//===----------------------------------------------------------------------===//
1689// AsmParser
1690//===----------------------------------------------------------------------===//
1691
Artem Tamazoveb4d5a92016-04-13 16:18:41 +00001692static int getRegClass(RegisterKind Is, unsigned RegWidth) {
1693 if (Is == IS_VGPR) {
Tom Stellard45bb48e2015-06-13 03:28:10 +00001694 switch (RegWidth) {
Matt Arsenault967c2f52015-11-03 22:50:32 +00001695 default: return -1;
Tom Stellard45bb48e2015-06-13 03:28:10 +00001696 case 1: return AMDGPU::VGPR_32RegClassID;
1697 case 2: return AMDGPU::VReg_64RegClassID;
1698 case 3: return AMDGPU::VReg_96RegClassID;
1699 case 4: return AMDGPU::VReg_128RegClassID;
1700 case 8: return AMDGPU::VReg_256RegClassID;
1701 case 16: return AMDGPU::VReg_512RegClassID;
1702 }
Artem Tamazoveb4d5a92016-04-13 16:18:41 +00001703 } else if (Is == IS_TTMP) {
1704 switch (RegWidth) {
1705 default: return -1;
1706 case 1: return AMDGPU::TTMP_32RegClassID;
1707 case 2: return AMDGPU::TTMP_64RegClassID;
Artem Tamazov38e496b2016-04-29 17:04:50 +00001708 case 4: return AMDGPU::TTMP_128RegClassID;
Dmitry Preobrazhensky27134952017-12-22 15:18:06 +00001709 case 8: return AMDGPU::TTMP_256RegClassID;
1710 case 16: return AMDGPU::TTMP_512RegClassID;
Artem Tamazoveb4d5a92016-04-13 16:18:41 +00001711 }
1712 } else if (Is == IS_SGPR) {
1713 switch (RegWidth) {
1714 default: return -1;
1715 case 1: return AMDGPU::SGPR_32RegClassID;
1716 case 2: return AMDGPU::SGPR_64RegClassID;
Artem Tamazov38e496b2016-04-29 17:04:50 +00001717 case 4: return AMDGPU::SGPR_128RegClassID;
Dmitry Preobrazhensky27134952017-12-22 15:18:06 +00001718 case 8: return AMDGPU::SGPR_256RegClassID;
1719 case 16: return AMDGPU::SGPR_512RegClassID;
Artem Tamazoveb4d5a92016-04-13 16:18:41 +00001720 }
Tom Stellard45bb48e2015-06-13 03:28:10 +00001721 }
Artem Tamazoveb4d5a92016-04-13 16:18:41 +00001722 return -1;
Tom Stellard45bb48e2015-06-13 03:28:10 +00001723}
1724
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001725static unsigned getSpecialRegForName(StringRef RegName) {
Tom Stellard45bb48e2015-06-13 03:28:10 +00001726 return StringSwitch<unsigned>(RegName)
1727 .Case("exec", AMDGPU::EXEC)
1728 .Case("vcc", AMDGPU::VCC)
Matt Arsenaultaac9b492015-11-03 22:50:34 +00001729 .Case("flat_scratch", AMDGPU::FLAT_SCR)
Dmitry Preobrazhensky3afbd822018-01-10 14:22:19 +00001730 .Case("xnack_mask", AMDGPU::XNACK_MASK)
Dmitry Preobrazhensky137976f2019-03-20 15:40:52 +00001731 .Case("shared_base", AMDGPU::SRC_SHARED_BASE)
1732 .Case("src_shared_base", AMDGPU::SRC_SHARED_BASE)
1733 .Case("shared_limit", AMDGPU::SRC_SHARED_LIMIT)
1734 .Case("src_shared_limit", AMDGPU::SRC_SHARED_LIMIT)
1735 .Case("private_base", AMDGPU::SRC_PRIVATE_BASE)
1736 .Case("src_private_base", AMDGPU::SRC_PRIVATE_BASE)
1737 .Case("private_limit", AMDGPU::SRC_PRIVATE_LIMIT)
1738 .Case("src_private_limit", AMDGPU::SRC_PRIVATE_LIMIT)
1739 .Case("pops_exiting_wave_id", AMDGPU::SRC_POPS_EXITING_WAVE_ID)
1740 .Case("src_pops_exiting_wave_id", AMDGPU::SRC_POPS_EXITING_WAVE_ID)
Dmitry Preobrazhensky942c2732019-02-08 14:57:37 +00001741 .Case("lds_direct", AMDGPU::LDS_DIRECT)
1742 .Case("src_lds_direct", AMDGPU::LDS_DIRECT)
Tom Stellard45bb48e2015-06-13 03:28:10 +00001743 .Case("m0", AMDGPU::M0)
Dmitry Preobrazhensky9111f352019-06-03 13:51:24 +00001744 .Case("vccz", AMDGPU::SRC_VCCZ)
1745 .Case("src_vccz", AMDGPU::SRC_VCCZ)
1746 .Case("execz", AMDGPU::SRC_EXECZ)
1747 .Case("src_execz", AMDGPU::SRC_EXECZ)
1748 .Case("scc", AMDGPU::SRC_SCC)
1749 .Case("src_scc", AMDGPU::SRC_SCC)
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001750 .Case("tba", AMDGPU::TBA)
1751 .Case("tma", AMDGPU::TMA)
Matt Arsenaultaac9b492015-11-03 22:50:34 +00001752 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
1753 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
Dmitry Preobrazhensky3afbd822018-01-10 14:22:19 +00001754 .Case("xnack_mask_lo", AMDGPU::XNACK_MASK_LO)
1755 .Case("xnack_mask_hi", AMDGPU::XNACK_MASK_HI)
Tom Stellard45bb48e2015-06-13 03:28:10 +00001756 .Case("vcc_lo", AMDGPU::VCC_LO)
1757 .Case("vcc_hi", AMDGPU::VCC_HI)
1758 .Case("exec_lo", AMDGPU::EXEC_LO)
1759 .Case("exec_hi", AMDGPU::EXEC_HI)
Artem Tamazoveb4d5a92016-04-13 16:18:41 +00001760 .Case("tma_lo", AMDGPU::TMA_LO)
1761 .Case("tma_hi", AMDGPU::TMA_HI)
1762 .Case("tba_lo", AMDGPU::TBA_LO)
1763 .Case("tba_hi", AMDGPU::TBA_HI)
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00001764 .Case("null", AMDGPU::SGPR_NULL)
Tom Stellard45bb48e2015-06-13 03:28:10 +00001765 .Default(0);
1766}
1767
Eugene Zelenko66203762017-01-21 00:53:49 +00001768bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1769 SMLoc &EndLoc) {
Valery Pykhtin0f97f172016-03-14 07:43:42 +00001770 auto R = parseRegister();
1771 if (!R) return true;
1772 assert(R->isReg());
1773 RegNo = R->getReg();
1774 StartLoc = R->getStartLoc();
1775 EndLoc = R->getEndLoc();
1776 return false;
1777}
1778
Eugene Zelenko66203762017-01-21 00:53:49 +00001779bool AMDGPUAsmParser::AddNextRegisterToList(unsigned &Reg, unsigned &RegWidth,
1780 RegisterKind RegKind, unsigned Reg1,
1781 unsigned RegNum) {
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001782 switch (RegKind) {
1783 case IS_SPECIAL:
Eugene Zelenko66203762017-01-21 00:53:49 +00001784 if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) {
1785 Reg = AMDGPU::EXEC;
1786 RegWidth = 2;
1787 return true;
1788 }
1789 if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) {
1790 Reg = AMDGPU::FLAT_SCR;
1791 RegWidth = 2;
1792 return true;
1793 }
Dmitry Preobrazhensky3afbd822018-01-10 14:22:19 +00001794 if (Reg == AMDGPU::XNACK_MASK_LO && Reg1 == AMDGPU::XNACK_MASK_HI) {
1795 Reg = AMDGPU::XNACK_MASK;
1796 RegWidth = 2;
1797 return true;
1798 }
Eugene Zelenko66203762017-01-21 00:53:49 +00001799 if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) {
1800 Reg = AMDGPU::VCC;
1801 RegWidth = 2;
1802 return true;
1803 }
1804 if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) {
1805 Reg = AMDGPU::TBA;
1806 RegWidth = 2;
1807 return true;
1808 }
1809 if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) {
1810 Reg = AMDGPU::TMA;
1811 RegWidth = 2;
1812 return true;
1813 }
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001814 return false;
1815 case IS_VGPR:
1816 case IS_SGPR:
1817 case IS_TTMP:
Eugene Zelenko66203762017-01-21 00:53:49 +00001818 if (Reg1 != Reg + RegWidth) {
1819 return false;
1820 }
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001821 RegWidth++;
1822 return true;
1823 default:
Matt Arsenault92b355b2016-11-15 19:34:37 +00001824 llvm_unreachable("unexpected register kind");
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001825 }
1826}
1827
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00001828static const StringRef Registers[] = {
1829 { "v" },
1830 { "s" },
1831 { "ttmp" },
1832};
1833
1834bool
1835AMDGPUAsmParser::isRegister(const AsmToken &Token,
1836 const AsmToken &NextToken) const {
1837
1838 // A list of consecutive registers: [s0,s1,s2,s3]
1839 if (Token.is(AsmToken::LBrac))
1840 return true;
1841
1842 if (!Token.is(AsmToken::Identifier))
1843 return false;
1844
1845 // A single register like s0 or a range of registers like s[0:1]
1846
1847 StringRef RegName = Token.getString();
1848
1849 for (StringRef Reg : Registers) {
1850 if (RegName.startswith(Reg)) {
1851 if (Reg.size() < RegName.size()) {
1852 unsigned RegNum;
1853 // A single register with an index: rXX
1854 if (!RegName.substr(Reg.size()).getAsInteger(10, RegNum))
1855 return true;
1856 } else {
1857 // A range of registers: r[XX:YY].
1858 if (NextToken.is(AsmToken::LBrac))
1859 return true;
1860 }
1861 }
1862 }
1863
1864 return getSpecialRegForName(RegName);
1865}
1866
1867bool
1868AMDGPUAsmParser::isRegister()
1869{
1870 return isRegister(getToken(), peekToken());
1871}
1872
Eugene Zelenko66203762017-01-21 00:53:49 +00001873bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg,
1874 unsigned &RegNum, unsigned &RegWidth,
1875 unsigned *DwordRegIndex) {
Artem Tamazova01cce82016-12-27 16:00:11 +00001876 if (DwordRegIndex) { *DwordRegIndex = 0; }
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001877 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
1878 if (getLexer().is(AsmToken::Identifier)) {
1879 StringRef RegName = Parser.getTok().getString();
1880 if ((Reg = getSpecialRegForName(RegName))) {
1881 Parser.Lex();
1882 RegKind = IS_SPECIAL;
1883 } else {
1884 unsigned RegNumIndex = 0;
Artem Tamazovf88397c2016-06-03 14:41:17 +00001885 if (RegName[0] == 'v') {
1886 RegNumIndex = 1;
1887 RegKind = IS_VGPR;
1888 } else if (RegName[0] == 's') {
1889 RegNumIndex = 1;
1890 RegKind = IS_SGPR;
1891 } else if (RegName.startswith("ttmp")) {
1892 RegNumIndex = strlen("ttmp");
1893 RegKind = IS_TTMP;
1894 } else {
1895 return false;
1896 }
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001897 if (RegName.size() > RegNumIndex) {
1898 // Single 32-bit register: vXX.
Artem Tamazovf88397c2016-06-03 14:41:17 +00001899 if (RegName.substr(RegNumIndex).getAsInteger(10, RegNum))
1900 return false;
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001901 Parser.Lex();
1902 RegWidth = 1;
1903 } else {
Artem Tamazov7da9b822016-05-27 12:50:13 +00001904 // Range of registers: v[XX:YY]. ":YY" is optional.
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001905 Parser.Lex();
1906 int64_t RegLo, RegHi;
Artem Tamazovf88397c2016-06-03 14:41:17 +00001907 if (getLexer().isNot(AsmToken::LBrac))
1908 return false;
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001909 Parser.Lex();
1910
Artem Tamazovf88397c2016-06-03 14:41:17 +00001911 if (getParser().parseAbsoluteExpression(RegLo))
1912 return false;
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001913
Artem Tamazov7da9b822016-05-27 12:50:13 +00001914 const bool isRBrace = getLexer().is(AsmToken::RBrac);
Artem Tamazovf88397c2016-06-03 14:41:17 +00001915 if (!isRBrace && getLexer().isNot(AsmToken::Colon))
1916 return false;
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001917 Parser.Lex();
1918
Artem Tamazov7da9b822016-05-27 12:50:13 +00001919 if (isRBrace) {
1920 RegHi = RegLo;
1921 } else {
Artem Tamazovf88397c2016-06-03 14:41:17 +00001922 if (getParser().parseAbsoluteExpression(RegHi))
1923 return false;
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001924
Artem Tamazovf88397c2016-06-03 14:41:17 +00001925 if (getLexer().isNot(AsmToken::RBrac))
1926 return false;
Artem Tamazov7da9b822016-05-27 12:50:13 +00001927 Parser.Lex();
1928 }
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001929 RegNum = (unsigned) RegLo;
1930 RegWidth = (RegHi - RegLo) + 1;
1931 }
1932 }
1933 } else if (getLexer().is(AsmToken::LBrac)) {
1934 // List of consecutive registers: [s0,s1,s2,s3]
1935 Parser.Lex();
Artem Tamazova01cce82016-12-27 16:00:11 +00001936 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, nullptr))
Artem Tamazovf88397c2016-06-03 14:41:17 +00001937 return false;
1938 if (RegWidth != 1)
1939 return false;
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001940 RegisterKind RegKind1;
1941 unsigned Reg1, RegNum1, RegWidth1;
1942 do {
1943 if (getLexer().is(AsmToken::Comma)) {
1944 Parser.Lex();
1945 } else if (getLexer().is(AsmToken::RBrac)) {
1946 Parser.Lex();
1947 break;
Artem Tamazova01cce82016-12-27 16:00:11 +00001948 } else if (ParseAMDGPURegister(RegKind1, Reg1, RegNum1, RegWidth1, nullptr)) {
Artem Tamazovf88397c2016-06-03 14:41:17 +00001949 if (RegWidth1 != 1) {
1950 return false;
1951 }
1952 if (RegKind1 != RegKind) {
1953 return false;
1954 }
1955 if (!AddNextRegisterToList(Reg, RegWidth, RegKind1, Reg1, RegNum1)) {
1956 return false;
1957 }
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001958 } else {
1959 return false;
1960 }
1961 } while (true);
1962 } else {
1963 return false;
1964 }
1965 switch (RegKind) {
1966 case IS_SPECIAL:
1967 RegNum = 0;
1968 RegWidth = 1;
1969 break;
1970 case IS_VGPR:
1971 case IS_SGPR:
1972 case IS_TTMP:
1973 {
1974 unsigned Size = 1;
1975 if (RegKind == IS_SGPR || RegKind == IS_TTMP) {
Artem Tamazova01cce82016-12-27 16:00:11 +00001976 // SGPR and TTMP registers must be aligned. Max required alignment is 4 dwords.
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001977 Size = std::min(RegWidth, 4u);
1978 }
Artem Tamazovf88397c2016-06-03 14:41:17 +00001979 if (RegNum % Size != 0)
1980 return false;
Artem Tamazova01cce82016-12-27 16:00:11 +00001981 if (DwordRegIndex) { *DwordRegIndex = RegNum; }
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001982 RegNum = RegNum / Size;
1983 int RCID = getRegClass(RegKind, RegWidth);
Artem Tamazovf88397c2016-06-03 14:41:17 +00001984 if (RCID == -1)
1985 return false;
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001986 const MCRegisterClass RC = TRI->getRegClass(RCID);
Artem Tamazovf88397c2016-06-03 14:41:17 +00001987 if (RegNum >= RC.getNumRegs())
1988 return false;
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001989 Reg = RC.getRegister(RegNum);
1990 break;
1991 }
1992
1993 default:
Matt Arsenault92b355b2016-11-15 19:34:37 +00001994 llvm_unreachable("unexpected register kind");
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001995 }
1996
Artem Tamazovf88397c2016-06-03 14:41:17 +00001997 if (!subtargetHasRegister(*TRI, Reg))
1998 return false;
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001999 return true;
2000}
2001
Scott Linder1e8c2c72018-06-21 19:38:56 +00002002Optional<StringRef>
2003AMDGPUAsmParser::getGprCountSymbolName(RegisterKind RegKind) {
2004 switch (RegKind) {
2005 case IS_VGPR:
2006 return StringRef(".amdgcn.next_free_vgpr");
2007 case IS_SGPR:
2008 return StringRef(".amdgcn.next_free_sgpr");
2009 default:
2010 return None;
2011 }
2012}
2013
2014void AMDGPUAsmParser::initializeGprCountSymbol(RegisterKind RegKind) {
2015 auto SymbolName = getGprCountSymbolName(RegKind);
2016 assert(SymbolName && "initializing invalid register kind");
2017 MCSymbol *Sym = getContext().getOrCreateSymbol(*SymbolName);
2018 Sym->setVariableValue(MCConstantExpr::create(0, getContext()));
2019}
2020
2021bool AMDGPUAsmParser::updateGprCountSymbols(RegisterKind RegKind,
2022 unsigned DwordRegIndex,
2023 unsigned RegWidth) {
2024 // Symbols are only defined for GCN targets
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00002025 if (AMDGPU::getIsaVersion(getSTI().getCPU()).Major < 6)
Scott Linder1e8c2c72018-06-21 19:38:56 +00002026 return true;
2027
2028 auto SymbolName = getGprCountSymbolName(RegKind);
2029 if (!SymbolName)
2030 return true;
2031 MCSymbol *Sym = getContext().getOrCreateSymbol(*SymbolName);
2032
2033 int64_t NewMax = DwordRegIndex + RegWidth - 1;
2034 int64_t OldCount;
2035
2036 if (!Sym->isVariable())
2037 return !Error(getParser().getTok().getLoc(),
2038 ".amdgcn.next_free_{v,s}gpr symbols must be variable");
2039 if (!Sym->getVariableValue(false)->evaluateAsAbsolute(OldCount))
2040 return !Error(
2041 getParser().getTok().getLoc(),
2042 ".amdgcn.next_free_{v,s}gpr symbols must be absolute expressions");
2043
2044 if (OldCount <= NewMax)
2045 Sym->setVariableValue(MCConstantExpr::create(NewMax + 1, getContext()));
2046
2047 return true;
2048}
2049
Valery Pykhtin0f97f172016-03-14 07:43:42 +00002050std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() {
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002051 const auto &Tok = Parser.getTok();
Valery Pykhtin0f97f172016-03-14 07:43:42 +00002052 SMLoc StartLoc = Tok.getLoc();
2053 SMLoc EndLoc = Tok.getEndLoc();
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002054 RegisterKind RegKind;
Artem Tamazova01cce82016-12-27 16:00:11 +00002055 unsigned Reg, RegNum, RegWidth, DwordRegIndex;
Tom Stellard45bb48e2015-06-13 03:28:10 +00002056
Artem Tamazova01cce82016-12-27 16:00:11 +00002057 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, &DwordRegIndex)) {
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00002058 //FIXME: improve error messages (bug 41303).
2059 Error(StartLoc, "not a valid operand.");
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002060 return nullptr;
Tom Stellard45bb48e2015-06-13 03:28:10 +00002061 }
Scott Linder1e8c2c72018-06-21 19:38:56 +00002062 if (AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) {
2063 if (!updateGprCountSymbols(RegKind, DwordRegIndex, RegWidth))
2064 return nullptr;
2065 } else
2066 KernelScope.usesRegister(RegKind, DwordRegIndex, RegWidth);
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002067 return AMDGPUOperand::CreateReg(this, Reg, StartLoc, EndLoc);
Tom Stellard45bb48e2015-06-13 03:28:10 +00002068}
2069
Alex Bradbury58eba092016-11-01 16:32:05 +00002070OperandMatchResultTy
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00002071AMDGPUAsmParser::parseImm(OperandVector &Operands, bool HasSP3AbsModifier) {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00002072 // TODO: add syntactic sugar for 1/(2*PI)
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00002073
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +00002074 assert(!isRegister());
2075 assert(!isModifier());
2076
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00002077 const auto& Tok = getToken();
2078 const auto& NextTok = peekToken();
2079 bool IsReal = Tok.is(AsmToken::Real);
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +00002080 SMLoc S = getLoc();
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00002081 bool Negate = false;
2082
2083 if (!IsReal && Tok.is(AsmToken::Minus) && NextTok.is(AsmToken::Real)) {
2084 lex();
2085 IsReal = true;
2086 Negate = true;
Sam Kolton1bdcef72016-05-23 09:59:02 +00002087 }
2088
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00002089 if (IsReal) {
2090 // Floating-point expressions are not supported.
2091 // Can only allow floating-point literals with an
2092 // optional sign.
2093
2094 StringRef Num = getTokenStr();
2095 lex();
2096
2097 APFloat RealVal(APFloat::IEEEdouble());
2098 auto roundMode = APFloat::rmNearestTiesToEven;
2099 if (RealVal.convertFromString(Num, roundMode) == APFloat::opInvalidOp) {
Sam Kolton1bdcef72016-05-23 09:59:02 +00002100 return MatchOperand_ParseFail;
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00002101 }
2102 if (Negate)
2103 RealVal.changeSign();
2104
2105 Operands.push_back(
2106 AMDGPUOperand::CreateImm(this, RealVal.bitcastToAPInt().getZExtValue(), S,
2107 AMDGPUOperand::ImmTyNone, true));
2108
2109 return MatchOperand_Success;
2110
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +00002111 } else {
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00002112 int64_t IntVal;
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +00002113 const MCExpr *Expr;
2114 SMLoc S = getLoc();
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00002115
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +00002116 if (HasSP3AbsModifier) {
2117 // This is a workaround for handling expressions
2118 // as arguments of SP3 'abs' modifier, for example:
2119 // |1.0|
2120 // |-1|
2121 // |1+x|
2122 // This syntax is not compatible with syntax of standard
2123 // MC expressions (due to the trailing '|').
2124 SMLoc EndLoc;
2125 if (getParser().parsePrimaryExpr(Expr, EndLoc))
2126 return MatchOperand_ParseFail;
2127 } else {
2128 if (Parser.parseExpression(Expr))
2129 return MatchOperand_ParseFail;
2130 }
2131
2132 if (Expr->evaluateAsAbsolute(IntVal)) {
2133 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S));
2134 } else {
2135 Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S));
2136 }
2137
Sam Kolton1bdcef72016-05-23 09:59:02 +00002138 return MatchOperand_Success;
2139 }
Sam Kolton1bdcef72016-05-23 09:59:02 +00002140
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00002141 return MatchOperand_NoMatch;
Sam Kolton1bdcef72016-05-23 09:59:02 +00002142}
2143
Alex Bradbury58eba092016-11-01 16:32:05 +00002144OperandMatchResultTy
Sam Kolton9772eb32017-01-11 11:46:30 +00002145AMDGPUAsmParser::parseReg(OperandVector &Operands) {
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00002146 if (!isRegister())
2147 return MatchOperand_NoMatch;
2148
Sam Kolton1bdcef72016-05-23 09:59:02 +00002149 if (auto R = parseRegister()) {
2150 assert(R->isReg());
Sam Kolton1bdcef72016-05-23 09:59:02 +00002151 Operands.push_back(std::move(R));
2152 return MatchOperand_Success;
2153 }
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00002154 return MatchOperand_ParseFail;
Sam Kolton1bdcef72016-05-23 09:59:02 +00002155}
2156
Alex Bradbury58eba092016-11-01 16:32:05 +00002157OperandMatchResultTy
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002158AMDGPUAsmParser::parseRegOrImm(OperandVector &Operands, bool HasSP3AbsMod) {
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00002159 auto res = parseReg(Operands);
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +00002160 if (res != MatchOperand_NoMatch) {
2161 return res;
2162 } else if (isModifier()) {
2163 return MatchOperand_NoMatch;
2164 } else {
2165 return parseImm(Operands, HasSP3AbsMod);
2166 }
2167}
2168
2169bool
2170AMDGPUAsmParser::isNamedOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const {
2171 if (Token.is(AsmToken::Identifier) && NextToken.is(AsmToken::LParen)) {
2172 const auto &str = Token.getString();
2173 return str == "abs" || str == "neg" || str == "sext";
2174 }
2175 return false;
2176}
2177
2178bool
2179AMDGPUAsmParser::isOpcodeModifierWithVal(const AsmToken &Token, const AsmToken &NextToken) const {
2180 return Token.is(AsmToken::Identifier) && NextToken.is(AsmToken::Colon);
2181}
2182
2183bool
2184AMDGPUAsmParser::isOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const {
2185 return isNamedOperandModifier(Token, NextToken) || Token.is(AsmToken::Pipe);
2186}
2187
2188bool
2189AMDGPUAsmParser::isRegOrOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const {
2190 return isRegister(Token, NextToken) || isOperandModifier(Token, NextToken);
2191}
2192
2193// Check if this is an operand modifier or an opcode modifier
2194// which may look like an expression but it is not. We should
2195// avoid parsing these modifiers as expressions. Currently
2196// recognized sequences are:
2197// |...|
2198// abs(...)
2199// neg(...)
2200// sext(...)
2201// -reg
2202// -|...|
2203// -abs(...)
2204// name:...
2205// Note that simple opcode modifiers like 'gds' may be parsed as
2206// expressions; this is a special case. See getExpressionAsToken.
2207//
2208bool
2209AMDGPUAsmParser::isModifier() {
2210
2211 AsmToken Tok = getToken();
2212 AsmToken NextToken[2];
2213 peekTokens(NextToken);
2214
2215 return isOperandModifier(Tok, NextToken[0]) ||
2216 (Tok.is(AsmToken::Minus) && isRegOrOperandModifier(NextToken[0], NextToken[1])) ||
2217 isOpcodeModifierWithVal(Tok, NextToken[0]);
Sam Kolton9772eb32017-01-11 11:46:30 +00002218}
2219
Dmitry Preobrazhenskye2707f52019-04-22 14:35:47 +00002220// Check if the current token is an SP3 'neg' modifier.
2221// Currently this modifier is allowed in the following context:
2222//
2223// 1. Before a register, e.g. "-v0", "-v[...]" or "-[v0,v1]".
2224// 2. Before an 'abs' modifier: -abs(...)
2225// 3. Before an SP3 'abs' modifier: -|...|
2226//
2227// In all other cases "-" is handled as a part
2228// of an expression that follows the sign.
2229//
2230// Note: When "-" is followed by an integer literal,
2231// this is interpreted as integer negation rather
2232// than a floating-point NEG modifier applied to N.
2233// Beside being contr-intuitive, such use of floating-point
2234// NEG modifier would have resulted in different meaning
2235// of integer literals used with VOP1/2/C and VOP3,
2236// for example:
2237// v_exp_f32_e32 v5, -1 // VOP1: src0 = 0xFFFFFFFF
2238// v_exp_f32_e64 v5, -1 // VOP3: src0 = 0x80000001
2239// Negative fp literals with preceding "-" are
2240// handled likewise for unifomtity
2241//
2242bool
2243AMDGPUAsmParser::parseSP3NegModifier() {
2244
2245 AsmToken NextToken[2];
2246 peekTokens(NextToken);
2247
2248 if (isToken(AsmToken::Minus) &&
2249 (isRegister(NextToken[0], NextToken[1]) ||
2250 NextToken[0].is(AsmToken::Pipe) ||
2251 isId(NextToken[0], "abs"))) {
2252 lex();
2253 return true;
2254 }
2255
2256 return false;
2257}
2258
Sam Kolton9772eb32017-01-11 11:46:30 +00002259OperandMatchResultTy
Eugene Zelenko66203762017-01-21 00:53:49 +00002260AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands,
2261 bool AllowImm) {
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002262 bool Neg, SP3Neg;
2263 bool Abs, SP3Abs;
2264 SMLoc Loc;
Sam Kolton1bdcef72016-05-23 09:59:02 +00002265
Dmitry Preobrazhenskye2707f52019-04-22 14:35:47 +00002266 // Disable ambiguous constructs like '--1' etc. Should use neg(-1) instead.
2267 if (isToken(AsmToken::Minus) && peekToken().is(AsmToken::Minus)) {
2268 Error(getLoc(), "invalid syntax, expected 'neg' modifier");
2269 return MatchOperand_ParseFail;
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +00002270 }
2271
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002272 SP3Neg = parseSP3NegModifier();
Dmitry Preobrazhenskye2707f52019-04-22 14:35:47 +00002273
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002274 Loc = getLoc();
2275 Neg = trySkipId("neg");
2276 if (Neg && SP3Neg) {
2277 Error(Loc, "expected register or immediate");
2278 return MatchOperand_ParseFail;
Sam Kolton1bdcef72016-05-23 09:59:02 +00002279 }
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002280 if (Neg && !skipToken(AsmToken::LParen, "expected left paren after neg"))
2281 return MatchOperand_ParseFail;
Sam Kolton1bdcef72016-05-23 09:59:02 +00002282
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002283 Abs = trySkipId("abs");
2284 if (Abs && !skipToken(AsmToken::LParen, "expected left paren after abs"))
2285 return MatchOperand_ParseFail;
Sam Kolton1bdcef72016-05-23 09:59:02 +00002286
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002287 Loc = getLoc();
2288 SP3Abs = trySkipToken(AsmToken::Pipe);
2289 if (Abs && SP3Abs) {
2290 Error(Loc, "expected register or immediate");
2291 return MatchOperand_ParseFail;
Sam Kolton1bdcef72016-05-23 09:59:02 +00002292 }
2293
Sam Kolton9772eb32017-01-11 11:46:30 +00002294 OperandMatchResultTy Res;
2295 if (AllowImm) {
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002296 Res = parseRegOrImm(Operands, SP3Abs);
Sam Kolton9772eb32017-01-11 11:46:30 +00002297 } else {
2298 Res = parseReg(Operands);
2299 }
Sam Kolton1bdcef72016-05-23 09:59:02 +00002300 if (Res != MatchOperand_Success) {
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002301 return (SP3Neg || Neg || SP3Abs || Abs)? MatchOperand_ParseFail : Res;
Sam Kolton1bdcef72016-05-23 09:59:02 +00002302 }
2303
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002304 if (SP3Abs && !skipToken(AsmToken::Pipe, "expected vertical bar"))
2305 return MatchOperand_ParseFail;
2306 if (Abs && !skipToken(AsmToken::RParen, "expected closing parentheses"))
2307 return MatchOperand_ParseFail;
2308 if (Neg && !skipToken(AsmToken::RParen, "expected closing parentheses"))
2309 return MatchOperand_ParseFail;
2310
Matt Arsenaultb55f6202016-12-03 18:22:49 +00002311 AMDGPUOperand::Modifiers Mods;
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002312 Mods.Abs = Abs || SP3Abs;
2313 Mods.Neg = Neg || SP3Neg;
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +00002314
Sam Kolton945231a2016-06-10 09:57:59 +00002315 if (Mods.hasFPModifiers()) {
Sam Kolton1bdcef72016-05-23 09:59:02 +00002316 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +00002317 if (Op.isExpr()) {
2318 Error(Op.getStartLoc(), "expected an absolute expression");
2319 return MatchOperand_ParseFail;
2320 }
Sam Kolton945231a2016-06-10 09:57:59 +00002321 Op.setModifiers(Mods);
Sam Kolton1bdcef72016-05-23 09:59:02 +00002322 }
2323 return MatchOperand_Success;
2324}
2325
Alex Bradbury58eba092016-11-01 16:32:05 +00002326OperandMatchResultTy
Eugene Zelenko66203762017-01-21 00:53:49 +00002327AMDGPUAsmParser::parseRegOrImmWithIntInputMods(OperandVector &Operands,
2328 bool AllowImm) {
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002329 bool Sext = trySkipId("sext");
2330 if (Sext && !skipToken(AsmToken::LParen, "expected left paren after sext"))
2331 return MatchOperand_ParseFail;
Sam Kolton945231a2016-06-10 09:57:59 +00002332
Sam Kolton9772eb32017-01-11 11:46:30 +00002333 OperandMatchResultTy Res;
2334 if (AllowImm) {
2335 Res = parseRegOrImm(Operands);
2336 } else {
2337 Res = parseReg(Operands);
2338 }
Sam Kolton945231a2016-06-10 09:57:59 +00002339 if (Res != MatchOperand_Success) {
Dmitry Preobrazhenskye2707f52019-04-22 14:35:47 +00002340 return Sext? MatchOperand_ParseFail : Res;
Sam Kolton945231a2016-06-10 09:57:59 +00002341 }
2342
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002343 if (Sext && !skipToken(AsmToken::RParen, "expected closing parentheses"))
2344 return MatchOperand_ParseFail;
2345
Matt Arsenaultb55f6202016-12-03 18:22:49 +00002346 AMDGPUOperand::Modifiers Mods;
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002347 Mods.Sext = Sext;
Matt Arsenaultf3dd8632016-11-01 00:55:14 +00002348
Sam Kolton945231a2016-06-10 09:57:59 +00002349 if (Mods.hasIntModifiers()) {
Sam Koltona9cd6aa2016-07-05 14:01:11 +00002350 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +00002351 if (Op.isExpr()) {
2352 Error(Op.getStartLoc(), "expected an absolute expression");
2353 return MatchOperand_ParseFail;
2354 }
Sam Kolton945231a2016-06-10 09:57:59 +00002355 Op.setModifiers(Mods);
2356 }
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00002357
Sam Kolton945231a2016-06-10 09:57:59 +00002358 return MatchOperand_Success;
2359}
Sam Kolton1bdcef72016-05-23 09:59:02 +00002360
Sam Kolton9772eb32017-01-11 11:46:30 +00002361OperandMatchResultTy
2362AMDGPUAsmParser::parseRegWithFPInputMods(OperandVector &Operands) {
2363 return parseRegOrImmWithFPInputMods(Operands, false);
2364}
2365
2366OperandMatchResultTy
2367AMDGPUAsmParser::parseRegWithIntInputMods(OperandVector &Operands) {
2368 return parseRegOrImmWithIntInputMods(Operands, false);
2369}
2370
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00002371OperandMatchResultTy AMDGPUAsmParser::parseVReg32OrOff(OperandVector &Operands) {
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00002372 auto Loc = getLoc();
2373 if (trySkipId("off")) {
2374 Operands.push_back(AMDGPUOperand::CreateImm(this, 0, Loc,
2375 AMDGPUOperand::ImmTyOff, false));
2376 return MatchOperand_Success;
2377 }
2378
2379 if (!isRegister())
2380 return MatchOperand_NoMatch;
2381
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00002382 std::unique_ptr<AMDGPUOperand> Reg = parseRegister();
2383 if (Reg) {
2384 Operands.push_back(std::move(Reg));
2385 return MatchOperand_Success;
2386 }
2387
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00002388 return MatchOperand_ParseFail;
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00002389
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00002390}
2391
Tom Stellard45bb48e2015-06-13 03:28:10 +00002392unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Tom Stellard45bb48e2015-06-13 03:28:10 +00002393 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
2394
2395 if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) ||
Sam Kolton05ef1c92016-06-03 10:27:37 +00002396 (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3)) ||
2397 (isForcedDPP() && !(TSFlags & SIInstrFlags::DPP)) ||
2398 (isForcedSDWA() && !(TSFlags & SIInstrFlags::SDWA)) )
Tom Stellard45bb48e2015-06-13 03:28:10 +00002399 return Match_InvalidOperand;
2400
Tom Stellard88e0b252015-10-06 15:57:53 +00002401 if ((TSFlags & SIInstrFlags::VOP3) &&
2402 (TSFlags & SIInstrFlags::VOPAsmPrefer32Bit) &&
2403 getForcedEncodingSize() != 64)
2404 return Match_PreferE32;
2405
Sam Koltona568e3d2016-12-22 12:57:41 +00002406 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
2407 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
Sam Koltona3ec5c12016-10-07 14:46:06 +00002408 // v_mac_f32/16 allow only dst_sel == DWORD;
Konstantin Zhuravlyovf86e4b72016-11-13 07:01:11 +00002409 auto OpNum =
2410 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::dst_sel);
Sam Koltona3ec5c12016-10-07 14:46:06 +00002411 const auto &Op = Inst.getOperand(OpNum);
2412 if (!Op.isImm() || Op.getImm() != AMDGPU::SDWA::SdwaSel::DWORD) {
2413 return Match_InvalidOperand;
2414 }
2415 }
2416
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00002417 if (TSFlags & SIInstrFlags::FLAT) {
Matt Arsenaultfd023142017-06-12 15:55:58 +00002418 // FIXME: Produces error without correct column reported.
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00002419 auto Opcode = Inst.getOpcode();
2420 auto OpNum = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::offset);
2421
Matt Arsenaultfd023142017-06-12 15:55:58 +00002422 const auto &Op = Inst.getOperand(OpNum);
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00002423 if (!hasFlatOffsets() && Op.getImm() != 0)
Matt Arsenaultfd023142017-06-12 15:55:58 +00002424 return Match_InvalidOperand;
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00002425
2426 // GFX10: Address offset is 12-bit signed byte offset. Must be positive for
2427 // FLAT segment. For FLAT segment MSB is ignored and forced to zero.
2428 if (isGFX10()) {
2429 if (TSFlags & SIInstrFlags::IsNonFlatSeg) {
2430 if (!isInt<12>(Op.getImm()))
2431 return Match_InvalidOperand;
2432 } else {
2433 if (!isUInt<11>(Op.getImm()))
2434 return Match_InvalidOperand;
2435 }
2436 }
Matt Arsenaultfd023142017-06-12 15:55:58 +00002437 }
2438
Tom Stellard45bb48e2015-06-13 03:28:10 +00002439 return Match_Success;
2440}
2441
Matt Arsenault5f45e782017-01-09 18:44:11 +00002442// What asm variants we should check
2443ArrayRef<unsigned> AMDGPUAsmParser::getMatchedVariants() const {
2444 if (getForcedEncodingSize() == 32) {
2445 static const unsigned Variants[] = {AMDGPUAsmVariants::DEFAULT};
2446 return makeArrayRef(Variants);
2447 }
2448
2449 if (isForcedVOP3()) {
2450 static const unsigned Variants[] = {AMDGPUAsmVariants::VOP3};
2451 return makeArrayRef(Variants);
2452 }
2453
2454 if (isForcedSDWA()) {
Sam Koltonf7659d712017-05-23 10:08:55 +00002455 static const unsigned Variants[] = {AMDGPUAsmVariants::SDWA,
2456 AMDGPUAsmVariants::SDWA9};
Matt Arsenault5f45e782017-01-09 18:44:11 +00002457 return makeArrayRef(Variants);
2458 }
2459
2460 if (isForcedDPP()) {
2461 static const unsigned Variants[] = {AMDGPUAsmVariants::DPP};
2462 return makeArrayRef(Variants);
2463 }
2464
2465 static const unsigned Variants[] = {
2466 AMDGPUAsmVariants::DEFAULT, AMDGPUAsmVariants::VOP3,
Sam Koltonf7659d712017-05-23 10:08:55 +00002467 AMDGPUAsmVariants::SDWA, AMDGPUAsmVariants::SDWA9, AMDGPUAsmVariants::DPP
Matt Arsenault5f45e782017-01-09 18:44:11 +00002468 };
2469
2470 return makeArrayRef(Variants);
2471}
2472
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002473unsigned AMDGPUAsmParser::findImplicitSGPRReadInVOP(const MCInst &Inst) const {
2474 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2475 const unsigned Num = Desc.getNumImplicitUses();
2476 for (unsigned i = 0; i < Num; ++i) {
2477 unsigned Reg = Desc.ImplicitUses[i];
2478 switch (Reg) {
2479 case AMDGPU::FLAT_SCR:
2480 case AMDGPU::VCC:
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00002481 case AMDGPU::VCC_LO:
2482 case AMDGPU::VCC_HI:
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002483 case AMDGPU::M0:
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00002484 case AMDGPU::SGPR_NULL:
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002485 return Reg;
2486 default:
2487 break;
2488 }
2489 }
2490 return AMDGPU::NoRegister;
2491}
2492
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002493// NB: This code is correct only when used to check constant
2494// bus limitations because GFX7 support no f16 inline constants.
2495// Note that there are no cases when a GFX7 opcode violates
2496// constant bus limitations due to the use of an f16 constant.
2497bool AMDGPUAsmParser::isInlineConstant(const MCInst &Inst,
2498 unsigned OpIdx) const {
2499 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2500
2501 if (!AMDGPU::isSISrcOperand(Desc, OpIdx)) {
2502 return false;
2503 }
2504
2505 const MCOperand &MO = Inst.getOperand(OpIdx);
2506
2507 int64_t Val = MO.getImm();
2508 auto OpSize = AMDGPU::getOperandSize(Desc, OpIdx);
2509
2510 switch (OpSize) { // expected operand size
2511 case 8:
2512 return AMDGPU::isInlinableLiteral64(Val, hasInv2PiInlineImm());
2513 case 4:
2514 return AMDGPU::isInlinableLiteral32(Val, hasInv2PiInlineImm());
2515 case 2: {
2516 const unsigned OperandType = Desc.OpInfo[OpIdx].OperandType;
2517 if (OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2INT16 ||
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00002518 OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2FP16 ||
2519 OperandType == AMDGPU::OPERAND_REG_IMM_V2INT16 ||
2520 OperandType == AMDGPU::OPERAND_REG_IMM_V2FP16) {
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002521 return AMDGPU::isInlinableLiteralV216(Val, hasInv2PiInlineImm());
2522 } else {
2523 return AMDGPU::isInlinableLiteral16(Val, hasInv2PiInlineImm());
2524 }
2525 }
2526 default:
2527 llvm_unreachable("invalid operand size");
2528 }
2529}
2530
2531bool AMDGPUAsmParser::usesConstantBus(const MCInst &Inst, unsigned OpIdx) {
2532 const MCOperand &MO = Inst.getOperand(OpIdx);
2533 if (MO.isImm()) {
2534 return !isInlineConstant(Inst, OpIdx);
2535 }
Sam Koltonf7659d712017-05-23 10:08:55 +00002536 return !MO.isReg() ||
2537 isSGPR(mc2PseudoReg(MO.getReg()), getContext().getRegisterInfo());
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002538}
2539
Dmitry Preobrazhenskydc4ac822017-06-21 14:41:34 +00002540bool AMDGPUAsmParser::validateConstantBusLimitations(const MCInst &Inst) {
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002541 const unsigned Opcode = Inst.getOpcode();
2542 const MCInstrDesc &Desc = MII.get(Opcode);
2543 unsigned ConstantBusUseCount = 0;
Stanislav Mekhanoshinf2baae02019-05-02 03:47:23 +00002544 unsigned NumLiterals = 0;
2545 unsigned LiteralSize;
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002546
2547 if (Desc.TSFlags &
2548 (SIInstrFlags::VOPC |
2549 SIInstrFlags::VOP1 | SIInstrFlags::VOP2 |
Sam Koltonf7659d712017-05-23 10:08:55 +00002550 SIInstrFlags::VOP3 | SIInstrFlags::VOP3P |
2551 SIInstrFlags::SDWA)) {
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002552 // Check special imm operands (used by madmk, etc)
2553 if (AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm) != -1) {
2554 ++ConstantBusUseCount;
2555 }
2556
Stanislav Mekhanoshinf2baae02019-05-02 03:47:23 +00002557 SmallDenseSet<unsigned> SGPRsUsed;
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002558 unsigned SGPRUsed = findImplicitSGPRReadInVOP(Inst);
2559 if (SGPRUsed != AMDGPU::NoRegister) {
Stanislav Mekhanoshinf2baae02019-05-02 03:47:23 +00002560 SGPRsUsed.insert(SGPRUsed);
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002561 ++ConstantBusUseCount;
2562 }
2563
2564 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
2565 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
2566 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
2567
2568 const int OpIndices[] = { Src0Idx, Src1Idx, Src2Idx };
2569
2570 for (int OpIdx : OpIndices) {
2571 if (OpIdx == -1) break;
2572
2573 const MCOperand &MO = Inst.getOperand(OpIdx);
2574 if (usesConstantBus(Inst, OpIdx)) {
2575 if (MO.isReg()) {
2576 const unsigned Reg = mc2PseudoReg(MO.getReg());
2577 // Pairs of registers with a partial intersections like these
2578 // s0, s[0:1]
2579 // flat_scratch_lo, flat_scratch
2580 // flat_scratch_lo, flat_scratch_hi
2581 // are theoretically valid but they are disabled anyway.
2582 // Note that this code mimics SIInstrInfo::verifyInstruction
Stanislav Mekhanoshinf2baae02019-05-02 03:47:23 +00002583 if (!SGPRsUsed.count(Reg)) {
2584 SGPRsUsed.insert(Reg);
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002585 ++ConstantBusUseCount;
2586 }
2587 SGPRUsed = Reg;
2588 } else { // Expression or a literal
Stanislav Mekhanoshinf2baae02019-05-02 03:47:23 +00002589
2590 if (Desc.OpInfo[OpIdx].OperandType == MCOI::OPERAND_IMMEDIATE)
2591 continue; // special operand like VINTERP attr_chan
2592
2593 // An instruction may use only one literal.
2594 // This has been validated on the previous step.
2595 // See validateVOP3Literal.
2596 // This literal may be used as more than one operand.
2597 // If all these operands are of the same size,
2598 // this literal counts as one scalar value.
2599 // Otherwise it counts as 2 scalar values.
2600 // See "GFX10 Shader Programming", section 3.6.2.3.
2601
2602 unsigned Size = AMDGPU::getOperandSize(Desc, OpIdx);
2603 if (Size < 4) Size = 4;
2604
2605 if (NumLiterals == 0) {
2606 NumLiterals = 1;
2607 LiteralSize = Size;
2608 } else if (LiteralSize != Size) {
2609 NumLiterals = 2;
2610 }
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002611 }
2612 }
2613 }
2614 }
Stanislav Mekhanoshinf2baae02019-05-02 03:47:23 +00002615 ConstantBusUseCount += NumLiterals;
2616
2617 if (isGFX10())
2618 return ConstantBusUseCount <= 2;
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002619
2620 return ConstantBusUseCount <= 1;
2621}
2622
Dmitry Preobrazhenskydc4ac822017-06-21 14:41:34 +00002623bool AMDGPUAsmParser::validateEarlyClobberLimitations(const MCInst &Inst) {
Dmitry Preobrazhenskydc4ac822017-06-21 14:41:34 +00002624 const unsigned Opcode = Inst.getOpcode();
2625 const MCInstrDesc &Desc = MII.get(Opcode);
2626
2627 const int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
2628 if (DstIdx == -1 ||
2629 Desc.getOperandConstraint(DstIdx, MCOI::EARLY_CLOBBER) == -1) {
2630 return true;
2631 }
2632
2633 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
2634
2635 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
2636 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
2637 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
2638
2639 assert(DstIdx != -1);
2640 const MCOperand &Dst = Inst.getOperand(DstIdx);
2641 assert(Dst.isReg());
2642 const unsigned DstReg = mc2PseudoReg(Dst.getReg());
2643
2644 const int SrcIndices[] = { Src0Idx, Src1Idx, Src2Idx };
2645
2646 for (int SrcIdx : SrcIndices) {
2647 if (SrcIdx == -1) break;
2648 const MCOperand &Src = Inst.getOperand(SrcIdx);
2649 if (Src.isReg()) {
2650 const unsigned SrcReg = mc2PseudoReg(Src.getReg());
2651 if (isRegIntersect(DstReg, SrcReg, TRI)) {
2652 return false;
2653 }
2654 }
2655 }
2656
2657 return true;
2658}
2659
Dmitry Preobrazhenskyff64aa52017-08-16 13:51:56 +00002660bool AMDGPUAsmParser::validateIntClampSupported(const MCInst &Inst) {
2661
2662 const unsigned Opc = Inst.getOpcode();
2663 const MCInstrDesc &Desc = MII.get(Opc);
2664
2665 if ((Desc.TSFlags & SIInstrFlags::IntClamp) != 0 && !hasIntClamp()) {
2666 int ClampIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp);
2667 assert(ClampIdx != -1);
2668 return Inst.getOperand(ClampIdx).getImm() == 0;
2669 }
2670
2671 return true;
2672}
2673
Dmitry Preobrazhensky70682812018-01-26 16:42:51 +00002674bool AMDGPUAsmParser::validateMIMGDataSize(const MCInst &Inst) {
2675
2676 const unsigned Opc = Inst.getOpcode();
2677 const MCInstrDesc &Desc = MII.get(Opc);
2678
2679 if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0)
2680 return true;
2681
Dmitry Preobrazhensky70682812018-01-26 16:42:51 +00002682 int VDataIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
2683 int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask);
2684 int TFEIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::tfe);
2685
2686 assert(VDataIdx != -1);
2687 assert(DMaskIdx != -1);
2688 assert(TFEIdx != -1);
2689
2690 unsigned VDataSize = AMDGPU::getRegOperandSize(getMRI(), Desc, VDataIdx);
2691 unsigned TFESize = Inst.getOperand(TFEIdx).getImm()? 1 : 0;
2692 unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf;
2693 if (DMask == 0)
2694 DMask = 1;
2695
Nicolai Haehnlef2674312018-06-21 13:36:01 +00002696 unsigned DataSize =
2697 (Desc.TSFlags & SIInstrFlags::Gather4) ? 4 : countPopulation(DMask);
2698 if (hasPackedD16()) {
2699 int D16Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::d16);
2700 if (D16Idx >= 0 && Inst.getOperand(D16Idx).getImm())
2701 DataSize = (DataSize + 1) / 2;
Dmitry Preobrazhensky0a1ff462018-02-05 14:18:53 +00002702 }
2703
2704 return (VDataSize / 4) == DataSize + TFESize;
Dmitry Preobrazhensky70682812018-01-26 16:42:51 +00002705}
2706
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00002707bool AMDGPUAsmParser::validateMIMGAddrSize(const MCInst &Inst) {
2708 const unsigned Opc = Inst.getOpcode();
2709 const MCInstrDesc &Desc = MII.get(Opc);
2710
2711 if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0 || !isGFX10())
2712 return true;
2713
2714 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opc);
2715 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
2716 AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
2717 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
2718 int SrsrcIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::srsrc);
2719 int DimIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dim);
2720
2721 assert(VAddr0Idx != -1);
2722 assert(SrsrcIdx != -1);
2723 assert(DimIdx != -1);
2724 assert(SrsrcIdx > VAddr0Idx);
2725
2726 unsigned Dim = Inst.getOperand(DimIdx).getImm();
2727 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByEncoding(Dim);
2728 bool IsNSA = SrsrcIdx - VAddr0Idx > 1;
2729 unsigned VAddrSize =
2730 IsNSA ? SrsrcIdx - VAddr0Idx
2731 : AMDGPU::getRegOperandSize(getMRI(), Desc, VAddr0Idx) / 4;
2732
2733 unsigned AddrSize = BaseOpcode->NumExtraArgs +
2734 (BaseOpcode->Gradients ? DimInfo->NumGradients : 0) +
2735 (BaseOpcode->Coordinates ? DimInfo->NumCoords : 0) +
2736 (BaseOpcode->LodOrClampOrMip ? 1 : 0);
2737 if (!IsNSA) {
2738 if (AddrSize > 8)
2739 AddrSize = 16;
2740 else if (AddrSize > 4)
2741 AddrSize = 8;
2742 }
2743
2744 return VAddrSize == AddrSize;
2745}
2746
Dmitry Preobrazhensky70682812018-01-26 16:42:51 +00002747bool AMDGPUAsmParser::validateMIMGAtomicDMask(const MCInst &Inst) {
2748
2749 const unsigned Opc = Inst.getOpcode();
2750 const MCInstrDesc &Desc = MII.get(Opc);
2751
2752 if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0)
2753 return true;
2754 if (!Desc.mayLoad() || !Desc.mayStore())
2755 return true; // Not atomic
2756
2757 int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask);
2758 unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf;
2759
2760 // This is an incomplete check because image_atomic_cmpswap
2761 // may only use 0x3 and 0xf while other atomic operations
2762 // may use 0x1 and 0x3. However these limitations are
2763 // verified when we check that dmask matches dst size.
2764 return DMask == 0x1 || DMask == 0x3 || DMask == 0xf;
2765}
2766
Dmitry Preobrazhenskyda4a7c02018-03-12 15:03:34 +00002767bool AMDGPUAsmParser::validateMIMGGatherDMask(const MCInst &Inst) {
2768
2769 const unsigned Opc = Inst.getOpcode();
2770 const MCInstrDesc &Desc = MII.get(Opc);
2771
2772 if ((Desc.TSFlags & SIInstrFlags::Gather4) == 0)
2773 return true;
2774
2775 int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask);
2776 unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf;
2777
2778 // GATHER4 instructions use dmask in a different fashion compared to
2779 // other MIMG instructions. The only useful DMASK values are
2780 // 1=red, 2=green, 4=blue, 8=alpha. (e.g. 1 returns
2781 // (red,red,red,red) etc.) The ISA document doesn't mention
2782 // this.
2783 return DMask == 0x1 || DMask == 0x2 || DMask == 0x4 || DMask == 0x8;
2784}
2785
Dmitry Preobrazhenskye3271ae2018-02-05 12:45:43 +00002786bool AMDGPUAsmParser::validateMIMGD16(const MCInst &Inst) {
2787
2788 const unsigned Opc = Inst.getOpcode();
2789 const MCInstrDesc &Desc = MII.get(Opc);
2790
2791 if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0)
2792 return true;
Dmitry Preobrazhenskye3271ae2018-02-05 12:45:43 +00002793
Nicolai Haehnlef2674312018-06-21 13:36:01 +00002794 int D16Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::d16);
2795 if (D16Idx >= 0 && Inst.getOperand(D16Idx).getImm()) {
2796 if (isCI() || isSI())
2797 return false;
2798 }
2799
2800 return true;
Dmitry Preobrazhenskye3271ae2018-02-05 12:45:43 +00002801}
2802
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00002803bool AMDGPUAsmParser::validateMIMGDim(const MCInst &Inst) {
2804 const unsigned Opc = Inst.getOpcode();
2805 const MCInstrDesc &Desc = MII.get(Opc);
2806
2807 if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0)
2808 return true;
2809
2810 int DimIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dim);
2811 if (DimIdx < 0)
2812 return true;
2813
2814 long Imm = Inst.getOperand(DimIdx).getImm();
2815 if (Imm < 0 || Imm >= 8)
2816 return false;
2817
2818 return true;
2819}
2820
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002821static bool IsRevOpcode(const unsigned Opcode)
2822{
2823 switch (Opcode) {
2824 case AMDGPU::V_SUBREV_F32_e32:
2825 case AMDGPU::V_SUBREV_F32_e64:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002826 case AMDGPU::V_SUBREV_F32_e32_gfx10:
2827 case AMDGPU::V_SUBREV_F32_e32_gfx6_gfx7:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002828 case AMDGPU::V_SUBREV_F32_e32_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002829 case AMDGPU::V_SUBREV_F32_e64_gfx10:
2830 case AMDGPU::V_SUBREV_F32_e64_gfx6_gfx7:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002831 case AMDGPU::V_SUBREV_F32_e64_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002832
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002833 case AMDGPU::V_SUBREV_I32_e32:
2834 case AMDGPU::V_SUBREV_I32_e64:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002835 case AMDGPU::V_SUBREV_I32_e32_gfx6_gfx7:
2836 case AMDGPU::V_SUBREV_I32_e64_gfx6_gfx7:
2837
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002838 case AMDGPU::V_SUBBREV_U32_e32:
2839 case AMDGPU::V_SUBBREV_U32_e64:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002840 case AMDGPU::V_SUBBREV_U32_e32_gfx6_gfx7:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002841 case AMDGPU::V_SUBBREV_U32_e32_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002842 case AMDGPU::V_SUBBREV_U32_e64_gfx6_gfx7:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002843 case AMDGPU::V_SUBBREV_U32_e64_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002844
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002845 case AMDGPU::V_SUBREV_U32_e32:
2846 case AMDGPU::V_SUBREV_U32_e64:
2847 case AMDGPU::V_SUBREV_U32_e32_gfx9:
2848 case AMDGPU::V_SUBREV_U32_e32_vi:
2849 case AMDGPU::V_SUBREV_U32_e64_gfx9:
2850 case AMDGPU::V_SUBREV_U32_e64_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002851
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002852 case AMDGPU::V_SUBREV_F16_e32:
2853 case AMDGPU::V_SUBREV_F16_e64:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002854 case AMDGPU::V_SUBREV_F16_e32_gfx10:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002855 case AMDGPU::V_SUBREV_F16_e32_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002856 case AMDGPU::V_SUBREV_F16_e64_gfx10:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002857 case AMDGPU::V_SUBREV_F16_e64_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002858
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002859 case AMDGPU::V_SUBREV_U16_e32:
2860 case AMDGPU::V_SUBREV_U16_e64:
2861 case AMDGPU::V_SUBREV_U16_e32_vi:
2862 case AMDGPU::V_SUBREV_U16_e64_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002863
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002864 case AMDGPU::V_SUBREV_CO_U32_e32_gfx9:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002865 case AMDGPU::V_SUBREV_CO_U32_e64_gfx10:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002866 case AMDGPU::V_SUBREV_CO_U32_e64_gfx9:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002867
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002868 case AMDGPU::V_SUBBREV_CO_U32_e32_gfx9:
2869 case AMDGPU::V_SUBBREV_CO_U32_e64_gfx9:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002870
2871 case AMDGPU::V_SUBREV_NC_U32_e32_gfx10:
2872 case AMDGPU::V_SUBREV_NC_U32_e64_gfx10:
2873
2874 case AMDGPU::V_SUBREV_CO_CI_U32_e32_gfx10:
2875 case AMDGPU::V_SUBREV_CO_CI_U32_e64_gfx10:
2876
2877 case AMDGPU::V_LSHRREV_B32_e32:
2878 case AMDGPU::V_LSHRREV_B32_e64:
2879 case AMDGPU::V_LSHRREV_B32_e32_gfx6_gfx7:
2880 case AMDGPU::V_LSHRREV_B32_e64_gfx6_gfx7:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002881 case AMDGPU::V_LSHRREV_B32_e32_vi:
2882 case AMDGPU::V_LSHRREV_B32_e64_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002883 case AMDGPU::V_LSHRREV_B32_e32_gfx10:
2884 case AMDGPU::V_LSHRREV_B32_e64_gfx10:
2885
2886 case AMDGPU::V_ASHRREV_I32_e32:
2887 case AMDGPU::V_ASHRREV_I32_e64:
2888 case AMDGPU::V_ASHRREV_I32_e32_gfx10:
2889 case AMDGPU::V_ASHRREV_I32_e32_gfx6_gfx7:
2890 case AMDGPU::V_ASHRREV_I32_e32_vi:
2891 case AMDGPU::V_ASHRREV_I32_e64_gfx10:
2892 case AMDGPU::V_ASHRREV_I32_e64_gfx6_gfx7:
2893 case AMDGPU::V_ASHRREV_I32_e64_vi:
2894
2895 case AMDGPU::V_LSHLREV_B32_e32:
2896 case AMDGPU::V_LSHLREV_B32_e64:
2897 case AMDGPU::V_LSHLREV_B32_e32_gfx10:
2898 case AMDGPU::V_LSHLREV_B32_e32_gfx6_gfx7:
2899 case AMDGPU::V_LSHLREV_B32_e32_vi:
2900 case AMDGPU::V_LSHLREV_B32_e64_gfx10:
2901 case AMDGPU::V_LSHLREV_B32_e64_gfx6_gfx7:
2902 case AMDGPU::V_LSHLREV_B32_e64_vi:
2903
2904 case AMDGPU::V_LSHLREV_B16_e32:
2905 case AMDGPU::V_LSHLREV_B16_e64:
2906 case AMDGPU::V_LSHLREV_B16_e32_vi:
2907 case AMDGPU::V_LSHLREV_B16_e64_vi:
Stanislav Mekhanoshin61beff02019-04-26 17:56:03 +00002908 case AMDGPU::V_LSHLREV_B16_gfx10:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002909
2910 case AMDGPU::V_LSHRREV_B16_e32:
2911 case AMDGPU::V_LSHRREV_B16_e64:
2912 case AMDGPU::V_LSHRREV_B16_e32_vi:
2913 case AMDGPU::V_LSHRREV_B16_e64_vi:
Stanislav Mekhanoshin61beff02019-04-26 17:56:03 +00002914 case AMDGPU::V_LSHRREV_B16_gfx10:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002915
2916 case AMDGPU::V_ASHRREV_I16_e32:
2917 case AMDGPU::V_ASHRREV_I16_e64:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002918 case AMDGPU::V_ASHRREV_I16_e32_vi:
2919 case AMDGPU::V_ASHRREV_I16_e64_vi:
Stanislav Mekhanoshin61beff02019-04-26 17:56:03 +00002920 case AMDGPU::V_ASHRREV_I16_gfx10:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002921
2922 case AMDGPU::V_LSHLREV_B64:
Stanislav Mekhanoshin61beff02019-04-26 17:56:03 +00002923 case AMDGPU::V_LSHLREV_B64_gfx10:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002924 case AMDGPU::V_LSHLREV_B64_vi:
2925
2926 case AMDGPU::V_LSHRREV_B64:
Stanislav Mekhanoshin61beff02019-04-26 17:56:03 +00002927 case AMDGPU::V_LSHRREV_B64_gfx10:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002928 case AMDGPU::V_LSHRREV_B64_vi:
2929
2930 case AMDGPU::V_ASHRREV_I64:
Stanislav Mekhanoshin61beff02019-04-26 17:56:03 +00002931 case AMDGPU::V_ASHRREV_I64_gfx10:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002932 case AMDGPU::V_ASHRREV_I64_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002933
2934 case AMDGPU::V_PK_LSHLREV_B16:
Stanislav Mekhanoshin61beff02019-04-26 17:56:03 +00002935 case AMDGPU::V_PK_LSHLREV_B16_gfx10:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002936 case AMDGPU::V_PK_LSHLREV_B16_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002937
2938 case AMDGPU::V_PK_LSHRREV_B16:
Stanislav Mekhanoshin61beff02019-04-26 17:56:03 +00002939 case AMDGPU::V_PK_LSHRREV_B16_gfx10:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002940 case AMDGPU::V_PK_LSHRREV_B16_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00002941 case AMDGPU::V_PK_ASHRREV_I16:
Stanislav Mekhanoshin61beff02019-04-26 17:56:03 +00002942 case AMDGPU::V_PK_ASHRREV_I16_gfx10:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002943 case AMDGPU::V_PK_ASHRREV_I16_vi:
2944 return true;
2945 default:
2946 return false;
2947 }
2948}
2949
Dmitry Preobrazhensky942c2732019-02-08 14:57:37 +00002950bool AMDGPUAsmParser::validateLdsDirect(const MCInst &Inst) {
2951
2952 using namespace SIInstrFlags;
2953 const unsigned Opcode = Inst.getOpcode();
2954 const MCInstrDesc &Desc = MII.get(Opcode);
2955
2956 // lds_direct register is defined so that it can be used
2957 // with 9-bit operands only. Ignore encodings which do not accept these.
2958 if ((Desc.TSFlags & (VOP1 | VOP2 | VOP3 | VOPC | VOP3P | SIInstrFlags::SDWA)) == 0)
2959 return true;
2960
2961 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
2962 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
2963 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
2964
2965 const int SrcIndices[] = { Src1Idx, Src2Idx };
2966
2967 // lds_direct cannot be specified as either src1 or src2.
2968 for (int SrcIdx : SrcIndices) {
2969 if (SrcIdx == -1) break;
2970 const MCOperand &Src = Inst.getOperand(SrcIdx);
2971 if (Src.isReg() && Src.getReg() == LDS_DIRECT) {
2972 return false;
2973 }
2974 }
2975
2976 if (Src0Idx == -1)
2977 return true;
2978
2979 const MCOperand &Src = Inst.getOperand(Src0Idx);
2980 if (!Src.isReg() || Src.getReg() != LDS_DIRECT)
2981 return true;
2982
2983 // lds_direct is specified as src0. Check additional limitations.
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00002984 return (Desc.TSFlags & SIInstrFlags::SDWA) == 0 && !IsRevOpcode(Opcode);
Dmitry Preobrazhensky942c2732019-02-08 14:57:37 +00002985}
2986
Dmitry Preobrazhensky61105ba2019-01-18 13:57:43 +00002987bool AMDGPUAsmParser::validateSOPLiteral(const MCInst &Inst) const {
2988 unsigned Opcode = Inst.getOpcode();
2989 const MCInstrDesc &Desc = MII.get(Opcode);
2990 if (!(Desc.TSFlags & (SIInstrFlags::SOP2 | SIInstrFlags::SOPC)))
2991 return true;
2992
2993 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
2994 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
2995
2996 const int OpIndices[] = { Src0Idx, Src1Idx };
2997
2998 unsigned NumLiterals = 0;
2999 uint32_t LiteralValue;
3000
3001 for (int OpIdx : OpIndices) {
3002 if (OpIdx == -1) break;
3003
3004 const MCOperand &MO = Inst.getOperand(OpIdx);
3005 if (MO.isImm() &&
3006 // Exclude special imm operands (like that used by s_set_gpr_idx_on)
3007 AMDGPU::isSISrcOperand(Desc, OpIdx) &&
3008 !isInlineConstant(Inst, OpIdx)) {
3009 uint32_t Value = static_cast<uint32_t>(MO.getImm());
3010 if (NumLiterals == 0 || LiteralValue != Value) {
3011 LiteralValue = Value;
3012 ++NumLiterals;
3013 }
3014 }
3015 }
3016
3017 return NumLiterals <= 1;
3018}
3019
Stanislav Mekhanoshin5f581c92019-06-12 17:52:51 +00003020bool AMDGPUAsmParser::validateOpSel(const MCInst &Inst) {
3021 const unsigned Opc = Inst.getOpcode();
3022 if (Opc == AMDGPU::V_PERMLANE16_B32_gfx10 ||
3023 Opc == AMDGPU::V_PERMLANEX16_B32_gfx10) {
3024 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
3025 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
3026
3027 if (OpSel & ~3)
3028 return false;
3029 }
3030 return true;
3031}
3032
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00003033// VOP3 literal is only allowed in GFX10+ and only one can be used
3034bool AMDGPUAsmParser::validateVOP3Literal(const MCInst &Inst) const {
3035 unsigned Opcode = Inst.getOpcode();
3036 const MCInstrDesc &Desc = MII.get(Opcode);
3037 if (!(Desc.TSFlags & (SIInstrFlags::VOP3 | SIInstrFlags::VOP3P)))
3038 return true;
3039
3040 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
3041 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
3042 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
3043
3044 const int OpIndices[] = { Src0Idx, Src1Idx, Src2Idx };
3045
3046 unsigned NumLiterals = 0;
3047 uint32_t LiteralValue;
3048
3049 for (int OpIdx : OpIndices) {
3050 if (OpIdx == -1) break;
3051
3052 const MCOperand &MO = Inst.getOperand(OpIdx);
3053 if (!MO.isImm() || !AMDGPU::isSISrcOperand(Desc, OpIdx))
3054 continue;
3055
3056 if (!isInlineConstant(Inst, OpIdx)) {
3057 uint32_t Value = static_cast<uint32_t>(MO.getImm());
3058 if (NumLiterals == 0 || LiteralValue != Value) {
3059 LiteralValue = Value;
3060 ++NumLiterals;
3061 }
3062 }
3063 }
3064
3065 return !NumLiterals ||
3066 (NumLiterals == 1 && getFeatureBits()[AMDGPU::FeatureVOP3Literal]);
3067}
3068
Dmitry Preobrazhenskydc4ac822017-06-21 14:41:34 +00003069bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst,
3070 const SMLoc &IDLoc) {
Dmitry Preobrazhensky942c2732019-02-08 14:57:37 +00003071 if (!validateLdsDirect(Inst)) {
3072 Error(IDLoc,
3073 "invalid use of lds_direct");
3074 return false;
3075 }
Dmitry Preobrazhensky61105ba2019-01-18 13:57:43 +00003076 if (!validateSOPLiteral(Inst)) {
3077 Error(IDLoc,
3078 "only one literal operand is allowed");
3079 return false;
3080 }
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00003081 if (!validateVOP3Literal(Inst)) {
3082 Error(IDLoc,
3083 "invalid literal operand");
3084 return false;
3085 }
Dmitry Preobrazhenskydc4ac822017-06-21 14:41:34 +00003086 if (!validateConstantBusLimitations(Inst)) {
3087 Error(IDLoc,
3088 "invalid operand (violates constant bus restrictions)");
3089 return false;
3090 }
3091 if (!validateEarlyClobberLimitations(Inst)) {
3092 Error(IDLoc,
3093 "destination must be different than all sources");
3094 return false;
3095 }
Dmitry Preobrazhenskyff64aa52017-08-16 13:51:56 +00003096 if (!validateIntClampSupported(Inst)) {
3097 Error(IDLoc,
3098 "integer clamping is not supported on this GPU");
3099 return false;
3100 }
Stanislav Mekhanoshin5f581c92019-06-12 17:52:51 +00003101 if (!validateOpSel(Inst)) {
3102 Error(IDLoc,
3103 "invalid op_sel operand");
3104 return false;
3105 }
Dmitry Preobrazhenskye3271ae2018-02-05 12:45:43 +00003106 // For MUBUF/MTBUF d16 is a part of opcode, so there is nothing to validate.
3107 if (!validateMIMGD16(Inst)) {
3108 Error(IDLoc,
3109 "d16 modifier is not supported on this GPU");
3110 return false;
3111 }
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00003112 if (!validateMIMGDim(Inst)) {
3113 Error(IDLoc, "dim modifier is required on this GPU");
3114 return false;
3115 }
Dmitry Preobrazhensky0a1ff462018-02-05 14:18:53 +00003116 if (!validateMIMGDataSize(Inst)) {
3117 Error(IDLoc,
3118 "image data size does not match dmask and tfe");
3119 return false;
3120 }
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00003121 if (!validateMIMGAddrSize(Inst)) {
3122 Error(IDLoc,
3123 "image address size does not match dim and a16");
3124 return false;
3125 }
Dmitry Preobrazhensky0a1ff462018-02-05 14:18:53 +00003126 if (!validateMIMGAtomicDMask(Inst)) {
3127 Error(IDLoc,
3128 "invalid atomic image dmask");
3129 return false;
3130 }
Dmitry Preobrazhenskyda4a7c02018-03-12 15:03:34 +00003131 if (!validateMIMGGatherDMask(Inst)) {
3132 Error(IDLoc,
3133 "invalid image_gather dmask: only one bit must be set");
3134 return false;
3135 }
Dmitry Preobrazhenskydc4ac822017-06-21 14:41:34 +00003136
3137 return true;
3138}
3139
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00003140static std::string AMDGPUMnemonicSpellCheck(StringRef S,
3141 const FeatureBitset &FBS,
Matt Arsenaultf7f59b52017-12-20 18:52:57 +00003142 unsigned VariantID = 0);
3143
Tom Stellard45bb48e2015-06-13 03:28:10 +00003144bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3145 OperandVector &Operands,
3146 MCStreamer &Out,
3147 uint64_t &ErrorInfo,
3148 bool MatchingInlineAsm) {
3149 MCInst Inst;
Sam Koltond63d8a72016-09-09 09:37:51 +00003150 unsigned Result = Match_Success;
Matt Arsenault5f45e782017-01-09 18:44:11 +00003151 for (auto Variant : getMatchedVariants()) {
Sam Koltond63d8a72016-09-09 09:37:51 +00003152 uint64_t EI;
3153 auto R = MatchInstructionImpl(Operands, Inst, EI, MatchingInlineAsm,
3154 Variant);
3155 // We order match statuses from least to most specific. We use most specific
3156 // status as resulting
3157 // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature < Match_PreferE32
3158 if ((R == Match_Success) ||
3159 (R == Match_PreferE32) ||
3160 (R == Match_MissingFeature && Result != Match_PreferE32) ||
3161 (R == Match_InvalidOperand && Result != Match_MissingFeature
3162 && Result != Match_PreferE32) ||
3163 (R == Match_MnemonicFail && Result != Match_InvalidOperand
3164 && Result != Match_MissingFeature
3165 && Result != Match_PreferE32)) {
3166 Result = R;
3167 ErrorInfo = EI;
Tom Stellard45bb48e2015-06-13 03:28:10 +00003168 }
Sam Koltond63d8a72016-09-09 09:37:51 +00003169 if (R == Match_Success)
3170 break;
3171 }
3172
3173 switch (Result) {
3174 default: break;
3175 case Match_Success:
Dmitry Preobrazhenskydc4ac822017-06-21 14:41:34 +00003176 if (!validateInstruction(Inst, IDLoc)) {
3177 return true;
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00003178 }
Sam Koltond63d8a72016-09-09 09:37:51 +00003179 Inst.setLoc(IDLoc);
3180 Out.EmitInstruction(Inst, getSTI());
3181 return false;
3182
3183 case Match_MissingFeature:
3184 return Error(IDLoc, "instruction not supported on this GPU");
3185
Matt Arsenaultf7f59b52017-12-20 18:52:57 +00003186 case Match_MnemonicFail: {
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00003187 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
Matt Arsenaultf7f59b52017-12-20 18:52:57 +00003188 std::string Suggestion = AMDGPUMnemonicSpellCheck(
3189 ((AMDGPUOperand &)*Operands[0]).getToken(), FBS);
3190 return Error(IDLoc, "invalid instruction" + Suggestion,
3191 ((AMDGPUOperand &)*Operands[0]).getLocRange());
3192 }
Sam Koltond63d8a72016-09-09 09:37:51 +00003193
3194 case Match_InvalidOperand: {
3195 SMLoc ErrorLoc = IDLoc;
3196 if (ErrorInfo != ~0ULL) {
3197 if (ErrorInfo >= Operands.size()) {
3198 return Error(IDLoc, "too few operands for instruction");
3199 }
3200 ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc();
3201 if (ErrorLoc == SMLoc())
3202 ErrorLoc = IDLoc;
3203 }
3204 return Error(ErrorLoc, "invalid operand for instruction");
3205 }
3206
3207 case Match_PreferE32:
3208 return Error(IDLoc, "internal error: instruction without _e64 suffix "
3209 "should be encoded as e32");
Tom Stellard45bb48e2015-06-13 03:28:10 +00003210 }
3211 llvm_unreachable("Implement any new match types added!");
3212}
3213
Artem Tamazov25478d82016-12-29 15:41:52 +00003214bool AMDGPUAsmParser::ParseAsAbsoluteExpression(uint32_t &Ret) {
3215 int64_t Tmp = -1;
3216 if (getLexer().isNot(AsmToken::Integer) && getLexer().isNot(AsmToken::Identifier)) {
3217 return true;
3218 }
3219 if (getParser().parseAbsoluteExpression(Tmp)) {
3220 return true;
3221 }
3222 Ret = static_cast<uint32_t>(Tmp);
3223 return false;
3224}
3225
Tom Stellard347ac792015-06-26 21:15:07 +00003226bool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major,
3227 uint32_t &Minor) {
Artem Tamazov25478d82016-12-29 15:41:52 +00003228 if (ParseAsAbsoluteExpression(Major))
Tom Stellard347ac792015-06-26 21:15:07 +00003229 return TokError("invalid major version");
3230
Tom Stellard347ac792015-06-26 21:15:07 +00003231 if (getLexer().isNot(AsmToken::Comma))
3232 return TokError("minor version number required, comma expected");
3233 Lex();
3234
Artem Tamazov25478d82016-12-29 15:41:52 +00003235 if (ParseAsAbsoluteExpression(Minor))
Tom Stellard347ac792015-06-26 21:15:07 +00003236 return TokError("invalid minor version");
3237
Tom Stellard347ac792015-06-26 21:15:07 +00003238 return false;
3239}
3240
Scott Linder1e8c2c72018-06-21 19:38:56 +00003241bool AMDGPUAsmParser::ParseDirectiveAMDGCNTarget() {
3242 if (getSTI().getTargetTriple().getArch() != Triple::amdgcn)
3243 return TokError("directive only supported for amdgcn architecture");
3244
3245 std::string Target;
3246
3247 SMLoc TargetStart = getTok().getLoc();
3248 if (getParser().parseEscapedString(Target))
3249 return true;
3250 SMRange TargetRange = SMRange(TargetStart, getTok().getLoc());
3251
3252 std::string ExpectedTarget;
3253 raw_string_ostream ExpectedTargetOS(ExpectedTarget);
3254 IsaInfo::streamIsaVersion(&getSTI(), ExpectedTargetOS);
3255
3256 if (Target != ExpectedTargetOS.str())
3257 return getParser().Error(TargetRange.Start, "target must match options",
3258 TargetRange);
3259
3260 getTargetStreamer().EmitDirectiveAMDGCNTarget(Target);
3261 return false;
3262}
3263
3264bool AMDGPUAsmParser::OutOfRangeError(SMRange Range) {
3265 return getParser().Error(Range.Start, "value out of range", Range);
3266}
3267
3268bool AMDGPUAsmParser::calculateGPRBlocks(
3269 const FeatureBitset &Features, bool VCCUsed, bool FlatScrUsed,
3270 bool XNACKUsed, unsigned NextFreeVGPR, SMRange VGPRRange,
3271 unsigned NextFreeSGPR, SMRange SGPRRange, unsigned &VGPRBlocks,
3272 unsigned &SGPRBlocks) {
3273 // TODO(scott.linder): These calculations are duplicated from
3274 // AMDGPUAsmPrinter::getSIProgramInfo and could be unified.
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00003275 IsaVersion Version = getIsaVersion(getSTI().getCPU());
Scott Linder1e8c2c72018-06-21 19:38:56 +00003276
3277 unsigned NumVGPRs = NextFreeVGPR;
3278 unsigned NumSGPRs = NextFreeSGPR;
Scott Linder1e8c2c72018-06-21 19:38:56 +00003279
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00003280 if (Version.Major >= 10)
3281 NumSGPRs = 0;
3282 else {
3283 unsigned MaxAddressableNumSGPRs =
3284 IsaInfo::getAddressableNumSGPRs(&getSTI());
Scott Linder1e8c2c72018-06-21 19:38:56 +00003285
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00003286 if (Version.Major >= 8 && !Features.test(FeatureSGPRInitBug) &&
3287 NumSGPRs > MaxAddressableNumSGPRs)
3288 return OutOfRangeError(SGPRRange);
Scott Linder1e8c2c72018-06-21 19:38:56 +00003289
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00003290 NumSGPRs +=
3291 IsaInfo::getNumExtraSGPRs(&getSTI(), VCCUsed, FlatScrUsed, XNACKUsed);
Scott Linder1e8c2c72018-06-21 19:38:56 +00003292
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00003293 if ((Version.Major <= 7 || Features.test(FeatureSGPRInitBug)) &&
3294 NumSGPRs > MaxAddressableNumSGPRs)
3295 return OutOfRangeError(SGPRRange);
3296
3297 if (Features.test(FeatureSGPRInitBug))
3298 NumSGPRs = IsaInfo::FIXED_NUM_SGPRS_FOR_INIT_BUG;
3299 }
Scott Linder1e8c2c72018-06-21 19:38:56 +00003300
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00003301 VGPRBlocks = IsaInfo::getNumVGPRBlocks(&getSTI(), NumVGPRs);
3302 SGPRBlocks = IsaInfo::getNumSGPRBlocks(&getSTI(), NumSGPRs);
Scott Linder1e8c2c72018-06-21 19:38:56 +00003303
3304 return false;
3305}
3306
3307bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() {
3308 if (getSTI().getTargetTriple().getArch() != Triple::amdgcn)
3309 return TokError("directive only supported for amdgcn architecture");
3310
3311 if (getSTI().getTargetTriple().getOS() != Triple::AMDHSA)
3312 return TokError("directive only supported for amdhsa OS");
3313
3314 StringRef KernelName;
3315 if (getParser().parseIdentifier(KernelName))
3316 return true;
3317
Stanislav Mekhanoshincee607e2019-04-24 17:03:15 +00003318 kernel_descriptor_t KD = getDefaultAmdhsaKernelDescriptor(&getSTI());
Scott Linder1e8c2c72018-06-21 19:38:56 +00003319
3320 StringSet<> Seen;
3321
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00003322 IsaVersion IVersion = getIsaVersion(getSTI().getCPU());
Scott Linder1e8c2c72018-06-21 19:38:56 +00003323
3324 SMRange VGPRRange;
3325 uint64_t NextFreeVGPR = 0;
3326 SMRange SGPRRange;
3327 uint64_t NextFreeSGPR = 0;
3328 unsigned UserSGPRCount = 0;
3329 bool ReserveVCC = true;
3330 bool ReserveFlatScr = true;
3331 bool ReserveXNACK = hasXNACK();
3332
3333 while (true) {
3334 while (getLexer().is(AsmToken::EndOfStatement))
3335 Lex();
3336
3337 if (getLexer().isNot(AsmToken::Identifier))
3338 return TokError("expected .amdhsa_ directive or .end_amdhsa_kernel");
3339
3340 StringRef ID = getTok().getIdentifier();
3341 SMRange IDRange = getTok().getLocRange();
3342 Lex();
3343
3344 if (ID == ".end_amdhsa_kernel")
3345 break;
3346
3347 if (Seen.find(ID) != Seen.end())
3348 return TokError(".amdhsa_ directives cannot be repeated");
3349 Seen.insert(ID);
3350
3351 SMLoc ValStart = getTok().getLoc();
3352 int64_t IVal;
3353 if (getParser().parseAbsoluteExpression(IVal))
3354 return true;
3355 SMLoc ValEnd = getTok().getLoc();
3356 SMRange ValRange = SMRange(ValStart, ValEnd);
3357
3358 if (IVal < 0)
3359 return OutOfRangeError(ValRange);
3360
3361 uint64_t Val = IVal;
3362
3363#define PARSE_BITS_ENTRY(FIELD, ENTRY, VALUE, RANGE) \
3364 if (!isUInt<ENTRY##_WIDTH>(VALUE)) \
3365 return OutOfRangeError(RANGE); \
3366 AMDHSA_BITS_SET(FIELD, ENTRY, VALUE);
3367
3368 if (ID == ".amdhsa_group_segment_fixed_size") {
3369 if (!isUInt<sizeof(KD.group_segment_fixed_size) * CHAR_BIT>(Val))
3370 return OutOfRangeError(ValRange);
3371 KD.group_segment_fixed_size = Val;
3372 } else if (ID == ".amdhsa_private_segment_fixed_size") {
3373 if (!isUInt<sizeof(KD.private_segment_fixed_size) * CHAR_BIT>(Val))
3374 return OutOfRangeError(ValRange);
3375 KD.private_segment_fixed_size = Val;
3376 } else if (ID == ".amdhsa_user_sgpr_private_segment_buffer") {
3377 PARSE_BITS_ENTRY(KD.kernel_code_properties,
3378 KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER,
3379 Val, ValRange);
Konstantin Zhuravlyov88268e32019-03-20 19:44:47 +00003380 UserSGPRCount += 4;
Scott Linder1e8c2c72018-06-21 19:38:56 +00003381 } else if (ID == ".amdhsa_user_sgpr_dispatch_ptr") {
3382 PARSE_BITS_ENTRY(KD.kernel_code_properties,
3383 KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR, Val,
3384 ValRange);
Konstantin Zhuravlyov88268e32019-03-20 19:44:47 +00003385 UserSGPRCount += 2;
Scott Linder1e8c2c72018-06-21 19:38:56 +00003386 } else if (ID == ".amdhsa_user_sgpr_queue_ptr") {
3387 PARSE_BITS_ENTRY(KD.kernel_code_properties,
3388 KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR, Val,
3389 ValRange);
Konstantin Zhuravlyov88268e32019-03-20 19:44:47 +00003390 UserSGPRCount += 2;
Scott Linder1e8c2c72018-06-21 19:38:56 +00003391 } else if (ID == ".amdhsa_user_sgpr_kernarg_segment_ptr") {
3392 PARSE_BITS_ENTRY(KD.kernel_code_properties,
3393 KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR,
3394 Val, ValRange);
Konstantin Zhuravlyov88268e32019-03-20 19:44:47 +00003395 UserSGPRCount += 2;
Scott Linder1e8c2c72018-06-21 19:38:56 +00003396 } else if (ID == ".amdhsa_user_sgpr_dispatch_id") {
3397 PARSE_BITS_ENTRY(KD.kernel_code_properties,
3398 KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID, Val,
3399 ValRange);
Konstantin Zhuravlyov88268e32019-03-20 19:44:47 +00003400 UserSGPRCount += 2;
Scott Linder1e8c2c72018-06-21 19:38:56 +00003401 } else if (ID == ".amdhsa_user_sgpr_flat_scratch_init") {
3402 PARSE_BITS_ENTRY(KD.kernel_code_properties,
3403 KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT, Val,
3404 ValRange);
Konstantin Zhuravlyov88268e32019-03-20 19:44:47 +00003405 UserSGPRCount += 2;
Scott Linder1e8c2c72018-06-21 19:38:56 +00003406 } else if (ID == ".amdhsa_user_sgpr_private_segment_size") {
3407 PARSE_BITS_ENTRY(KD.kernel_code_properties,
3408 KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE,
3409 Val, ValRange);
Konstantin Zhuravlyov88268e32019-03-20 19:44:47 +00003410 UserSGPRCount += 1;
Scott Linder1e8c2c72018-06-21 19:38:56 +00003411 } else if (ID == ".amdhsa_system_sgpr_private_segment_wavefront_offset") {
3412 PARSE_BITS_ENTRY(
3413 KD.compute_pgm_rsrc2,
3414 COMPUTE_PGM_RSRC2_ENABLE_SGPR_PRIVATE_SEGMENT_WAVEFRONT_OFFSET, Val,
3415 ValRange);
3416 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_x") {
3417 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3418 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X, Val,
3419 ValRange);
3420 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_y") {
3421 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3422 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y, Val,
3423 ValRange);
3424 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_z") {
3425 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3426 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z, Val,
3427 ValRange);
3428 } else if (ID == ".amdhsa_system_sgpr_workgroup_info") {
3429 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3430 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO, Val,
3431 ValRange);
3432 } else if (ID == ".amdhsa_system_vgpr_workitem_id") {
3433 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3434 COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID, Val,
3435 ValRange);
3436 } else if (ID == ".amdhsa_next_free_vgpr") {
3437 VGPRRange = ValRange;
3438 NextFreeVGPR = Val;
3439 } else if (ID == ".amdhsa_next_free_sgpr") {
3440 SGPRRange = ValRange;
3441 NextFreeSGPR = Val;
3442 } else if (ID == ".amdhsa_reserve_vcc") {
3443 if (!isUInt<1>(Val))
3444 return OutOfRangeError(ValRange);
3445 ReserveVCC = Val;
3446 } else if (ID == ".amdhsa_reserve_flat_scratch") {
3447 if (IVersion.Major < 7)
3448 return getParser().Error(IDRange.Start, "directive requires gfx7+",
3449 IDRange);
3450 if (!isUInt<1>(Val))
3451 return OutOfRangeError(ValRange);
3452 ReserveFlatScr = Val;
3453 } else if (ID == ".amdhsa_reserve_xnack_mask") {
3454 if (IVersion.Major < 8)
3455 return getParser().Error(IDRange.Start, "directive requires gfx8+",
3456 IDRange);
3457 if (!isUInt<1>(Val))
3458 return OutOfRangeError(ValRange);
3459 ReserveXNACK = Val;
3460 } else if (ID == ".amdhsa_float_round_mode_32") {
3461 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1,
3462 COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32, Val, ValRange);
3463 } else if (ID == ".amdhsa_float_round_mode_16_64") {
3464 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1,
3465 COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64, Val, ValRange);
3466 } else if (ID == ".amdhsa_float_denorm_mode_32") {
3467 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1,
3468 COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32, Val, ValRange);
3469 } else if (ID == ".amdhsa_float_denorm_mode_16_64") {
3470 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1,
3471 COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64, Val,
3472 ValRange);
3473 } else if (ID == ".amdhsa_dx10_clamp") {
3474 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1,
3475 COMPUTE_PGM_RSRC1_ENABLE_DX10_CLAMP, Val, ValRange);
3476 } else if (ID == ".amdhsa_ieee_mode") {
3477 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_ENABLE_IEEE_MODE,
3478 Val, ValRange);
3479 } else if (ID == ".amdhsa_fp16_overflow") {
3480 if (IVersion.Major < 9)
3481 return getParser().Error(IDRange.Start, "directive requires gfx9+",
3482 IDRange);
3483 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_FP16_OVFL, Val,
3484 ValRange);
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00003485 } else if (ID == ".amdhsa_workgroup_processor_mode") {
3486 if (IVersion.Major < 10)
3487 return getParser().Error(IDRange.Start, "directive requires gfx10+",
3488 IDRange);
3489 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_WGP_MODE, Val,
3490 ValRange);
3491 } else if (ID == ".amdhsa_memory_ordered") {
3492 if (IVersion.Major < 10)
3493 return getParser().Error(IDRange.Start, "directive requires gfx10+",
3494 IDRange);
3495 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_MEM_ORDERED, Val,
3496 ValRange);
3497 } else if (ID == ".amdhsa_forward_progress") {
3498 if (IVersion.Major < 10)
3499 return getParser().Error(IDRange.Start, "directive requires gfx10+",
3500 IDRange);
3501 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_FWD_PROGRESS, Val,
3502 ValRange);
Scott Linder1e8c2c72018-06-21 19:38:56 +00003503 } else if (ID == ".amdhsa_exception_fp_ieee_invalid_op") {
3504 PARSE_BITS_ENTRY(
3505 KD.compute_pgm_rsrc2,
3506 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION, Val,
3507 ValRange);
3508 } else if (ID == ".amdhsa_exception_fp_denorm_src") {
3509 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3510 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE,
3511 Val, ValRange);
3512 } else if (ID == ".amdhsa_exception_fp_ieee_div_zero") {
3513 PARSE_BITS_ENTRY(
3514 KD.compute_pgm_rsrc2,
3515 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO, Val,
3516 ValRange);
3517 } else if (ID == ".amdhsa_exception_fp_ieee_overflow") {
3518 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3519 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW,
3520 Val, ValRange);
3521 } else if (ID == ".amdhsa_exception_fp_ieee_underflow") {
3522 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3523 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW,
3524 Val, ValRange);
3525 } else if (ID == ".amdhsa_exception_fp_ieee_inexact") {
3526 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3527 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT,
3528 Val, ValRange);
3529 } else if (ID == ".amdhsa_exception_int_div_zero") {
3530 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3531 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO,
3532 Val, ValRange);
3533 } else {
3534 return getParser().Error(IDRange.Start,
3535 "unknown .amdhsa_kernel directive", IDRange);
3536 }
3537
3538#undef PARSE_BITS_ENTRY
3539 }
3540
3541 if (Seen.find(".amdhsa_next_free_vgpr") == Seen.end())
3542 return TokError(".amdhsa_next_free_vgpr directive is required");
3543
3544 if (Seen.find(".amdhsa_next_free_sgpr") == Seen.end())
3545 return TokError(".amdhsa_next_free_sgpr directive is required");
3546
3547 unsigned VGPRBlocks;
3548 unsigned SGPRBlocks;
3549 if (calculateGPRBlocks(getFeatureBits(), ReserveVCC, ReserveFlatScr,
3550 ReserveXNACK, NextFreeVGPR, VGPRRange, NextFreeSGPR,
3551 SGPRRange, VGPRBlocks, SGPRBlocks))
3552 return true;
3553
3554 if (!isUInt<COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT_WIDTH>(
3555 VGPRBlocks))
3556 return OutOfRangeError(VGPRRange);
3557 AMDHSA_BITS_SET(KD.compute_pgm_rsrc1,
3558 COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT, VGPRBlocks);
3559
3560 if (!isUInt<COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT_WIDTH>(
3561 SGPRBlocks))
3562 return OutOfRangeError(SGPRRange);
3563 AMDHSA_BITS_SET(KD.compute_pgm_rsrc1,
3564 COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT,
3565 SGPRBlocks);
3566
3567 if (!isUInt<COMPUTE_PGM_RSRC2_USER_SGPR_COUNT_WIDTH>(UserSGPRCount))
3568 return TokError("too many user SGPRs enabled");
3569 AMDHSA_BITS_SET(KD.compute_pgm_rsrc2, COMPUTE_PGM_RSRC2_USER_SGPR_COUNT,
3570 UserSGPRCount);
3571
3572 getTargetStreamer().EmitAmdhsaKernelDescriptor(
3573 getSTI(), KernelName, KD, NextFreeVGPR, NextFreeSGPR, ReserveVCC,
3574 ReserveFlatScr, ReserveXNACK);
3575 return false;
3576}
3577
Tom Stellard347ac792015-06-26 21:15:07 +00003578bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() {
Tom Stellard347ac792015-06-26 21:15:07 +00003579 uint32_t Major;
3580 uint32_t Minor;
3581
3582 if (ParseDirectiveMajorMinor(Major, Minor))
3583 return true;
3584
3585 getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor);
3586 return false;
3587}
3588
3589bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() {
Tom Stellard347ac792015-06-26 21:15:07 +00003590 uint32_t Major;
3591 uint32_t Minor;
3592 uint32_t Stepping;
3593 StringRef VendorName;
3594 StringRef ArchName;
3595
3596 // If this directive has no arguments, then use the ISA version for the
3597 // targeted GPU.
3598 if (getLexer().is(AsmToken::EndOfStatement)) {
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00003599 AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU());
Konstantin Zhuravlyov9f89ede2017-02-08 14:05:23 +00003600 getTargetStreamer().EmitDirectiveHSACodeObjectISA(ISA.Major, ISA.Minor,
3601 ISA.Stepping,
Tom Stellard347ac792015-06-26 21:15:07 +00003602 "AMD", "AMDGPU");
3603 return false;
3604 }
3605
Tom Stellard347ac792015-06-26 21:15:07 +00003606 if (ParseDirectiveMajorMinor(Major, Minor))
3607 return true;
3608
3609 if (getLexer().isNot(AsmToken::Comma))
3610 return TokError("stepping version number required, comma expected");
3611 Lex();
3612
Artem Tamazov25478d82016-12-29 15:41:52 +00003613 if (ParseAsAbsoluteExpression(Stepping))
Tom Stellard347ac792015-06-26 21:15:07 +00003614 return TokError("invalid stepping version");
3615
Tom Stellard347ac792015-06-26 21:15:07 +00003616 if (getLexer().isNot(AsmToken::Comma))
3617 return TokError("vendor name required, comma expected");
3618 Lex();
3619
3620 if (getLexer().isNot(AsmToken::String))
3621 return TokError("invalid vendor name");
3622
3623 VendorName = getLexer().getTok().getStringContents();
3624 Lex();
3625
3626 if (getLexer().isNot(AsmToken::Comma))
3627 return TokError("arch name required, comma expected");
3628 Lex();
3629
3630 if (getLexer().isNot(AsmToken::String))
3631 return TokError("invalid arch name");
3632
3633 ArchName = getLexer().getTok().getStringContents();
3634 Lex();
3635
3636 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping,
3637 VendorName, ArchName);
3638 return false;
3639}
3640
Tom Stellardff7416b2015-06-26 21:58:31 +00003641bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID,
3642 amd_kernel_code_t &Header) {
Konstantin Zhuravlyov61830652018-04-09 20:47:22 +00003643 // max_scratch_backing_memory_byte_size is deprecated. Ignore it while parsing
3644 // assembly for backwards compatibility.
3645 if (ID == "max_scratch_backing_memory_byte_size") {
3646 Parser.eatToEndOfStatement();
3647 return false;
3648 }
3649
Valery Pykhtindc110542016-03-06 20:25:36 +00003650 SmallString<40> ErrStr;
3651 raw_svector_ostream Err(ErrStr);
Valery Pykhtina852d692016-06-23 14:13:06 +00003652 if (!parseAmdKernelCodeField(ID, getParser(), Header, Err)) {
Valery Pykhtindc110542016-03-06 20:25:36 +00003653 return TokError(Err.str());
3654 }
Tom Stellardff7416b2015-06-26 21:58:31 +00003655 Lex();
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00003656
3657 if (ID == "enable_wgp_mode") {
3658 if (G_00B848_WGP_MODE(Header.compute_pgm_resource_registers) && !isGFX10())
3659 return TokError("enable_wgp_mode=1 is only allowed on GFX10+");
3660 }
3661
3662 if (ID == "enable_mem_ordered") {
3663 if (G_00B848_MEM_ORDERED(Header.compute_pgm_resource_registers) && !isGFX10())
3664 return TokError("enable_mem_ordered=1 is only allowed on GFX10+");
3665 }
3666
3667 if (ID == "enable_fwd_progress") {
3668 if (G_00B848_FWD_PROGRESS(Header.compute_pgm_resource_registers) && !isGFX10())
3669 return TokError("enable_fwd_progress=1 is only allowed on GFX10+");
3670 }
3671
Tom Stellardff7416b2015-06-26 21:58:31 +00003672 return false;
3673}
3674
3675bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() {
Tom Stellardff7416b2015-06-26 21:58:31 +00003676 amd_kernel_code_t Header;
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00003677 AMDGPU::initDefaultAMDKernelCodeT(Header, &getSTI());
Tom Stellardff7416b2015-06-26 21:58:31 +00003678
3679 while (true) {
Tom Stellardff7416b2015-06-26 21:58:31 +00003680 // Lex EndOfStatement. This is in a while loop, because lexing a comment
3681 // will set the current token to EndOfStatement.
3682 while(getLexer().is(AsmToken::EndOfStatement))
3683 Lex();
3684
3685 if (getLexer().isNot(AsmToken::Identifier))
3686 return TokError("expected value identifier or .end_amd_kernel_code_t");
3687
3688 StringRef ID = getLexer().getTok().getIdentifier();
3689 Lex();
3690
3691 if (ID == ".end_amd_kernel_code_t")
3692 break;
3693
3694 if (ParseAMDKernelCodeTValue(ID, Header))
3695 return true;
3696 }
3697
3698 getTargetStreamer().EmitAMDKernelCodeT(Header);
3699
3700 return false;
3701}
3702
Tom Stellard1e1b05d2015-11-06 11:45:14 +00003703bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() {
3704 if (getLexer().isNot(AsmToken::Identifier))
3705 return TokError("expected symbol name");
3706
3707 StringRef KernelName = Parser.getTok().getString();
3708
3709 getTargetStreamer().EmitAMDGPUSymbolType(KernelName,
3710 ELF::STT_AMDGPU_HSA_KERNEL);
3711 Lex();
Scott Linder1e8c2c72018-06-21 19:38:56 +00003712 if (!AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI()))
3713 KernelScope.initialize(getContext());
Tom Stellard1e1b05d2015-11-06 11:45:14 +00003714 return false;
3715}
3716
Konstantin Zhuravlyov9c05b2b2017-10-14 15:40:33 +00003717bool AMDGPUAsmParser::ParseDirectiveISAVersion() {
Konstantin Zhuravlyov219066b2017-10-14 16:15:28 +00003718 if (getSTI().getTargetTriple().getArch() != Triple::amdgcn) {
3719 return Error(getParser().getTok().getLoc(),
3720 ".amd_amdgpu_isa directive is not available on non-amdgcn "
3721 "architectures");
3722 }
3723
Konstantin Zhuravlyov9c05b2b2017-10-14 15:40:33 +00003724 auto ISAVersionStringFromASM = getLexer().getTok().getStringContents();
3725
3726 std::string ISAVersionStringFromSTI;
3727 raw_string_ostream ISAVersionStreamFromSTI(ISAVersionStringFromSTI);
3728 IsaInfo::streamIsaVersion(&getSTI(), ISAVersionStreamFromSTI);
3729
3730 if (ISAVersionStringFromASM != ISAVersionStreamFromSTI.str()) {
3731 return Error(getParser().getTok().getLoc(),
3732 ".amd_amdgpu_isa directive does not match triple and/or mcpu "
3733 "arguments specified through the command line");
3734 }
3735
3736 getTargetStreamer().EmitISAVersion(ISAVersionStreamFromSTI.str());
3737 Lex();
3738
3739 return false;
3740}
3741
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +00003742bool AMDGPUAsmParser::ParseDirectiveHSAMetadata() {
Scott Linderf5b36e52018-12-12 19:39:27 +00003743 const char *AssemblerDirectiveBegin;
3744 const char *AssemblerDirectiveEnd;
3745 std::tie(AssemblerDirectiveBegin, AssemblerDirectiveEnd) =
3746 AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())
3747 ? std::make_tuple(HSAMD::V3::AssemblerDirectiveBegin,
3748 HSAMD::V3::AssemblerDirectiveEnd)
3749 : std::make_tuple(HSAMD::AssemblerDirectiveBegin,
3750 HSAMD::AssemblerDirectiveEnd);
3751
Konstantin Zhuravlyov219066b2017-10-14 16:15:28 +00003752 if (getSTI().getTargetTriple().getOS() != Triple::AMDHSA) {
3753 return Error(getParser().getTok().getLoc(),
Scott Linderf5b36e52018-12-12 19:39:27 +00003754 (Twine(AssemblerDirectiveBegin) + Twine(" directive is "
Konstantin Zhuravlyov219066b2017-10-14 16:15:28 +00003755 "not available on non-amdhsa OSes")).str());
3756 }
3757
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +00003758 std::string HSAMetadataString;
Tim Renoufe7bd52f2019-03-20 18:47:21 +00003759 if (ParseToEndDirective(AssemblerDirectiveBegin, AssemblerDirectiveEnd,
3760 HSAMetadataString))
3761 return true;
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +00003762
Scott Linderf5b36e52018-12-12 19:39:27 +00003763 if (IsaInfo::hasCodeObjectV3(&getSTI())) {
3764 if (!getTargetStreamer().EmitHSAMetadataV3(HSAMetadataString))
3765 return Error(getParser().getTok().getLoc(), "invalid HSA metadata");
3766 } else {
3767 if (!getTargetStreamer().EmitHSAMetadataV2(HSAMetadataString))
3768 return Error(getParser().getTok().getLoc(), "invalid HSA metadata");
3769 }
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +00003770
3771 return false;
3772}
3773
Tim Renoufe7bd52f2019-03-20 18:47:21 +00003774/// Common code to parse out a block of text (typically YAML) between start and
3775/// end directives.
3776bool AMDGPUAsmParser::ParseToEndDirective(const char *AssemblerDirectiveBegin,
3777 const char *AssemblerDirectiveEnd,
3778 std::string &CollectString) {
3779
3780 raw_string_ostream CollectStream(CollectString);
3781
3782 getLexer().setSkipSpace(false);
3783
3784 bool FoundEnd = false;
3785 while (!getLexer().is(AsmToken::Eof)) {
3786 while (getLexer().is(AsmToken::Space)) {
3787 CollectStream << getLexer().getTok().getString();
3788 Lex();
3789 }
3790
3791 if (getLexer().is(AsmToken::Identifier)) {
3792 StringRef ID = getLexer().getTok().getIdentifier();
3793 if (ID == AssemblerDirectiveEnd) {
3794 Lex();
3795 FoundEnd = true;
3796 break;
3797 }
3798 }
3799
3800 CollectStream << Parser.parseStringToEndOfStatement()
3801 << getContext().getAsmInfo()->getSeparatorString();
3802
3803 Parser.eatToEndOfStatement();
3804 }
3805
3806 getLexer().setSkipSpace(true);
3807
3808 if (getLexer().is(AsmToken::Eof) && !FoundEnd) {
3809 return TokError(Twine("expected directive ") +
3810 Twine(AssemblerDirectiveEnd) + Twine(" not found"));
3811 }
3812
3813 CollectStream.flush();
3814 return false;
3815}
3816
3817/// Parse the assembler directive for new MsgPack-format PAL metadata.
3818bool AMDGPUAsmParser::ParseDirectivePALMetadataBegin() {
3819 std::string String;
3820 if (ParseToEndDirective(AMDGPU::PALMD::AssemblerDirectiveBegin,
3821 AMDGPU::PALMD::AssemblerDirectiveEnd, String))
3822 return true;
3823
3824 auto PALMetadata = getTargetStreamer().getPALMetadata();
3825 if (!PALMetadata->setFromString(String))
3826 return Error(getParser().getTok().getLoc(), "invalid PAL metadata");
3827 return false;
3828}
3829
3830/// Parse the assembler directive for old linear-format PAL metadata.
Konstantin Zhuravlyovc3beb6a2017-10-11 22:41:09 +00003831bool AMDGPUAsmParser::ParseDirectivePALMetadata() {
Konstantin Zhuravlyov219066b2017-10-14 16:15:28 +00003832 if (getSTI().getTargetTriple().getOS() != Triple::AMDPAL) {
3833 return Error(getParser().getTok().getLoc(),
3834 (Twine(PALMD::AssemblerDirective) + Twine(" directive is "
3835 "not available on non-amdpal OSes")).str());
3836 }
3837
Tim Renoufd737b552019-03-20 17:42:00 +00003838 auto PALMetadata = getTargetStreamer().getPALMetadata();
Tim Renoufe7bd52f2019-03-20 18:47:21 +00003839 PALMetadata->setLegacy();
Tim Renouf72800f02017-10-03 19:03:52 +00003840 for (;;) {
Tim Renoufd737b552019-03-20 17:42:00 +00003841 uint32_t Key, Value;
3842 if (ParseAsAbsoluteExpression(Key)) {
3843 return TokError(Twine("invalid value in ") +
3844 Twine(PALMD::AssemblerDirective));
3845 }
3846 if (getLexer().isNot(AsmToken::Comma)) {
3847 return TokError(Twine("expected an even number of values in ") +
3848 Twine(PALMD::AssemblerDirective));
3849 }
3850 Lex();
Konstantin Zhuravlyovc3beb6a2017-10-11 22:41:09 +00003851 if (ParseAsAbsoluteExpression(Value)) {
3852 return TokError(Twine("invalid value in ") +
3853 Twine(PALMD::AssemblerDirective));
3854 }
Tim Renoufd737b552019-03-20 17:42:00 +00003855 PALMetadata->setRegister(Key, Value);
Tim Renouf72800f02017-10-03 19:03:52 +00003856 if (getLexer().isNot(AsmToken::Comma))
3857 break;
3858 Lex();
3859 }
Tim Renouf72800f02017-10-03 19:03:52 +00003860 return false;
3861}
3862
Tom Stellard45bb48e2015-06-13 03:28:10 +00003863bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
Tom Stellard347ac792015-06-26 21:15:07 +00003864 StringRef IDVal = DirectiveID.getString();
3865
Scott Linder1e8c2c72018-06-21 19:38:56 +00003866 if (AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) {
3867 if (IDVal == ".amdgcn_target")
3868 return ParseDirectiveAMDGCNTarget();
Tom Stellard347ac792015-06-26 21:15:07 +00003869
Scott Linder1e8c2c72018-06-21 19:38:56 +00003870 if (IDVal == ".amdhsa_kernel")
3871 return ParseDirectiveAMDHSAKernel();
Scott Linderf5b36e52018-12-12 19:39:27 +00003872
3873 // TODO: Restructure/combine with PAL metadata directive.
3874 if (IDVal == AMDGPU::HSAMD::V3::AssemblerDirectiveBegin)
3875 return ParseDirectiveHSAMetadata();
Scott Linder1e8c2c72018-06-21 19:38:56 +00003876 } else {
3877 if (IDVal == ".hsa_code_object_version")
3878 return ParseDirectiveHSACodeObjectVersion();
Tom Stellard347ac792015-06-26 21:15:07 +00003879
Scott Linder1e8c2c72018-06-21 19:38:56 +00003880 if (IDVal == ".hsa_code_object_isa")
3881 return ParseDirectiveHSACodeObjectISA();
Tom Stellardff7416b2015-06-26 21:58:31 +00003882
Scott Linder1e8c2c72018-06-21 19:38:56 +00003883 if (IDVal == ".amd_kernel_code_t")
3884 return ParseDirectiveAMDKernelCodeT();
Tom Stellard1e1b05d2015-11-06 11:45:14 +00003885
Scott Linder1e8c2c72018-06-21 19:38:56 +00003886 if (IDVal == ".amdgpu_hsa_kernel")
3887 return ParseDirectiveAMDGPUHsaKernel();
3888
3889 if (IDVal == ".amd_amdgpu_isa")
3890 return ParseDirectiveISAVersion();
Konstantin Zhuravlyov9c05b2b2017-10-14 15:40:33 +00003891
Scott Linderf5b36e52018-12-12 19:39:27 +00003892 if (IDVal == AMDGPU::HSAMD::AssemblerDirectiveBegin)
3893 return ParseDirectiveHSAMetadata();
3894 }
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +00003895
Tim Renoufe7bd52f2019-03-20 18:47:21 +00003896 if (IDVal == PALMD::AssemblerDirectiveBegin)
3897 return ParseDirectivePALMetadataBegin();
3898
Konstantin Zhuravlyovc3beb6a2017-10-11 22:41:09 +00003899 if (IDVal == PALMD::AssemblerDirective)
3900 return ParseDirectivePALMetadata();
Tim Renouf72800f02017-10-03 19:03:52 +00003901
Tom Stellard45bb48e2015-06-13 03:28:10 +00003902 return true;
3903}
3904
Matt Arsenault68802d32015-11-05 03:11:27 +00003905bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI,
3906 unsigned RegNo) const {
Dmitry Preobrazhenskyac2b0262017-12-11 15:23:20 +00003907
3908 for (MCRegAliasIterator R(AMDGPU::TTMP12_TTMP13_TTMP14_TTMP15, &MRI, true);
3909 R.isValid(); ++R) {
3910 if (*R == RegNo)
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00003911 return isGFX9() || isGFX10();
3912 }
3913
3914 // GFX10 has 2 more SGPRs 104 and 105.
3915 for (MCRegAliasIterator R(AMDGPU::SGPR104_SGPR105, &MRI, true);
3916 R.isValid(); ++R) {
3917 if (*R == RegNo)
3918 return hasSGPR104_SGPR105();
Dmitry Preobrazhenskyac2b0262017-12-11 15:23:20 +00003919 }
3920
3921 switch (RegNo) {
Dmitry Preobrazhensky9111f352019-06-03 13:51:24 +00003922 case AMDGPU::SRC_SHARED_BASE:
3923 case AMDGPU::SRC_SHARED_LIMIT:
3924 case AMDGPU::SRC_PRIVATE_BASE:
3925 case AMDGPU::SRC_PRIVATE_LIMIT:
3926 case AMDGPU::SRC_POPS_EXITING_WAVE_ID:
3927 return !isCI() && !isSI() && !isVI();
Dmitry Preobrazhenskyac2b0262017-12-11 15:23:20 +00003928 case AMDGPU::TBA:
3929 case AMDGPU::TBA_LO:
3930 case AMDGPU::TBA_HI:
3931 case AMDGPU::TMA:
3932 case AMDGPU::TMA_LO:
3933 case AMDGPU::TMA_HI:
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00003934 return !isGFX9() && !isGFX10();
Dmitry Preobrazhensky3afbd822018-01-10 14:22:19 +00003935 case AMDGPU::XNACK_MASK:
3936 case AMDGPU::XNACK_MASK_LO:
3937 case AMDGPU::XNACK_MASK_HI:
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00003938 return !isCI() && !isSI() && !isGFX10() && hasXNACK();
3939 case AMDGPU::SGPR_NULL:
3940 return isGFX10();
Dmitry Preobrazhenskyac2b0262017-12-11 15:23:20 +00003941 default:
3942 break;
3943 }
3944
Matt Arsenault3b159672015-12-01 20:31:08 +00003945 if (isCI())
Matt Arsenault68802d32015-11-05 03:11:27 +00003946 return true;
3947
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00003948 if (isSI() || isGFX10()) {
3949 // No flat_scr on SI.
3950 // On GFX10 flat scratch is not a valid register operand and can only be
3951 // accessed with s_setreg/s_getreg.
Matt Arsenault3b159672015-12-01 20:31:08 +00003952 switch (RegNo) {
3953 case AMDGPU::FLAT_SCR:
3954 case AMDGPU::FLAT_SCR_LO:
3955 case AMDGPU::FLAT_SCR_HI:
3956 return false;
3957 default:
3958 return true;
3959 }
3960 }
3961
Matt Arsenault68802d32015-11-05 03:11:27 +00003962 // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that
3963 // SI/CI have.
3964 for (MCRegAliasIterator R(AMDGPU::SGPR102_SGPR103, &MRI, true);
3965 R.isValid(); ++R) {
3966 if (*R == RegNo)
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00003967 return hasSGPR102_SGPR103();
Matt Arsenault68802d32015-11-05 03:11:27 +00003968 }
3969
3970 return true;
3971}
3972
Alex Bradbury58eba092016-11-01 16:32:05 +00003973OperandMatchResultTy
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00003974AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic,
3975 OperandMode Mode) {
Tom Stellard45bb48e2015-06-13 03:28:10 +00003976 // Try to parse with a custom parser
3977 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3978
3979 // If we successfully parsed the operand or if there as an error parsing,
3980 // we are done.
3981 //
3982 // If we are parsing after we reach EndOfStatement then this means we
3983 // are appending default values to the Operands list. This is only done
3984 // by custom parser, so we shouldn't continue on to the generic parsing.
Sam Kolton1bdcef72016-05-23 09:59:02 +00003985 if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail ||
Tom Stellard45bb48e2015-06-13 03:28:10 +00003986 getLexer().is(AsmToken::EndOfStatement))
3987 return ResTy;
3988
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00003989 if (Mode == OperandMode_NSA && getLexer().is(AsmToken::LBrac)) {
3990 unsigned Prefix = Operands.size();
3991 SMLoc LBraceLoc = getTok().getLoc();
3992 Parser.Lex(); // eat the '['
3993
3994 for (;;) {
3995 ResTy = parseReg(Operands);
3996 if (ResTy != MatchOperand_Success)
3997 return ResTy;
3998
3999 if (getLexer().is(AsmToken::RBrac))
4000 break;
4001
4002 if (getLexer().isNot(AsmToken::Comma))
4003 return MatchOperand_ParseFail;
4004 Parser.Lex();
4005 }
4006
4007 if (Operands.size() - Prefix > 1) {
4008 Operands.insert(Operands.begin() + Prefix,
4009 AMDGPUOperand::CreateToken(this, "[", LBraceLoc));
4010 Operands.push_back(AMDGPUOperand::CreateToken(this, "]",
4011 getTok().getLoc()));
4012 }
4013
4014 Parser.Lex(); // eat the ']'
4015 return MatchOperand_Success;
4016 }
4017
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +00004018 return parseRegOrImm(Operands);
Tom Stellard45bb48e2015-06-13 03:28:10 +00004019}
4020
Sam Kolton05ef1c92016-06-03 10:27:37 +00004021StringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) {
4022 // Clear any forced encodings from the previous instruction.
4023 setForcedEncodingSize(0);
4024 setForcedDPP(false);
4025 setForcedSDWA(false);
4026
4027 if (Name.endswith("_e64")) {
4028 setForcedEncodingSize(64);
4029 return Name.substr(0, Name.size() - 4);
4030 } else if (Name.endswith("_e32")) {
4031 setForcedEncodingSize(32);
4032 return Name.substr(0, Name.size() - 4);
4033 } else if (Name.endswith("_dpp")) {
4034 setForcedDPP(true);
4035 return Name.substr(0, Name.size() - 4);
4036 } else if (Name.endswith("_sdwa")) {
4037 setForcedSDWA(true);
4038 return Name.substr(0, Name.size() - 5);
4039 }
4040 return Name;
4041}
4042
Tom Stellard45bb48e2015-06-13 03:28:10 +00004043bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info,
4044 StringRef Name,
4045 SMLoc NameLoc, OperandVector &Operands) {
Tom Stellard45bb48e2015-06-13 03:28:10 +00004046 // Add the instruction mnemonic
Sam Kolton05ef1c92016-06-03 10:27:37 +00004047 Name = parseMnemonicSuffix(Name);
Sam Kolton1eeb11b2016-09-09 14:44:04 +00004048 Operands.push_back(AMDGPUOperand::CreateToken(this, Name, NameLoc));
Matt Arsenault37fefd62016-06-10 02:18:02 +00004049
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00004050 bool IsMIMG = Name.startswith("image_");
4051
Tom Stellard45bb48e2015-06-13 03:28:10 +00004052 while (!getLexer().is(AsmToken::EndOfStatement)) {
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00004053 OperandMode Mode = OperandMode_Default;
4054 if (IsMIMG && isGFX10() && Operands.size() == 2)
4055 Mode = OperandMode_NSA;
4056 OperandMatchResultTy Res = parseOperand(Operands, Name, Mode);
Tom Stellard45bb48e2015-06-13 03:28:10 +00004057
4058 // Eat the comma or space if there is one.
4059 if (getLexer().is(AsmToken::Comma))
4060 Parser.Lex();
Matt Arsenault37fefd62016-06-10 02:18:02 +00004061
Tom Stellard45bb48e2015-06-13 03:28:10 +00004062 switch (Res) {
4063 case MatchOperand_Success: break;
Matt Arsenault37fefd62016-06-10 02:18:02 +00004064 case MatchOperand_ParseFail:
Dmitry Preobrazhensky7773fc42019-05-22 13:59:01 +00004065 // FIXME: use real operand location rather than the current location.
Sam Kolton1bdcef72016-05-23 09:59:02 +00004066 Error(getLexer().getLoc(), "failed parsing operand.");
4067 while (!getLexer().is(AsmToken::EndOfStatement)) {
4068 Parser.Lex();
4069 }
4070 return true;
Matt Arsenault37fefd62016-06-10 02:18:02 +00004071 case MatchOperand_NoMatch:
Dmitry Preobrazhensky7773fc42019-05-22 13:59:01 +00004072 // FIXME: use real operand location rather than the current location.
Sam Kolton1bdcef72016-05-23 09:59:02 +00004073 Error(getLexer().getLoc(), "not a valid operand.");
4074 while (!getLexer().is(AsmToken::EndOfStatement)) {
4075 Parser.Lex();
4076 }
4077 return true;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004078 }
4079 }
4080
Tom Stellard45bb48e2015-06-13 03:28:10 +00004081 return false;
4082}
4083
4084//===----------------------------------------------------------------------===//
4085// Utility functions
4086//===----------------------------------------------------------------------===//
4087
Alex Bradbury58eba092016-11-01 16:32:05 +00004088OperandMatchResultTy
Dmitry Preobrazhensky198611b2019-05-17 16:04:17 +00004089AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &IntVal) {
Tom Stellard45bb48e2015-06-13 03:28:10 +00004090
Dmitry Preobrazhensky198611b2019-05-17 16:04:17 +00004091 if (!trySkipId(Prefix, AsmToken::Colon))
4092 return MatchOperand_NoMatch;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004093
Dmitry Preobrazhensky198611b2019-05-17 16:04:17 +00004094 return parseExpr(IntVal) ? MatchOperand_Success : MatchOperand_ParseFail;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004095}
4096
Alex Bradbury58eba092016-11-01 16:32:05 +00004097OperandMatchResultTy
Tom Stellard45bb48e2015-06-13 03:28:10 +00004098AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
Matt Arsenaultf15da6c2017-02-03 20:49:51 +00004099 AMDGPUOperand::ImmTy ImmTy,
Nikolay Haustov4f672a32016-04-29 09:02:30 +00004100 bool (*ConvertResult)(int64_t&)) {
Dmitry Preobrazhensky198611b2019-05-17 16:04:17 +00004101 SMLoc S = getLoc();
Nikolay Haustov4f672a32016-04-29 09:02:30 +00004102 int64_t Value = 0;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004103
Alex Bradbury58eba092016-11-01 16:32:05 +00004104 OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Value);
Tom Stellard45bb48e2015-06-13 03:28:10 +00004105 if (Res != MatchOperand_Success)
4106 return Res;
4107
Nikolay Haustov4f672a32016-04-29 09:02:30 +00004108 if (ConvertResult && !ConvertResult(Value)) {
Dmitry Preobrazhensky198611b2019-05-17 16:04:17 +00004109 Error(S, "invalid " + StringRef(Prefix) + " value.");
Nikolay Haustov4f672a32016-04-29 09:02:30 +00004110 }
4111
Sam Kolton1eeb11b2016-09-09 14:44:04 +00004112 Operands.push_back(AMDGPUOperand::CreateImm(this, Value, S, ImmTy));
Tom Stellard45bb48e2015-06-13 03:28:10 +00004113 return MatchOperand_Success;
4114}
4115
Dmitry Preobrazhensky7773fc42019-05-22 13:59:01 +00004116OperandMatchResultTy
4117AMDGPUAsmParser::parseOperandArrayWithPrefix(const char *Prefix,
4118 OperandVector &Operands,
4119 AMDGPUOperand::ImmTy ImmTy,
4120 bool (*ConvertResult)(int64_t&)) {
4121 SMLoc S = getLoc();
4122 if (!trySkipId(Prefix, AsmToken::Colon))
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00004123 return MatchOperand_NoMatch;
4124
Dmitry Preobrazhensky7773fc42019-05-22 13:59:01 +00004125 if (!skipToken(AsmToken::LBrac, "expected a left square bracket"))
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00004126 return MatchOperand_ParseFail;
4127
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00004128 unsigned Val = 0;
Dmitry Preobrazhensky7773fc42019-05-22 13:59:01 +00004129 const unsigned MaxSize = 4;
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00004130
4131 // FIXME: How to verify the number of elements matches the number of src
4132 // operands?
Dmitry Preobrazhensky7773fc42019-05-22 13:59:01 +00004133 for (int I = 0; ; ++I) {
4134 int64_t Op;
4135 SMLoc Loc = getLoc();
4136 if (!parseExpr(Op))
4137 return MatchOperand_ParseFail;
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00004138
Dmitry Preobrazhensky7773fc42019-05-22 13:59:01 +00004139 if (Op != 0 && Op != 1) {
4140 Error(Loc, "invalid " + StringRef(Prefix) + " value.");
4141 return MatchOperand_ParseFail;
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00004142 }
4143
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00004144 Val |= (Op << I);
Dmitry Preobrazhensky7773fc42019-05-22 13:59:01 +00004145
4146 if (trySkipToken(AsmToken::RBrac))
4147 break;
4148
4149 if (I + 1 == MaxSize) {
4150 Error(getLoc(), "expected a closing square bracket");
4151 return MatchOperand_ParseFail;
4152 }
4153
4154 if (!skipToken(AsmToken::Comma, "expected a comma"))
4155 return MatchOperand_ParseFail;
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00004156 }
4157
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00004158 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S, ImmTy));
4159 return MatchOperand_Success;
4160}
4161
Alex Bradbury58eba092016-11-01 16:32:05 +00004162OperandMatchResultTy
Tom Stellard45bb48e2015-06-13 03:28:10 +00004163AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands,
Matt Arsenaultf15da6c2017-02-03 20:49:51 +00004164 AMDGPUOperand::ImmTy ImmTy) {
Tom Stellard45bb48e2015-06-13 03:28:10 +00004165 int64_t Bit = 0;
4166 SMLoc S = Parser.getTok().getLoc();
4167
4168 // We are at the end of the statement, and this is a default argument, so
4169 // use a default value.
4170 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4171 switch(getLexer().getKind()) {
4172 case AsmToken::Identifier: {
4173 StringRef Tok = Parser.getTok().getString();
4174 if (Tok == Name) {
Ryan Taylor1f334d02018-08-28 15:07:30 +00004175 if (Tok == "r128" && isGFX9())
4176 Error(S, "r128 modifier is not supported on this GPU");
4177 if (Tok == "a16" && !isGFX9())
4178 Error(S, "a16 modifier is not supported on this GPU");
Tom Stellard45bb48e2015-06-13 03:28:10 +00004179 Bit = 1;
4180 Parser.Lex();
4181 } else if (Tok.startswith("no") && Tok.endswith(Name)) {
4182 Bit = 0;
4183 Parser.Lex();
4184 } else {
Sam Kolton11de3702016-05-24 12:38:33 +00004185 return MatchOperand_NoMatch;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004186 }
4187 break;
4188 }
4189 default:
4190 return MatchOperand_NoMatch;
4191 }
4192 }
4193
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00004194 if (!isGFX10() && ImmTy == AMDGPUOperand::ImmTyDLC)
4195 return MatchOperand_ParseFail;
4196
Sam Kolton1eeb11b2016-09-09 14:44:04 +00004197 Operands.push_back(AMDGPUOperand::CreateImm(this, Bit, S, ImmTy));
Tom Stellard45bb48e2015-06-13 03:28:10 +00004198 return MatchOperand_Success;
4199}
4200
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00004201static void addOptionalImmOperand(
4202 MCInst& Inst, const OperandVector& Operands,
4203 AMDGPUAsmParser::OptionalImmIndexMap& OptionalIdx,
4204 AMDGPUOperand::ImmTy ImmT,
4205 int64_t Default = 0) {
Nikolay Haustov2e4c7292016-02-25 10:58:54 +00004206 auto i = OptionalIdx.find(ImmT);
4207 if (i != OptionalIdx.end()) {
4208 unsigned Idx = i->second;
4209 ((AMDGPUOperand &)*Operands[Idx]).addImmOperands(Inst, 1);
4210 } else {
Sam Koltondfa29f72016-03-09 12:29:31 +00004211 Inst.addOperand(MCOperand::createImm(Default));
Nikolay Haustov2e4c7292016-02-25 10:58:54 +00004212 }
4213}
4214
Alex Bradbury58eba092016-11-01 16:32:05 +00004215OperandMatchResultTy
Sam Kolton05ef1c92016-06-03 10:27:37 +00004216AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix, StringRef &Value) {
Sam Kolton3025e7f2016-04-26 13:33:56 +00004217 if (getLexer().isNot(AsmToken::Identifier)) {
4218 return MatchOperand_NoMatch;
4219 }
4220 StringRef Tok = Parser.getTok().getString();
4221 if (Tok != Prefix) {
4222 return MatchOperand_NoMatch;
4223 }
4224
4225 Parser.Lex();
4226 if (getLexer().isNot(AsmToken::Colon)) {
4227 return MatchOperand_ParseFail;
4228 }
Matt Arsenault37fefd62016-06-10 02:18:02 +00004229
Sam Kolton3025e7f2016-04-26 13:33:56 +00004230 Parser.Lex();
4231 if (getLexer().isNot(AsmToken::Identifier)) {
4232 return MatchOperand_ParseFail;
4233 }
4234
4235 Value = Parser.getTok().getString();
4236 return MatchOperand_Success;
4237}
4238
Tim Renouf35484c92018-08-21 11:06:05 +00004239// dfmt and nfmt (in a tbuffer instruction) are parsed as one to allow their
4240// values to live in a joint format operand in the MCInst encoding.
4241OperandMatchResultTy
4242AMDGPUAsmParser::parseDfmtNfmt(OperandVector &Operands) {
4243 SMLoc S = Parser.getTok().getLoc();
4244 int64_t Dfmt = 0, Nfmt = 0;
4245 // dfmt and nfmt can appear in either order, and each is optional.
4246 bool GotDfmt = false, GotNfmt = false;
4247 while (!GotDfmt || !GotNfmt) {
4248 if (!GotDfmt) {
4249 auto Res = parseIntWithPrefix("dfmt", Dfmt);
4250 if (Res != MatchOperand_NoMatch) {
4251 if (Res != MatchOperand_Success)
4252 return Res;
4253 if (Dfmt >= 16) {
4254 Error(Parser.getTok().getLoc(), "out of range dfmt");
4255 return MatchOperand_ParseFail;
4256 }
4257 GotDfmt = true;
4258 Parser.Lex();
4259 continue;
4260 }
4261 }
4262 if (!GotNfmt) {
4263 auto Res = parseIntWithPrefix("nfmt", Nfmt);
4264 if (Res != MatchOperand_NoMatch) {
4265 if (Res != MatchOperand_Success)
4266 return Res;
4267 if (Nfmt >= 8) {
4268 Error(Parser.getTok().getLoc(), "out of range nfmt");
4269 return MatchOperand_ParseFail;
4270 }
4271 GotNfmt = true;
4272 Parser.Lex();
4273 continue;
4274 }
4275 }
4276 break;
4277 }
4278 if (!GotDfmt && !GotNfmt)
4279 return MatchOperand_NoMatch;
4280 auto Format = Dfmt | Nfmt << 4;
4281 Operands.push_back(
4282 AMDGPUOperand::CreateImm(this, Format, S, AMDGPUOperand::ImmTyFORMAT));
4283 return MatchOperand_Success;
4284}
4285
Tom Stellard45bb48e2015-06-13 03:28:10 +00004286//===----------------------------------------------------------------------===//
4287// ds
4288//===----------------------------------------------------------------------===//
4289
Tom Stellard45bb48e2015-06-13 03:28:10 +00004290void AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst,
4291 const OperandVector &Operands) {
Nikolay Haustov2e4c7292016-02-25 10:58:54 +00004292 OptionalImmIndexMap OptionalIdx;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004293
4294 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
4295 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
4296
4297 // Add the register arguments
4298 if (Op.isReg()) {
4299 Op.addRegOperands(Inst, 1);
4300 continue;
4301 }
4302
4303 // Handle optional arguments
4304 OptionalIdx[Op.getImmTy()] = i;
4305 }
4306
Nikolay Haustov4f672a32016-04-29 09:02:30 +00004307 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset0);
4308 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset1);
Nikolay Haustov2e4c7292016-02-25 10:58:54 +00004309 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
Tom Stellard45bb48e2015-06-13 03:28:10 +00004310
Tom Stellard45bb48e2015-06-13 03:28:10 +00004311 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
4312}
4313
Matt Arsenaultf15da6c2017-02-03 20:49:51 +00004314void AMDGPUAsmParser::cvtDSImpl(MCInst &Inst, const OperandVector &Operands,
4315 bool IsGdsHardcoded) {
4316 OptionalImmIndexMap OptionalIdx;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004317
4318 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
4319 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
4320
4321 // Add the register arguments
4322 if (Op.isReg()) {
4323 Op.addRegOperands(Inst, 1);
4324 continue;
4325 }
4326
4327 if (Op.isToken() && Op.getToken() == "gds") {
Artem Tamazov43b61562017-02-03 12:47:30 +00004328 IsGdsHardcoded = true;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004329 continue;
4330 }
4331
4332 // Handle optional arguments
4333 OptionalIdx[Op.getImmTy()] = i;
4334 }
4335
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00004336 AMDGPUOperand::ImmTy OffsetType =
Stanislav Mekhanoshina224f682019-05-01 16:11:11 +00004337 (Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_gfx10 ||
4338 Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_gfx6_gfx7 ||
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00004339 Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_vi) ? AMDGPUOperand::ImmTySwizzle :
4340 AMDGPUOperand::ImmTyOffset;
4341
4342 addOptionalImmOperand(Inst, Operands, OptionalIdx, OffsetType);
4343
Artem Tamazov43b61562017-02-03 12:47:30 +00004344 if (!IsGdsHardcoded) {
Nikolay Haustov2e4c7292016-02-25 10:58:54 +00004345 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
Tom Stellard45bb48e2015-06-13 03:28:10 +00004346 }
4347 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
4348}
4349
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00004350void AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) {
4351 OptionalImmIndexMap OptionalIdx;
4352
Dmitry Preobrazhensky9321e8f2017-05-19 13:36:09 +00004353 unsigned OperandIdx[4];
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00004354 unsigned EnMask = 0;
4355 int SrcIdx = 0;
4356
4357 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
4358 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
4359
4360 // Add the register arguments
4361 if (Op.isReg()) {
Dmitry Preobrazhensky9321e8f2017-05-19 13:36:09 +00004362 assert(SrcIdx < 4);
4363 OperandIdx[SrcIdx] = Inst.size();
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00004364 Op.addRegOperands(Inst, 1);
4365 ++SrcIdx;
4366 continue;
4367 }
4368
4369 if (Op.isOff()) {
Dmitry Preobrazhensky9321e8f2017-05-19 13:36:09 +00004370 assert(SrcIdx < 4);
4371 OperandIdx[SrcIdx] = Inst.size();
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00004372 Inst.addOperand(MCOperand::createReg(AMDGPU::NoRegister));
Dmitry Preobrazhensky9321e8f2017-05-19 13:36:09 +00004373 ++SrcIdx;
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00004374 continue;
4375 }
4376
4377 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyExpTgt) {
4378 Op.addImmOperands(Inst, 1);
4379 continue;
4380 }
4381
4382 if (Op.isToken() && Op.getToken() == "done")
4383 continue;
4384
4385 // Handle optional arguments
4386 OptionalIdx[Op.getImmTy()] = i;
4387 }
4388
Dmitry Preobrazhensky9321e8f2017-05-19 13:36:09 +00004389 assert(SrcIdx == 4);
4390
4391 bool Compr = false;
4392 if (OptionalIdx.find(AMDGPUOperand::ImmTyExpCompr) != OptionalIdx.end()) {
4393 Compr = true;
4394 Inst.getOperand(OperandIdx[1]) = Inst.getOperand(OperandIdx[2]);
4395 Inst.getOperand(OperandIdx[2]).setReg(AMDGPU::NoRegister);
4396 Inst.getOperand(OperandIdx[3]).setReg(AMDGPU::NoRegister);
4397 }
4398
4399 for (auto i = 0; i < SrcIdx; ++i) {
4400 if (Inst.getOperand(OperandIdx[i]).getReg() != AMDGPU::NoRegister) {
4401 EnMask |= Compr? (0x3 << i * 2) : (0x1 << i);
4402 }
4403 }
4404
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00004405 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpVM);
4406 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpCompr);
4407
4408 Inst.addOperand(MCOperand::createImm(EnMask));
4409}
Tom Stellard45bb48e2015-06-13 03:28:10 +00004410
4411//===----------------------------------------------------------------------===//
4412// s_waitcnt
4413//===----------------------------------------------------------------------===//
4414
Dmitry Preobrazhensky43d297e2017-04-26 17:55:50 +00004415static bool
4416encodeCnt(
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00004417 const AMDGPU::IsaVersion ISA,
Dmitry Preobrazhensky43d297e2017-04-26 17:55:50 +00004418 int64_t &IntVal,
4419 int64_t CntVal,
4420 bool Saturate,
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00004421 unsigned (*encode)(const IsaVersion &Version, unsigned, unsigned),
4422 unsigned (*decode)(const IsaVersion &Version, unsigned))
Dmitry Preobrazhensky43d297e2017-04-26 17:55:50 +00004423{
4424 bool Failed = false;
4425
4426 IntVal = encode(ISA, IntVal, CntVal);
4427 if (CntVal != decode(ISA, IntVal)) {
4428 if (Saturate) {
4429 IntVal = encode(ISA, IntVal, -1);
4430 } else {
4431 Failed = true;
4432 }
4433 }
4434 return Failed;
4435}
4436
Tom Stellard45bb48e2015-06-13 03:28:10 +00004437bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
Dmitry Preobrazhenskyb79af792019-05-27 14:08:43 +00004438
4439 SMLoc CntLoc = getLoc();
4440 StringRef CntName = getTokenStr();
4441
4442 if (!skipToken(AsmToken::Identifier, "expected a counter name") ||
4443 !skipToken(AsmToken::LParen, "expected a left parenthesis"))
4444 return false;
4445
Tom Stellard45bb48e2015-06-13 03:28:10 +00004446 int64_t CntVal;
Dmitry Preobrazhenskyb79af792019-05-27 14:08:43 +00004447 SMLoc ValLoc = getLoc();
4448 if (!parseExpr(CntVal))
4449 return false;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004450
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00004451 AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU());
Tom Stellard45bb48e2015-06-13 03:28:10 +00004452
Dmitry Preobrazhensky43d297e2017-04-26 17:55:50 +00004453 bool Failed = true;
4454 bool Sat = CntName.endswith("_sat");
4455
4456 if (CntName == "vmcnt" || CntName == "vmcnt_sat") {
4457 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeVmcnt, decodeVmcnt);
4458 } else if (CntName == "expcnt" || CntName == "expcnt_sat") {
4459 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeExpcnt, decodeExpcnt);
4460 } else if (CntName == "lgkmcnt" || CntName == "lgkmcnt_sat") {
4461 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeLgkmcnt, decodeLgkmcnt);
Dmitry Preobrazhenskyb79af792019-05-27 14:08:43 +00004462 } else {
4463 Error(CntLoc, "invalid counter name " + CntName);
4464 return false;
Dmitry Preobrazhensky43d297e2017-04-26 17:55:50 +00004465 }
4466
Dmitry Preobrazhensky5a2f8812017-06-07 16:08:02 +00004467 if (Failed) {
4468 Error(ValLoc, "too large value for " + CntName);
Dmitry Preobrazhenskyb79af792019-05-27 14:08:43 +00004469 return false;
Dmitry Preobrazhensky5a2f8812017-06-07 16:08:02 +00004470 }
4471
Dmitry Preobrazhenskyb79af792019-05-27 14:08:43 +00004472 if (!skipToken(AsmToken::RParen, "expected a closing parenthesis"))
4473 return false;
Dmitry Preobrazhensky5a2f8812017-06-07 16:08:02 +00004474
Dmitry Preobrazhenskyb79af792019-05-27 14:08:43 +00004475 if (trySkipToken(AsmToken::Amp) || trySkipToken(AsmToken::Comma)) {
4476 if (isToken(AsmToken::EndOfStatement)) {
4477 Error(getLoc(), "expected a counter name");
4478 return false;
Dmitry Preobrazhensky43d297e2017-04-26 17:55:50 +00004479 }
4480 }
4481
Dmitry Preobrazhenskyb79af792019-05-27 14:08:43 +00004482 return true;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004483}
4484
Alex Bradbury58eba092016-11-01 16:32:05 +00004485OperandMatchResultTy
Tom Stellard45bb48e2015-06-13 03:28:10 +00004486AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) {
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00004487 AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU());
Konstantin Zhuravlyov9f89ede2017-02-08 14:05:23 +00004488 int64_t Waitcnt = getWaitcntBitMask(ISA);
Dmitry Preobrazhenskyb79af792019-05-27 14:08:43 +00004489 SMLoc S = getLoc();
Tom Stellard45bb48e2015-06-13 03:28:10 +00004490
Dmitry Preobrazhenskyb79af792019-05-27 14:08:43 +00004491 // If parse failed, do not return error code
4492 // to avoid excessive error messages.
4493 if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) {
4494 while (parseCnt(Waitcnt) && !isToken(AsmToken::EndOfStatement));
4495 } else {
4496 parseExpr(Waitcnt);
Tom Stellard45bb48e2015-06-13 03:28:10 +00004497 }
Dmitry Preobrazhenskyb79af792019-05-27 14:08:43 +00004498
Konstantin Zhuravlyovcdd45472016-10-11 18:58:22 +00004499 Operands.push_back(AMDGPUOperand::CreateImm(this, Waitcnt, S));
Tom Stellard45bb48e2015-06-13 03:28:10 +00004500 return MatchOperand_Success;
4501}
4502
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004503bool
4504AMDGPUOperand::isSWaitCnt() const {
4505 return isImm();
4506}
4507
4508//===----------------------------------------------------------------------===//
4509// hwreg
4510//===----------------------------------------------------------------------===//
4511
4512bool
4513AMDGPUAsmParser::parseHwregBody(OperandInfoTy &HwReg,
4514 int64_t &Offset,
4515 int64_t &Width) {
Artem Tamazov6edc1352016-05-26 17:00:33 +00004516 using namespace llvm::AMDGPU::Hwreg;
4517
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004518 // The register may be specified by name or using a numeric code
4519 if (isToken(AsmToken::Identifier) &&
4520 (HwReg.Id = getHwregId(getTokenStr())) >= 0) {
Artem Tamazov6edc1352016-05-26 17:00:33 +00004521 HwReg.IsSymbolic = true;
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004522 lex(); // skip message name
4523 } else if (!parseExpr(HwReg.Id)) {
Artem Tamazovd6468662016-04-25 14:13:51 +00004524 return false;
4525 }
4526
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004527 if (trySkipToken(AsmToken::RParen))
Artem Tamazovd6468662016-04-25 14:13:51 +00004528 return true;
4529
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004530 // parse optional params
4531 return
4532 skipToken(AsmToken::Comma, "expected a comma or a closing parenthesis") &&
4533 parseExpr(Offset) &&
4534 skipToken(AsmToken::Comma, "expected a comma") &&
4535 parseExpr(Width) &&
4536 skipToken(AsmToken::RParen, "expected a closing parenthesis");
Artem Tamazovd6468662016-04-25 14:13:51 +00004537}
4538
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004539void
4540AMDGPUAsmParser::validateHwreg(const OperandInfoTy &HwReg,
4541 const int64_t Offset,
4542 const int64_t Width,
4543 const SMLoc Loc) {
4544
Artem Tamazov6edc1352016-05-26 17:00:33 +00004545 using namespace llvm::AMDGPU::Hwreg;
4546
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004547 if (HwReg.IsSymbolic && !isValidHwreg(HwReg.Id, getSTI())) {
4548 Error(Loc, "specified hardware register is not supported on this GPU");
4549 } else if (!isValidHwreg(HwReg.Id)) {
4550 Error(Loc, "invalid code of hardware register: only 6-bit values are legal");
4551 } else if (!isValidHwregOffset(Offset)) {
4552 Error(Loc, "invalid bit offset: only 5-bit values are legal");
4553 } else if (!isValidHwregWidth(Width)) {
4554 Error(Loc, "invalid bitfield width: only values from 1 to 32 are legal");
Artem Tamazovd6468662016-04-25 14:13:51 +00004555 }
Artem Tamazovd6468662016-04-25 14:13:51 +00004556}
4557
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004558OperandMatchResultTy
4559AMDGPUAsmParser::parseHwreg(OperandVector &Operands) {
4560 using namespace llvm::AMDGPU::Hwreg;
4561
4562 int64_t ImmVal = 0;
4563 SMLoc Loc = getLoc();
4564
4565 // If parse failed, do not return error code
4566 // to avoid excessive error messages.
4567 if (trySkipId("hwreg", AsmToken::LParen)) {
4568 OperandInfoTy HwReg(ID_UNKNOWN_);
4569 int64_t Offset = OFFSET_DEFAULT_;
4570 int64_t Width = WIDTH_DEFAULT_;
4571 if (parseHwregBody(HwReg, Offset, Width)) {
4572 validateHwreg(HwReg, Offset, Width, Loc);
4573 ImmVal = encodeHwreg(HwReg.Id, Offset, Width);
4574 }
4575 } else if (parseExpr(ImmVal)) {
4576 if (ImmVal < 0 || !isUInt<16>(ImmVal))
4577 Error(Loc, "invalid immediate: only 16-bit values are legal");
4578 }
4579
4580 Operands.push_back(AMDGPUOperand::CreateImm(this, ImmVal, Loc, AMDGPUOperand::ImmTyHwreg));
4581 return MatchOperand_Success;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004582}
4583
Artem Tamazovd6468662016-04-25 14:13:51 +00004584bool AMDGPUOperand::isHwreg() const {
4585 return isImmTy(ImmTyHwreg);
4586}
4587
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004588//===----------------------------------------------------------------------===//
4589// sendmsg
4590//===----------------------------------------------------------------------===//
4591
Artem Tamazov6edc1352016-05-26 17:00:33 +00004592bool AMDGPUAsmParser::parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId) {
Artem Tamazovebe71ce2016-05-06 17:48:48 +00004593 using namespace llvm::AMDGPU::SendMsg;
4594
4595 if (Parser.getTok().getString() != "sendmsg")
4596 return true;
4597 Parser.Lex();
4598
4599 if (getLexer().isNot(AsmToken::LParen))
4600 return true;
4601 Parser.Lex();
4602
4603 if (getLexer().is(AsmToken::Identifier)) {
4604 Msg.IsSymbolic = true;
4605 Msg.Id = ID_UNKNOWN_;
4606 const std::string tok = Parser.getTok().getString();
4607 for (int i = ID_GAPS_FIRST_; i < ID_GAPS_LAST_; ++i) {
4608 switch(i) {
4609 default: continue; // Omit gaps.
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00004610 case ID_GS_ALLOC_REQ:
4611 if (isSI() || isCI() || isVI())
4612 continue;
4613 break;
4614 case ID_INTERRUPT: case ID_GS: case ID_GS_DONE:
4615 case ID_SYSMSG: break;
Artem Tamazovebe71ce2016-05-06 17:48:48 +00004616 }
4617 if (tok == IdSymbolic[i]) {
4618 Msg.Id = i;
4619 break;
4620 }
4621 }
4622 Parser.Lex();
4623 } else {
4624 Msg.IsSymbolic = false;
4625 if (getLexer().isNot(AsmToken::Integer))
4626 return true;
4627 if (getParser().parseAbsoluteExpression(Msg.Id))
4628 return true;
4629 if (getLexer().is(AsmToken::Integer))
4630 if (getParser().parseAbsoluteExpression(Msg.Id))
4631 Msg.Id = ID_UNKNOWN_;
4632 }
4633 if (Msg.Id == ID_UNKNOWN_) // Don't know how to parse the rest.
4634 return false;
4635
4636 if (!(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG)) {
4637 if (getLexer().isNot(AsmToken::RParen))
4638 return true;
4639 Parser.Lex();
4640 return false;
4641 }
4642
4643 if (getLexer().isNot(AsmToken::Comma))
4644 return true;
4645 Parser.Lex();
4646
4647 assert(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG);
4648 Operation.Id = ID_UNKNOWN_;
4649 if (getLexer().is(AsmToken::Identifier)) {
4650 Operation.IsSymbolic = true;
4651 const char* const *S = (Msg.Id == ID_SYSMSG) ? OpSysSymbolic : OpGsSymbolic;
4652 const int F = (Msg.Id == ID_SYSMSG) ? OP_SYS_FIRST_ : OP_GS_FIRST_;
4653 const int L = (Msg.Id == ID_SYSMSG) ? OP_SYS_LAST_ : OP_GS_LAST_;
Artem Tamazov6edc1352016-05-26 17:00:33 +00004654 const StringRef Tok = Parser.getTok().getString();
Artem Tamazovebe71ce2016-05-06 17:48:48 +00004655 for (int i = F; i < L; ++i) {
4656 if (Tok == S[i]) {
4657 Operation.Id = i;
4658 break;
4659 }
4660 }
4661 Parser.Lex();
4662 } else {
4663 Operation.IsSymbolic = false;
4664 if (getLexer().isNot(AsmToken::Integer))
4665 return true;
4666 if (getParser().parseAbsoluteExpression(Operation.Id))
4667 return true;
4668 }
4669
4670 if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
4671 // Stream id is optional.
4672 if (getLexer().is(AsmToken::RParen)) {
4673 Parser.Lex();
4674 return false;
4675 }
4676
4677 if (getLexer().isNot(AsmToken::Comma))
4678 return true;
4679 Parser.Lex();
4680
4681 if (getLexer().isNot(AsmToken::Integer))
4682 return true;
4683 if (getParser().parseAbsoluteExpression(StreamId))
4684 return true;
4685 }
4686
4687 if (getLexer().isNot(AsmToken::RParen))
4688 return true;
4689 Parser.Lex();
4690 return false;
4691}
4692
Matt Arsenault0e8a2992016-12-15 20:40:20 +00004693OperandMatchResultTy AMDGPUAsmParser::parseInterpSlot(OperandVector &Operands) {
4694 if (getLexer().getKind() != AsmToken::Identifier)
4695 return MatchOperand_NoMatch;
4696
4697 StringRef Str = Parser.getTok().getString();
4698 int Slot = StringSwitch<int>(Str)
4699 .Case("p10", 0)
4700 .Case("p20", 1)
4701 .Case("p0", 2)
4702 .Default(-1);
4703
4704 SMLoc S = Parser.getTok().getLoc();
4705 if (Slot == -1)
4706 return MatchOperand_ParseFail;
4707
4708 Parser.Lex();
4709 Operands.push_back(AMDGPUOperand::CreateImm(this, Slot, S,
4710 AMDGPUOperand::ImmTyInterpSlot));
4711 return MatchOperand_Success;
4712}
4713
4714OperandMatchResultTy AMDGPUAsmParser::parseInterpAttr(OperandVector &Operands) {
4715 if (getLexer().getKind() != AsmToken::Identifier)
4716 return MatchOperand_NoMatch;
4717
4718 StringRef Str = Parser.getTok().getString();
4719 if (!Str.startswith("attr"))
4720 return MatchOperand_NoMatch;
4721
4722 StringRef Chan = Str.take_back(2);
4723 int AttrChan = StringSwitch<int>(Chan)
4724 .Case(".x", 0)
4725 .Case(".y", 1)
4726 .Case(".z", 2)
4727 .Case(".w", 3)
4728 .Default(-1);
4729 if (AttrChan == -1)
4730 return MatchOperand_ParseFail;
4731
4732 Str = Str.drop_back(2).drop_front(4);
4733
4734 uint8_t Attr;
4735 if (Str.getAsInteger(10, Attr))
4736 return MatchOperand_ParseFail;
4737
4738 SMLoc S = Parser.getTok().getLoc();
4739 Parser.Lex();
4740 if (Attr > 63) {
4741 Error(S, "out of bounds attr");
4742 return MatchOperand_Success;
4743 }
4744
4745 SMLoc SChan = SMLoc::getFromPointer(Chan.data());
4746
4747 Operands.push_back(AMDGPUOperand::CreateImm(this, Attr, S,
4748 AMDGPUOperand::ImmTyInterpAttr));
4749 Operands.push_back(AMDGPUOperand::CreateImm(this, AttrChan, SChan,
4750 AMDGPUOperand::ImmTyAttrChan));
4751 return MatchOperand_Success;
4752}
4753
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00004754void AMDGPUAsmParser::errorExpTgt() {
4755 Error(Parser.getTok().getLoc(), "invalid exp target");
4756}
4757
4758OperandMatchResultTy AMDGPUAsmParser::parseExpTgtImpl(StringRef Str,
4759 uint8_t &Val) {
4760 if (Str == "null") {
4761 Val = 9;
4762 return MatchOperand_Success;
4763 }
4764
4765 if (Str.startswith("mrt")) {
4766 Str = Str.drop_front(3);
4767 if (Str == "z") { // == mrtz
4768 Val = 8;
4769 return MatchOperand_Success;
4770 }
4771
4772 if (Str.getAsInteger(10, Val))
4773 return MatchOperand_ParseFail;
4774
4775 if (Val > 7)
4776 errorExpTgt();
4777
4778 return MatchOperand_Success;
4779 }
4780
4781 if (Str.startswith("pos")) {
4782 Str = Str.drop_front(3);
4783 if (Str.getAsInteger(10, Val))
4784 return MatchOperand_ParseFail;
4785
Stanislav Mekhanoshin1dbf7212019-05-08 21:23:37 +00004786 if (Val > 4 || (Val == 4 && !isGFX10()))
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00004787 errorExpTgt();
4788
4789 Val += 12;
4790 return MatchOperand_Success;
4791 }
4792
Stanislav Mekhanoshin1dbf7212019-05-08 21:23:37 +00004793 if (isGFX10() && Str == "prim") {
4794 Val = 20;
4795 return MatchOperand_Success;
4796 }
4797
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00004798 if (Str.startswith("param")) {
4799 Str = Str.drop_front(5);
4800 if (Str.getAsInteger(10, Val))
4801 return MatchOperand_ParseFail;
4802
4803 if (Val >= 32)
4804 errorExpTgt();
4805
4806 Val += 32;
4807 return MatchOperand_Success;
4808 }
4809
4810 if (Str.startswith("invalid_target_")) {
4811 Str = Str.drop_front(15);
4812 if (Str.getAsInteger(10, Val))
4813 return MatchOperand_ParseFail;
4814
4815 errorExpTgt();
4816 return MatchOperand_Success;
4817 }
4818
4819 return MatchOperand_NoMatch;
4820}
4821
4822OperandMatchResultTy AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) {
4823 uint8_t Val;
4824 StringRef Str = Parser.getTok().getString();
4825
4826 auto Res = parseExpTgtImpl(Str, Val);
4827 if (Res != MatchOperand_Success)
4828 return Res;
4829
4830 SMLoc S = Parser.getTok().getLoc();
4831 Parser.Lex();
4832
4833 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S,
4834 AMDGPUOperand::ImmTyExpTgt));
4835 return MatchOperand_Success;
4836}
4837
Alex Bradbury58eba092016-11-01 16:32:05 +00004838OperandMatchResultTy
Artem Tamazovebe71ce2016-05-06 17:48:48 +00004839AMDGPUAsmParser::parseSendMsgOp(OperandVector &Operands) {
4840 using namespace llvm::AMDGPU::SendMsg;
4841
4842 int64_t Imm16Val = 0;
4843 SMLoc S = Parser.getTok().getLoc();
4844
4845 switch(getLexer().getKind()) {
4846 default:
4847 return MatchOperand_NoMatch;
4848 case AsmToken::Integer:
4849 // The operand can be an integer value.
4850 if (getParser().parseAbsoluteExpression(Imm16Val))
4851 return MatchOperand_NoMatch;
Artem Tamazov6edc1352016-05-26 17:00:33 +00004852 if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
Artem Tamazovebe71ce2016-05-06 17:48:48 +00004853 Error(S, "invalid immediate: only 16-bit values are legal");
4854 // Do not return error code, but create an imm operand anyway and proceed
4855 // to the next operand, if any. That avoids unneccessary error messages.
4856 }
4857 break;
4858 case AsmToken::Identifier: {
4859 OperandInfoTy Msg(ID_UNKNOWN_);
4860 OperandInfoTy Operation(OP_UNKNOWN_);
Artem Tamazov6edc1352016-05-26 17:00:33 +00004861 int64_t StreamId = STREAM_ID_DEFAULT_;
4862 if (parseSendMsgConstruct(Msg, Operation, StreamId))
4863 return MatchOperand_ParseFail;
Artem Tamazovebe71ce2016-05-06 17:48:48 +00004864 do {
4865 // Validate and encode message ID.
4866 if (! ((ID_INTERRUPT <= Msg.Id && Msg.Id <= ID_GS_DONE)
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00004867 || (Msg.Id == ID_GS_ALLOC_REQ && !isSI() && !isCI() && !isVI())
Artem Tamazovebe71ce2016-05-06 17:48:48 +00004868 || Msg.Id == ID_SYSMSG)) {
4869 if (Msg.IsSymbolic)
4870 Error(S, "invalid/unsupported symbolic name of message");
4871 else
4872 Error(S, "invalid/unsupported code of message");
4873 break;
4874 }
Artem Tamazov6edc1352016-05-26 17:00:33 +00004875 Imm16Val = (Msg.Id << ID_SHIFT_);
Artem Tamazovebe71ce2016-05-06 17:48:48 +00004876 // Validate and encode operation ID.
4877 if (Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) {
4878 if (! (OP_GS_FIRST_ <= Operation.Id && Operation.Id < OP_GS_LAST_)) {
4879 if (Operation.IsSymbolic)
4880 Error(S, "invalid symbolic name of GS_OP");
4881 else
4882 Error(S, "invalid code of GS_OP: only 2-bit values are legal");
4883 break;
4884 }
4885 if (Operation.Id == OP_GS_NOP
4886 && Msg.Id != ID_GS_DONE) {
4887 Error(S, "invalid GS_OP: NOP is for GS_DONE only");
4888 break;
4889 }
4890 Imm16Val |= (Operation.Id << OP_SHIFT_);
4891 }
4892 if (Msg.Id == ID_SYSMSG) {
4893 if (! (OP_SYS_FIRST_ <= Operation.Id && Operation.Id < OP_SYS_LAST_)) {
4894 if (Operation.IsSymbolic)
4895 Error(S, "invalid/unsupported symbolic name of SYSMSG_OP");
4896 else
4897 Error(S, "invalid/unsupported code of SYSMSG_OP");
4898 break;
4899 }
4900 Imm16Val |= (Operation.Id << OP_SHIFT_);
4901 }
4902 // Validate and encode stream ID.
4903 if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
4904 if (! (STREAM_ID_FIRST_ <= StreamId && StreamId < STREAM_ID_LAST_)) {
4905 Error(S, "invalid stream id: only 2-bit values are legal");
4906 break;
4907 }
4908 Imm16Val |= (StreamId << STREAM_ID_SHIFT_);
4909 }
Eugene Zelenko2bc2f332016-12-09 22:06:55 +00004910 } while (false);
Artem Tamazovebe71ce2016-05-06 17:48:48 +00004911 }
4912 break;
4913 }
Sam Kolton1eeb11b2016-09-09 14:44:04 +00004914 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm16Val, S, AMDGPUOperand::ImmTySendMsg));
Artem Tamazovebe71ce2016-05-06 17:48:48 +00004915 return MatchOperand_Success;
4916}
4917
4918bool AMDGPUOperand::isSendMsg() const {
4919 return isImmTy(ImmTySendMsg);
4920}
4921
Tom Stellard45bb48e2015-06-13 03:28:10 +00004922//===----------------------------------------------------------------------===//
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00004923// parser helpers
4924//===----------------------------------------------------------------------===//
4925
4926bool
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00004927AMDGPUAsmParser::isId(const AsmToken &Token, const StringRef Id) const {
4928 return Token.is(AsmToken::Identifier) && Token.getString() == Id;
4929}
4930
4931bool
4932AMDGPUAsmParser::isId(const StringRef Id) const {
4933 return isId(getToken(), Id);
4934}
4935
4936bool
4937AMDGPUAsmParser::isToken(const AsmToken::TokenKind Kind) const {
4938 return getTokenKind() == Kind;
4939}
4940
4941bool
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00004942AMDGPUAsmParser::trySkipId(const StringRef Id) {
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00004943 if (isId(Id)) {
4944 lex();
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00004945 return true;
4946 }
4947 return false;
4948}
4949
4950bool
Dmitry Preobrazhensky198611b2019-05-17 16:04:17 +00004951AMDGPUAsmParser::trySkipId(const StringRef Id, const AsmToken::TokenKind Kind) {
4952 if (isId(Id) && peekToken().is(Kind)) {
4953 lex();
4954 lex();
4955 return true;
4956 }
4957 return false;
4958}
4959
4960bool
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00004961AMDGPUAsmParser::trySkipToken(const AsmToken::TokenKind Kind) {
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00004962 if (isToken(Kind)) {
4963 lex();
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00004964 return true;
4965 }
4966 return false;
4967}
4968
4969bool
4970AMDGPUAsmParser::skipToken(const AsmToken::TokenKind Kind,
4971 const StringRef ErrMsg) {
4972 if (!trySkipToken(Kind)) {
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00004973 Error(getLoc(), ErrMsg);
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00004974 return false;
4975 }
4976 return true;
4977}
4978
4979bool
4980AMDGPUAsmParser::parseExpr(int64_t &Imm) {
4981 return !getParser().parseAbsoluteExpression(Imm);
4982}
4983
4984bool
4985AMDGPUAsmParser::parseString(StringRef &Val, const StringRef ErrMsg) {
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00004986 if (isToken(AsmToken::String)) {
4987 Val = getToken().getStringContents();
4988 lex();
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00004989 return true;
4990 } else {
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00004991 Error(getLoc(), ErrMsg);
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00004992 return false;
4993 }
4994}
4995
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00004996AsmToken
4997AMDGPUAsmParser::getToken() const {
4998 return Parser.getTok();
4999}
5000
5001AsmToken
5002AMDGPUAsmParser::peekToken() {
5003 return getLexer().peekTok();
5004}
5005
Dmitry Preobrazhenskye2707f52019-04-22 14:35:47 +00005006void
5007AMDGPUAsmParser::peekTokens(MutableArrayRef<AsmToken> Tokens) {
5008 auto TokCount = getLexer().peekTokens(Tokens);
5009
5010 for (auto Idx = TokCount; Idx < Tokens.size(); ++Idx)
5011 Tokens[Idx] = AsmToken(AsmToken::Error, "");
5012}
5013
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00005014AsmToken::TokenKind
5015AMDGPUAsmParser::getTokenKind() const {
5016 return getLexer().getKind();
5017}
5018
5019SMLoc
5020AMDGPUAsmParser::getLoc() const {
5021 return getToken().getLoc();
5022}
5023
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00005024StringRef
5025AMDGPUAsmParser::getTokenStr() const {
5026 return getToken().getString();
5027}
5028
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00005029void
5030AMDGPUAsmParser::lex() {
5031 Parser.Lex();
5032}
5033
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00005034//===----------------------------------------------------------------------===//
5035// swizzle
5036//===----------------------------------------------------------------------===//
5037
5038LLVM_READNONE
5039static unsigned
5040encodeBitmaskPerm(const unsigned AndMask,
5041 const unsigned OrMask,
5042 const unsigned XorMask) {
5043 using namespace llvm::AMDGPU::Swizzle;
5044
5045 return BITMASK_PERM_ENC |
5046 (AndMask << BITMASK_AND_SHIFT) |
5047 (OrMask << BITMASK_OR_SHIFT) |
5048 (XorMask << BITMASK_XOR_SHIFT);
5049}
5050
5051bool
5052AMDGPUAsmParser::parseSwizzleOperands(const unsigned OpNum, int64_t* Op,
5053 const unsigned MinVal,
5054 const unsigned MaxVal,
5055 const StringRef ErrMsg) {
5056 for (unsigned i = 0; i < OpNum; ++i) {
5057 if (!skipToken(AsmToken::Comma, "expected a comma")){
5058 return false;
5059 }
5060 SMLoc ExprLoc = Parser.getTok().getLoc();
5061 if (!parseExpr(Op[i])) {
5062 return false;
5063 }
5064 if (Op[i] < MinVal || Op[i] > MaxVal) {
5065 Error(ExprLoc, ErrMsg);
5066 return false;
5067 }
5068 }
5069
5070 return true;
5071}
5072
5073bool
5074AMDGPUAsmParser::parseSwizzleQuadPerm(int64_t &Imm) {
5075 using namespace llvm::AMDGPU::Swizzle;
5076
5077 int64_t Lane[LANE_NUM];
5078 if (parseSwizzleOperands(LANE_NUM, Lane, 0, LANE_MAX,
5079 "expected a 2-bit lane id")) {
5080 Imm = QUAD_PERM_ENC;
Stanislav Mekhanoshin266f1572019-03-11 16:49:32 +00005081 for (unsigned I = 0; I < LANE_NUM; ++I) {
5082 Imm |= Lane[I] << (LANE_SHIFT * I);
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00005083 }
5084 return true;
5085 }
5086 return false;
5087}
5088
5089bool
5090AMDGPUAsmParser::parseSwizzleBroadcast(int64_t &Imm) {
5091 using namespace llvm::AMDGPU::Swizzle;
5092
5093 SMLoc S = Parser.getTok().getLoc();
5094 int64_t GroupSize;
5095 int64_t LaneIdx;
5096
5097 if (!parseSwizzleOperands(1, &GroupSize,
5098 2, 32,
5099 "group size must be in the interval [2,32]")) {
5100 return false;
5101 }
5102 if (!isPowerOf2_64(GroupSize)) {
5103 Error(S, "group size must be a power of two");
5104 return false;
5105 }
5106 if (parseSwizzleOperands(1, &LaneIdx,
5107 0, GroupSize - 1,
5108 "lane id must be in the interval [0,group size - 1]")) {
5109 Imm = encodeBitmaskPerm(BITMASK_MAX - GroupSize + 1, LaneIdx, 0);
5110 return true;
5111 }
5112 return false;
5113}
5114
5115bool
5116AMDGPUAsmParser::parseSwizzleReverse(int64_t &Imm) {
5117 using namespace llvm::AMDGPU::Swizzle;
5118
5119 SMLoc S = Parser.getTok().getLoc();
5120 int64_t GroupSize;
5121
5122 if (!parseSwizzleOperands(1, &GroupSize,
5123 2, 32, "group size must be in the interval [2,32]")) {
5124 return false;
5125 }
5126 if (!isPowerOf2_64(GroupSize)) {
5127 Error(S, "group size must be a power of two");
5128 return false;
5129 }
5130
5131 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize - 1);
5132 return true;
5133}
5134
5135bool
5136AMDGPUAsmParser::parseSwizzleSwap(int64_t &Imm) {
5137 using namespace llvm::AMDGPU::Swizzle;
5138
5139 SMLoc S = Parser.getTok().getLoc();
5140 int64_t GroupSize;
5141
5142 if (!parseSwizzleOperands(1, &GroupSize,
5143 1, 16, "group size must be in the interval [1,16]")) {
5144 return false;
5145 }
5146 if (!isPowerOf2_64(GroupSize)) {
5147 Error(S, "group size must be a power of two");
5148 return false;
5149 }
5150
5151 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize);
5152 return true;
5153}
5154
5155bool
5156AMDGPUAsmParser::parseSwizzleBitmaskPerm(int64_t &Imm) {
5157 using namespace llvm::AMDGPU::Swizzle;
5158
5159 if (!skipToken(AsmToken::Comma, "expected a comma")) {
5160 return false;
5161 }
5162
5163 StringRef Ctl;
5164 SMLoc StrLoc = Parser.getTok().getLoc();
5165 if (!parseString(Ctl)) {
5166 return false;
5167 }
5168 if (Ctl.size() != BITMASK_WIDTH) {
5169 Error(StrLoc, "expected a 5-character mask");
5170 return false;
5171 }
5172
5173 unsigned AndMask = 0;
5174 unsigned OrMask = 0;
5175 unsigned XorMask = 0;
5176
5177 for (size_t i = 0; i < Ctl.size(); ++i) {
5178 unsigned Mask = 1 << (BITMASK_WIDTH - 1 - i);
5179 switch(Ctl[i]) {
5180 default:
5181 Error(StrLoc, "invalid mask");
5182 return false;
5183 case '0':
5184 break;
5185 case '1':
5186 OrMask |= Mask;
5187 break;
5188 case 'p':
5189 AndMask |= Mask;
5190 break;
5191 case 'i':
5192 AndMask |= Mask;
5193 XorMask |= Mask;
5194 break;
5195 }
5196 }
5197
5198 Imm = encodeBitmaskPerm(AndMask, OrMask, XorMask);
5199 return true;
5200}
5201
5202bool
5203AMDGPUAsmParser::parseSwizzleOffset(int64_t &Imm) {
5204
5205 SMLoc OffsetLoc = Parser.getTok().getLoc();
5206
5207 if (!parseExpr(Imm)) {
5208 return false;
5209 }
5210 if (!isUInt<16>(Imm)) {
5211 Error(OffsetLoc, "expected a 16-bit offset");
5212 return false;
5213 }
5214 return true;
5215}
5216
5217bool
5218AMDGPUAsmParser::parseSwizzleMacro(int64_t &Imm) {
5219 using namespace llvm::AMDGPU::Swizzle;
5220
5221 if (skipToken(AsmToken::LParen, "expected a left parentheses")) {
5222
5223 SMLoc ModeLoc = Parser.getTok().getLoc();
5224 bool Ok = false;
5225
5226 if (trySkipId(IdSymbolic[ID_QUAD_PERM])) {
5227 Ok = parseSwizzleQuadPerm(Imm);
5228 } else if (trySkipId(IdSymbolic[ID_BITMASK_PERM])) {
5229 Ok = parseSwizzleBitmaskPerm(Imm);
5230 } else if (trySkipId(IdSymbolic[ID_BROADCAST])) {
5231 Ok = parseSwizzleBroadcast(Imm);
5232 } else if (trySkipId(IdSymbolic[ID_SWAP])) {
5233 Ok = parseSwizzleSwap(Imm);
5234 } else if (trySkipId(IdSymbolic[ID_REVERSE])) {
5235 Ok = parseSwizzleReverse(Imm);
5236 } else {
5237 Error(ModeLoc, "expected a swizzle mode");
5238 }
5239
5240 return Ok && skipToken(AsmToken::RParen, "expected a closing parentheses");
5241 }
5242
5243 return false;
5244}
5245
5246OperandMatchResultTy
5247AMDGPUAsmParser::parseSwizzleOp(OperandVector &Operands) {
5248 SMLoc S = Parser.getTok().getLoc();
5249 int64_t Imm = 0;
5250
5251 if (trySkipId("offset")) {
5252
5253 bool Ok = false;
5254 if (skipToken(AsmToken::Colon, "expected a colon")) {
5255 if (trySkipId("swizzle")) {
5256 Ok = parseSwizzleMacro(Imm);
5257 } else {
5258 Ok = parseSwizzleOffset(Imm);
5259 }
5260 }
5261
5262 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTySwizzle));
5263
5264 return Ok? MatchOperand_Success : MatchOperand_ParseFail;
5265 } else {
Dmitry Preobrazhenskyc5b0c172017-12-22 17:13:28 +00005266 // Swizzle "offset" operand is optional.
5267 // If it is omitted, try parsing other optional operands.
Dmitry Preobrazhensky414e0532017-12-29 13:55:11 +00005268 return parseOptionalOpr(Operands);
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00005269 }
5270}
5271
5272bool
5273AMDGPUOperand::isSwizzle() const {
5274 return isImmTy(ImmTySwizzle);
5275}
5276
5277//===----------------------------------------------------------------------===//
Dmitry Preobrazhenskyef920352019-02-27 13:12:12 +00005278// VGPR Index Mode
5279//===----------------------------------------------------------------------===//
5280
5281int64_t AMDGPUAsmParser::parseGPRIdxMacro() {
5282
5283 using namespace llvm::AMDGPU::VGPRIndexMode;
5284
5285 if (trySkipToken(AsmToken::RParen)) {
5286 return OFF;
5287 }
5288
5289 int64_t Imm = 0;
5290
5291 while (true) {
5292 unsigned Mode = 0;
5293 SMLoc S = Parser.getTok().getLoc();
5294
5295 for (unsigned ModeId = ID_MIN; ModeId <= ID_MAX; ++ModeId) {
5296 if (trySkipId(IdSymbolic[ModeId])) {
5297 Mode = 1 << ModeId;
5298 break;
5299 }
5300 }
5301
5302 if (Mode == 0) {
5303 Error(S, (Imm == 0)?
5304 "expected a VGPR index mode or a closing parenthesis" :
5305 "expected a VGPR index mode");
5306 break;
5307 }
5308
5309 if (Imm & Mode) {
5310 Error(S, "duplicate VGPR index mode");
5311 break;
5312 }
5313 Imm |= Mode;
5314
5315 if (trySkipToken(AsmToken::RParen))
5316 break;
5317 if (!skipToken(AsmToken::Comma,
5318 "expected a comma or a closing parenthesis"))
5319 break;
5320 }
5321
5322 return Imm;
5323}
5324
5325OperandMatchResultTy
5326AMDGPUAsmParser::parseGPRIdxMode(OperandVector &Operands) {
5327
5328 int64_t Imm = 0;
5329 SMLoc S = Parser.getTok().getLoc();
5330
5331 if (getLexer().getKind() == AsmToken::Identifier &&
5332 Parser.getTok().getString() == "gpr_idx" &&
5333 getLexer().peekTok().is(AsmToken::LParen)) {
5334
5335 Parser.Lex();
5336 Parser.Lex();
5337
5338 // If parse failed, trigger an error but do not return error code
5339 // to avoid excessive error messages.
5340 Imm = parseGPRIdxMacro();
5341
5342 } else {
5343 if (getParser().parseAbsoluteExpression(Imm))
5344 return MatchOperand_NoMatch;
5345 if (Imm < 0 || !isUInt<4>(Imm)) {
5346 Error(S, "invalid immediate: only 4-bit values are legal");
5347 }
5348 }
5349
5350 Operands.push_back(
5351 AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTyGprIdxMode));
5352 return MatchOperand_Success;
5353}
5354
5355bool AMDGPUOperand::isGPRIdxMode() const {
5356 return isImmTy(ImmTyGprIdxMode);
5357}
5358
5359//===----------------------------------------------------------------------===//
Tom Stellard45bb48e2015-06-13 03:28:10 +00005360// sopp branch targets
5361//===----------------------------------------------------------------------===//
5362
Alex Bradbury58eba092016-11-01 16:32:05 +00005363OperandMatchResultTy
Tom Stellard45bb48e2015-06-13 03:28:10 +00005364AMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) {
5365 SMLoc S = Parser.getTok().getLoc();
5366
5367 switch (getLexer().getKind()) {
5368 default: return MatchOperand_ParseFail;
5369 case AsmToken::Integer: {
5370 int64_t Imm;
5371 if (getParser().parseAbsoluteExpression(Imm))
5372 return MatchOperand_ParseFail;
Sam Kolton1eeb11b2016-09-09 14:44:04 +00005373 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S));
Tom Stellard45bb48e2015-06-13 03:28:10 +00005374 return MatchOperand_Success;
5375 }
5376
5377 case AsmToken::Identifier:
Sam Kolton1eeb11b2016-09-09 14:44:04 +00005378 Operands.push_back(AMDGPUOperand::CreateExpr(this,
Tom Stellard45bb48e2015-06-13 03:28:10 +00005379 MCSymbolRefExpr::create(getContext().getOrCreateSymbol(
5380 Parser.getTok().getString()), getContext()), S));
5381 Parser.Lex();
5382 return MatchOperand_Success;
5383 }
5384}
5385
5386//===----------------------------------------------------------------------===//
Tom Stellard45bb48e2015-06-13 03:28:10 +00005387// mubuf
5388//===----------------------------------------------------------------------===//
5389
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00005390AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDLC() const {
5391 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDLC);
5392}
5393
Sam Kolton5f10a132016-05-06 11:31:17 +00005394AMDGPUOperand::Ptr AMDGPUAsmParser::defaultGLC() const {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00005395 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyGLC);
Sam Kolton5f10a132016-05-06 11:31:17 +00005396}
5397
5398AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSLC() const {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00005399 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTySLC);
Sam Kolton5f10a132016-05-06 11:31:17 +00005400}
5401
Artem Tamazov8ce1f712016-05-19 12:22:39 +00005402void AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst,
5403 const OperandVector &Operands,
Dmitry Preobrazhenskyd98c97b2018-03-12 17:29:24 +00005404 bool IsAtomic,
5405 bool IsAtomicReturn,
5406 bool IsLds) {
5407 bool IsLdsOpcode = IsLds;
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +00005408 bool HasLdsModifier = false;
Nikolay Haustov2e4c7292016-02-25 10:58:54 +00005409 OptionalImmIndexMap OptionalIdx;
Artem Tamazov8ce1f712016-05-19 12:22:39 +00005410 assert(IsAtomicReturn ? IsAtomic : true);
Dmitry Preobrazhensky7f335742019-03-29 12:16:04 +00005411 unsigned FirstOperandIdx = 1;
Tom Stellard45bb48e2015-06-13 03:28:10 +00005412
Dmitry Preobrazhensky7f335742019-03-29 12:16:04 +00005413 for (unsigned i = FirstOperandIdx, e = Operands.size(); i != e; ++i) {
Tom Stellard45bb48e2015-06-13 03:28:10 +00005414 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
5415
5416 // Add the register arguments
5417 if (Op.isReg()) {
5418 Op.addRegOperands(Inst, 1);
Dmitry Preobrazhensky7f335742019-03-29 12:16:04 +00005419 // Insert a tied src for atomic return dst.
5420 // This cannot be postponed as subsequent calls to
5421 // addImmOperands rely on correct number of MC operands.
5422 if (IsAtomicReturn && i == FirstOperandIdx)
5423 Op.addRegOperands(Inst, 1);
Tom Stellard45bb48e2015-06-13 03:28:10 +00005424 continue;
5425 }
5426
5427 // Handle the case where soffset is an immediate
5428 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
5429 Op.addImmOperands(Inst, 1);
5430 continue;
5431 }
5432
Stanislav Mekhanoshina224f682019-05-01 16:11:11 +00005433 HasLdsModifier |= Op.isLDS();
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +00005434
Tom Stellard45bb48e2015-06-13 03:28:10 +00005435 // Handle tokens like 'offen' which are sometimes hard-coded into the
5436 // asm string. There are no MCInst operands for these.
5437 if (Op.isToken()) {
5438 continue;
5439 }
5440 assert(Op.isImm());
5441
5442 // Handle optional arguments
5443 OptionalIdx[Op.getImmTy()] = i;
5444 }
5445
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +00005446 // This is a workaround for an llvm quirk which may result in an
5447 // incorrect instruction selection. Lds and non-lds versions of
5448 // MUBUF instructions are identical except that lds versions
5449 // have mandatory 'lds' modifier. However this modifier follows
5450 // optional modifiers and llvm asm matcher regards this 'lds'
5451 // modifier as an optional one. As a result, an lds version
5452 // of opcode may be selected even if it has no 'lds' modifier.
Dmitry Preobrazhenskyd98c97b2018-03-12 17:29:24 +00005453 if (IsLdsOpcode && !HasLdsModifier) {
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +00005454 int NoLdsOpcode = AMDGPU::getMUBUFNoLdsInst(Inst.getOpcode());
5455 if (NoLdsOpcode != -1) { // Got lds version - correct it.
5456 Inst.setOpcode(NoLdsOpcode);
Dmitry Preobrazhenskyd98c97b2018-03-12 17:29:24 +00005457 IsLdsOpcode = false;
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +00005458 }
5459 }
5460
Nikolay Haustov2e4c7292016-02-25 10:58:54 +00005461 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
Artem Tamazov8ce1f712016-05-19 12:22:39 +00005462 if (!IsAtomic) { // glc is hard-coded.
5463 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
5464 }
Nikolay Haustov2e4c7292016-02-25 10:58:54 +00005465 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +00005466
Dmitry Preobrazhenskyd98c97b2018-03-12 17:29:24 +00005467 if (!IsLdsOpcode) { // tfe is not legal with lds opcodes
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +00005468 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
5469 }
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00005470
5471 if (isGFX10())
5472 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDLC);
Tom Stellard45bb48e2015-06-13 03:28:10 +00005473}
5474
David Stuttard70e8bc12017-06-22 16:29:22 +00005475void AMDGPUAsmParser::cvtMtbuf(MCInst &Inst, const OperandVector &Operands) {
5476 OptionalImmIndexMap OptionalIdx;
5477
5478 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
5479 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
5480
5481 // Add the register arguments
5482 if (Op.isReg()) {
5483 Op.addRegOperands(Inst, 1);
5484 continue;
5485 }
5486
5487 // Handle the case where soffset is an immediate
5488 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
5489 Op.addImmOperands(Inst, 1);
5490 continue;
5491 }
5492
5493 // Handle tokens like 'offen' which are sometimes hard-coded into the
5494 // asm string. There are no MCInst operands for these.
5495 if (Op.isToken()) {
5496 continue;
5497 }
5498 assert(Op.isImm());
5499
5500 // Handle optional arguments
5501 OptionalIdx[Op.getImmTy()] = i;
5502 }
5503
5504 addOptionalImmOperand(Inst, Operands, OptionalIdx,
5505 AMDGPUOperand::ImmTyOffset);
Tim Renouf35484c92018-08-21 11:06:05 +00005506 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyFORMAT);
David Stuttard70e8bc12017-06-22 16:29:22 +00005507 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
5508 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
5509 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00005510
5511 if (isGFX10())
5512 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDLC);
David Stuttard70e8bc12017-06-22 16:29:22 +00005513}
5514
Tom Stellard45bb48e2015-06-13 03:28:10 +00005515//===----------------------------------------------------------------------===//
5516// mimg
5517//===----------------------------------------------------------------------===//
5518
Sam Kolton10ac2fd2017-07-07 15:21:52 +00005519void AMDGPUAsmParser::cvtMIMG(MCInst &Inst, const OperandVector &Operands,
5520 bool IsAtomic) {
Sam Kolton1bdcef72016-05-23 09:59:02 +00005521 unsigned I = 1;
5522 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
5523 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
5524 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
5525 }
5526
Sam Kolton10ac2fd2017-07-07 15:21:52 +00005527 if (IsAtomic) {
5528 // Add src, same as dst
Dmitry Preobrazhensky0e074e32018-01-19 13:49:53 +00005529 assert(Desc.getNumDefs() == 1);
5530 ((AMDGPUOperand &)*Operands[I - 1]).addRegOperands(Inst, 1);
Sam Kolton10ac2fd2017-07-07 15:21:52 +00005531 }
5532
Sam Kolton1bdcef72016-05-23 09:59:02 +00005533 OptionalImmIndexMap OptionalIdx;
5534
5535 for (unsigned E = Operands.size(); I != E; ++I) {
5536 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
5537
5538 // Add the register arguments
Dmitry Preobrazhensky0e074e32018-01-19 13:49:53 +00005539 if (Op.isReg()) {
5540 Op.addRegOperands(Inst, 1);
Sam Kolton1bdcef72016-05-23 09:59:02 +00005541 } else if (Op.isImmModifier()) {
5542 OptionalIdx[Op.getImmTy()] = I;
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00005543 } else if (!Op.isToken()) {
Matt Arsenault92b355b2016-11-15 19:34:37 +00005544 llvm_unreachable("unexpected operand type");
Sam Kolton1bdcef72016-05-23 09:59:02 +00005545 }
5546 }
5547
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00005548 bool IsGFX10 = isGFX10();
5549
Sam Kolton1bdcef72016-05-23 09:59:02 +00005550 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00005551 if (IsGFX10)
5552 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDim, -1);
Sam Kolton1bdcef72016-05-23 09:59:02 +00005553 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00005554 if (IsGFX10)
5555 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDLC);
Sam Kolton1bdcef72016-05-23 09:59:02 +00005556 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
Dmitry Preobrazhensky0e074e32018-01-19 13:49:53 +00005557 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
Ryan Taylor1f334d02018-08-28 15:07:30 +00005558 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128A16);
Sam Kolton1bdcef72016-05-23 09:59:02 +00005559 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
5560 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00005561 if (!IsGFX10)
5562 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
Nicolai Haehnlef2674312018-06-21 13:36:01 +00005563 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyD16);
Sam Kolton1bdcef72016-05-23 09:59:02 +00005564}
5565
5566void AMDGPUAsmParser::cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands) {
Sam Kolton10ac2fd2017-07-07 15:21:52 +00005567 cvtMIMG(Inst, Operands, true);
Sam Kolton1bdcef72016-05-23 09:59:02 +00005568}
5569
Tom Stellard45bb48e2015-06-13 03:28:10 +00005570//===----------------------------------------------------------------------===//
Tom Stellard217361c2015-08-06 19:28:38 +00005571// smrd
5572//===----------------------------------------------------------------------===//
5573
Artem Tamazov54bfd542016-10-31 16:07:39 +00005574bool AMDGPUOperand::isSMRDOffset8() const {
Tom Stellard217361c2015-08-06 19:28:38 +00005575 return isImm() && isUInt<8>(getImm());
5576}
5577
Artem Tamazov54bfd542016-10-31 16:07:39 +00005578bool AMDGPUOperand::isSMRDOffset20() const {
5579 return isImm() && isUInt<20>(getImm());
5580}
5581
Tom Stellard217361c2015-08-06 19:28:38 +00005582bool AMDGPUOperand::isSMRDLiteralOffset() const {
5583 // 32-bit literals are only supported on CI and we only want to use them
5584 // when the offset is > 8-bits.
5585 return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm());
5586}
5587
Artem Tamazov54bfd542016-10-31 16:07:39 +00005588AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset8() const {
5589 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
5590}
5591
5592AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset20() const {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00005593 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
Sam Kolton5f10a132016-05-06 11:31:17 +00005594}
5595
5596AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDLiteralOffset() const {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00005597 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
Sam Kolton5f10a132016-05-06 11:31:17 +00005598}
5599
Matt Arsenaultfd023142017-06-12 15:55:58 +00005600AMDGPUOperand::Ptr AMDGPUAsmParser::defaultOffsetU12() const {
5601 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
5602}
5603
Matt Arsenault9698f1c2017-06-20 19:54:14 +00005604AMDGPUOperand::Ptr AMDGPUAsmParser::defaultOffsetS13() const {
5605 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
5606}
5607
Tom Stellard217361c2015-08-06 19:28:38 +00005608//===----------------------------------------------------------------------===//
Tom Stellard45bb48e2015-06-13 03:28:10 +00005609// vop3
5610//===----------------------------------------------------------------------===//
5611
5612static bool ConvertOmodMul(int64_t &Mul) {
5613 if (Mul != 1 && Mul != 2 && Mul != 4)
5614 return false;
5615
5616 Mul >>= 1;
5617 return true;
5618}
5619
5620static bool ConvertOmodDiv(int64_t &Div) {
5621 if (Div == 1) {
5622 Div = 0;
5623 return true;
5624 }
5625
5626 if (Div == 2) {
5627 Div = 3;
5628 return true;
5629 }
5630
5631 return false;
5632}
5633
Nikolay Haustov4f672a32016-04-29 09:02:30 +00005634static bool ConvertBoundCtrl(int64_t &BoundCtrl) {
5635 if (BoundCtrl == 0) {
5636 BoundCtrl = 1;
Tom Stellard45bb48e2015-06-13 03:28:10 +00005637 return true;
Matt Arsenault12c53892016-11-15 19:58:54 +00005638 }
5639
5640 if (BoundCtrl == -1) {
Nikolay Haustov4f672a32016-04-29 09:02:30 +00005641 BoundCtrl = 0;
Tom Stellard45bb48e2015-06-13 03:28:10 +00005642 return true;
Tom Stellard45bb48e2015-06-13 03:28:10 +00005643 }
Matt Arsenault12c53892016-11-15 19:58:54 +00005644
Tom Stellard45bb48e2015-06-13 03:28:10 +00005645 return false;
5646}
5647
Nikolay Haustov4f672a32016-04-29 09:02:30 +00005648// Note: the order in this table matches the order of operands in AsmString.
Sam Kolton11de3702016-05-24 12:38:33 +00005649static const OptionalOperand AMDGPUOptionalOperandTable[] = {
5650 {"offen", AMDGPUOperand::ImmTyOffen, true, nullptr},
5651 {"idxen", AMDGPUOperand::ImmTyIdxen, true, nullptr},
5652 {"addr64", AMDGPUOperand::ImmTyAddr64, true, nullptr},
5653 {"offset0", AMDGPUOperand::ImmTyOffset0, false, nullptr},
5654 {"offset1", AMDGPUOperand::ImmTyOffset1, false, nullptr},
5655 {"gds", AMDGPUOperand::ImmTyGDS, true, nullptr},
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +00005656 {"lds", AMDGPUOperand::ImmTyLDS, true, nullptr},
Sam Kolton11de3702016-05-24 12:38:33 +00005657 {"offset", AMDGPUOperand::ImmTyOffset, false, nullptr},
Dmitry Preobrazhenskydd2f1c92017-11-24 13:22:38 +00005658 {"inst_offset", AMDGPUOperand::ImmTyInstOffset, false, nullptr},
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00005659 {"dlc", AMDGPUOperand::ImmTyDLC, true, nullptr},
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00005660 {"format", AMDGPUOperand::ImmTyFORMAT, false, nullptr},
Sam Kolton11de3702016-05-24 12:38:33 +00005661 {"glc", AMDGPUOperand::ImmTyGLC, true, nullptr},
5662 {"slc", AMDGPUOperand::ImmTySLC, true, nullptr},
5663 {"tfe", AMDGPUOperand::ImmTyTFE, true, nullptr},
Dmitry Preobrazhensky4f321ae2018-01-29 14:20:42 +00005664 {"d16", AMDGPUOperand::ImmTyD16, true, nullptr},
Dmitry Preobrazhensky50805a02017-08-07 13:14:12 +00005665 {"high", AMDGPUOperand::ImmTyHigh, true, nullptr},
Sam Kolton11de3702016-05-24 12:38:33 +00005666 {"clamp", AMDGPUOperand::ImmTyClampSI, true, nullptr},
5667 {"omod", AMDGPUOperand::ImmTyOModSI, false, ConvertOmodMul},
5668 {"unorm", AMDGPUOperand::ImmTyUNorm, true, nullptr},
5669 {"da", AMDGPUOperand::ImmTyDA, true, nullptr},
Ryan Taylor1f334d02018-08-28 15:07:30 +00005670 {"r128", AMDGPUOperand::ImmTyR128A16, true, nullptr},
5671 {"a16", AMDGPUOperand::ImmTyR128A16, true, nullptr},
Sam Kolton11de3702016-05-24 12:38:33 +00005672 {"lwe", AMDGPUOperand::ImmTyLWE, true, nullptr},
Nicolai Haehnlef2674312018-06-21 13:36:01 +00005673 {"d16", AMDGPUOperand::ImmTyD16, true, nullptr},
Sam Kolton11de3702016-05-24 12:38:33 +00005674 {"dmask", AMDGPUOperand::ImmTyDMask, false, nullptr},
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00005675 {"dim", AMDGPUOperand::ImmTyDim, false, nullptr},
Sam Kolton11de3702016-05-24 12:38:33 +00005676 {"row_mask", AMDGPUOperand::ImmTyDppRowMask, false, nullptr},
5677 {"bank_mask", AMDGPUOperand::ImmTyDppBankMask, false, nullptr},
5678 {"bound_ctrl", AMDGPUOperand::ImmTyDppBoundCtrl, false, ConvertBoundCtrl},
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00005679 {"fi", AMDGPUOperand::ImmTyDppFi, false, nullptr},
Sam Kolton05ef1c92016-06-03 10:27:37 +00005680 {"dst_sel", AMDGPUOperand::ImmTySdwaDstSel, false, nullptr},
5681 {"src0_sel", AMDGPUOperand::ImmTySdwaSrc0Sel, false, nullptr},
5682 {"src1_sel", AMDGPUOperand::ImmTySdwaSrc1Sel, false, nullptr},
Sam Kolton11de3702016-05-24 12:38:33 +00005683 {"dst_unused", AMDGPUOperand::ImmTySdwaDstUnused, false, nullptr},
Dmitry Preobrazhensky9321e8f2017-05-19 13:36:09 +00005684 {"compr", AMDGPUOperand::ImmTyExpCompr, true, nullptr },
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00005685 {"vm", AMDGPUOperand::ImmTyExpVM, true, nullptr},
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00005686 {"op_sel", AMDGPUOperand::ImmTyOpSel, false, nullptr},
5687 {"op_sel_hi", AMDGPUOperand::ImmTyOpSelHi, false, nullptr},
5688 {"neg_lo", AMDGPUOperand::ImmTyNegLo, false, nullptr},
5689 {"neg_hi", AMDGPUOperand::ImmTyNegHi, false, nullptr}
Nikolay Haustov4f672a32016-04-29 09:02:30 +00005690};
Tom Stellard45bb48e2015-06-13 03:28:10 +00005691
Alex Bradbury58eba092016-11-01 16:32:05 +00005692OperandMatchResultTy AMDGPUAsmParser::parseOptionalOperand(OperandVector &Operands) {
Dmitry Preobrazhensky414e0532017-12-29 13:55:11 +00005693 unsigned size = Operands.size();
5694 assert(size > 0);
5695
5696 OperandMatchResultTy res = parseOptionalOpr(Operands);
5697
5698 // This is a hack to enable hardcoded mandatory operands which follow
5699 // optional operands.
5700 //
5701 // Current design assumes that all operands after the first optional operand
5702 // are also optional. However implementation of some instructions violates
5703 // this rule (see e.g. flat/global atomic which have hardcoded 'glc' operands).
5704 //
5705 // To alleviate this problem, we have to (implicitly) parse extra operands
5706 // to make sure autogenerated parser of custom operands never hit hardcoded
5707 // mandatory operands.
5708
5709 if (size == 1 || ((AMDGPUOperand &)*Operands[size - 1]).isRegKind()) {
5710
5711 // We have parsed the first optional operand.
5712 // Parse as many operands as necessary to skip all mandatory operands.
5713
5714 for (unsigned i = 0; i < MAX_OPR_LOOKAHEAD; ++i) {
5715 if (res != MatchOperand_Success ||
5716 getLexer().is(AsmToken::EndOfStatement)) break;
5717 if (getLexer().is(AsmToken::Comma)) Parser.Lex();
5718 res = parseOptionalOpr(Operands);
5719 }
5720 }
5721
5722 return res;
5723}
5724
5725OperandMatchResultTy AMDGPUAsmParser::parseOptionalOpr(OperandVector &Operands) {
Sam Kolton11de3702016-05-24 12:38:33 +00005726 OperandMatchResultTy res;
5727 for (const OptionalOperand &Op : AMDGPUOptionalOperandTable) {
5728 // try to parse any optional operand here
5729 if (Op.IsBit) {
5730 res = parseNamedBit(Op.Name, Operands, Op.Type);
5731 } else if (Op.Type == AMDGPUOperand::ImmTyOModSI) {
5732 res = parseOModOperand(Operands);
Sam Kolton05ef1c92016-06-03 10:27:37 +00005733 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstSel ||
5734 Op.Type == AMDGPUOperand::ImmTySdwaSrc0Sel ||
5735 Op.Type == AMDGPUOperand::ImmTySdwaSrc1Sel) {
5736 res = parseSDWASel(Operands, Op.Name, Op.Type);
Sam Kolton11de3702016-05-24 12:38:33 +00005737 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstUnused) {
5738 res = parseSDWADstUnused(Operands);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00005739 } else if (Op.Type == AMDGPUOperand::ImmTyOpSel ||
5740 Op.Type == AMDGPUOperand::ImmTyOpSelHi ||
5741 Op.Type == AMDGPUOperand::ImmTyNegLo ||
5742 Op.Type == AMDGPUOperand::ImmTyNegHi) {
5743 res = parseOperandArrayWithPrefix(Op.Name, Operands, Op.Type,
5744 Op.ConvertResult);
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00005745 } else if (Op.Type == AMDGPUOperand::ImmTyDim) {
5746 res = parseDim(Operands);
5747 } else if (Op.Type == AMDGPUOperand::ImmTyFORMAT && !isGFX10()) {
Tim Renouf35484c92018-08-21 11:06:05 +00005748 res = parseDfmtNfmt(Operands);
Sam Kolton11de3702016-05-24 12:38:33 +00005749 } else {
5750 res = parseIntWithPrefix(Op.Name, Operands, Op.Type, Op.ConvertResult);
5751 }
5752 if (res != MatchOperand_NoMatch) {
5753 return res;
Tom Stellard45bb48e2015-06-13 03:28:10 +00005754 }
Tom Stellard45bb48e2015-06-13 03:28:10 +00005755 }
5756 return MatchOperand_NoMatch;
5757}
5758
Matt Arsenault12c53892016-11-15 19:58:54 +00005759OperandMatchResultTy AMDGPUAsmParser::parseOModOperand(OperandVector &Operands) {
Nikolay Haustov4f672a32016-04-29 09:02:30 +00005760 StringRef Name = Parser.getTok().getString();
5761 if (Name == "mul") {
Matt Arsenault12c53892016-11-15 19:58:54 +00005762 return parseIntWithPrefix("mul", Operands,
5763 AMDGPUOperand::ImmTyOModSI, ConvertOmodMul);
Nikolay Haustov4f672a32016-04-29 09:02:30 +00005764 }
Matt Arsenault12c53892016-11-15 19:58:54 +00005765
5766 if (Name == "div") {
5767 return parseIntWithPrefix("div", Operands,
5768 AMDGPUOperand::ImmTyOModSI, ConvertOmodDiv);
5769 }
5770
5771 return MatchOperand_NoMatch;
Nikolay Haustov4f672a32016-04-29 09:02:30 +00005772}
5773
Dmitry Preobrazhenskyabf28392017-07-21 13:54:11 +00005774void AMDGPUAsmParser::cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands) {
5775 cvtVOP3P(Inst, Operands);
5776
5777 int Opc = Inst.getOpcode();
5778
5779 int SrcNum;
5780 const int Ops[] = { AMDGPU::OpName::src0,
5781 AMDGPU::OpName::src1,
5782 AMDGPU::OpName::src2 };
5783 for (SrcNum = 0;
5784 SrcNum < 3 && AMDGPU::getNamedOperandIdx(Opc, Ops[SrcNum]) != -1;
5785 ++SrcNum);
5786 assert(SrcNum > 0);
5787
5788 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
5789 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
5790
5791 if ((OpSel & (1 << SrcNum)) != 0) {
5792 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers);
5793 uint32_t ModVal = Inst.getOperand(ModIdx).getImm();
5794 Inst.getOperand(ModIdx).setImm(ModVal | SISrcMods::DST_OP_SEL);
5795 }
5796}
5797
Sam Koltona3ec5c12016-10-07 14:46:06 +00005798static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum) {
5799 // 1. This operand is input modifiers
5800 return Desc.OpInfo[OpNum].OperandType == AMDGPU::OPERAND_INPUT_MODS
5801 // 2. This is not last operand
5802 && Desc.NumOperands > (OpNum + 1)
5803 // 3. Next operand is register class
5804 && Desc.OpInfo[OpNum + 1].RegClass != -1
5805 // 4. Next register is not tied to any other operand
5806 && Desc.getOperandConstraint(OpNum + 1, MCOI::OperandConstraint::TIED_TO) == -1;
5807}
5808
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00005809void AMDGPUAsmParser::cvtVOP3Interp(MCInst &Inst, const OperandVector &Operands)
5810{
Dmitry Preobrazhensky50805a02017-08-07 13:14:12 +00005811 OptionalImmIndexMap OptionalIdx;
5812 unsigned Opc = Inst.getOpcode();
5813
5814 unsigned I = 1;
5815 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
5816 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
5817 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
5818 }
5819
5820 for (unsigned E = Operands.size(); I != E; ++I) {
5821 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
5822 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
5823 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
5824 } else if (Op.isInterpSlot() ||
5825 Op.isInterpAttr() ||
5826 Op.isAttrChan()) {
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00005827 Inst.addOperand(MCOperand::createImm(Op.getImm()));
Dmitry Preobrazhensky50805a02017-08-07 13:14:12 +00005828 } else if (Op.isImmModifier()) {
5829 OptionalIdx[Op.getImmTy()] = I;
5830 } else {
5831 llvm_unreachable("unhandled operand type");
5832 }
5833 }
5834
5835 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::high) != -1) {
5836 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyHigh);
5837 }
5838
5839 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1) {
5840 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
5841 }
5842
5843 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod) != -1) {
5844 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
5845 }
5846}
5847
Sam Kolton10ac2fd2017-07-07 15:21:52 +00005848void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands,
5849 OptionalImmIndexMap &OptionalIdx) {
5850 unsigned Opc = Inst.getOpcode();
5851
Tom Stellarda90b9522016-02-11 03:28:15 +00005852 unsigned I = 1;
5853 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
Tom Stellarde9934512016-02-11 18:25:26 +00005854 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
Tom Stellarda90b9522016-02-11 03:28:15 +00005855 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
Tom Stellard88e0b252015-10-06 15:57:53 +00005856 }
Tom Stellard45bb48e2015-06-13 03:28:10 +00005857
Sam Kolton10ac2fd2017-07-07 15:21:52 +00005858 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers) != -1) {
5859 // This instruction has src modifiers
5860 for (unsigned E = Operands.size(); I != E; ++I) {
5861 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
5862 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
5863 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
5864 } else if (Op.isImmModifier()) {
5865 OptionalIdx[Op.getImmTy()] = I;
5866 } else if (Op.isRegOrImm()) {
5867 Op.addRegOrImmOperands(Inst, 1);
5868 } else {
5869 llvm_unreachable("unhandled operand type");
5870 }
5871 }
5872 } else {
5873 // No src modifiers
5874 for (unsigned E = Operands.size(); I != E; ++I) {
5875 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
5876 if (Op.isMod()) {
5877 OptionalIdx[Op.getImmTy()] = I;
5878 } else {
5879 Op.addRegOrImmOperands(Inst, 1);
5880 }
Tom Stellard45bb48e2015-06-13 03:28:10 +00005881 }
Tom Stellarda90b9522016-02-11 03:28:15 +00005882 }
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00005883
Sam Kolton10ac2fd2017-07-07 15:21:52 +00005884 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1) {
5885 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
5886 }
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00005887
Sam Kolton10ac2fd2017-07-07 15:21:52 +00005888 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod) != -1) {
5889 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
5890 }
Sam Koltona3ec5c12016-10-07 14:46:06 +00005891
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00005892 // Special case v_mac_{f16, f32} and v_fmac_{f16, f32} (gfx906/gfx10+):
Sam Koltona3ec5c12016-10-07 14:46:06 +00005893 // it has src2 register operand that is tied to dst operand
5894 // we don't allow modifiers for this operand in assembler so src2_modifiers
Matt Arsenault0084adc2018-04-30 19:08:16 +00005895 // should be 0.
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00005896 if (Opc == AMDGPU::V_MAC_F32_e64_gfx6_gfx7 ||
5897 Opc == AMDGPU::V_MAC_F32_e64_gfx10 ||
Matt Arsenault0084adc2018-04-30 19:08:16 +00005898 Opc == AMDGPU::V_MAC_F32_e64_vi ||
5899 Opc == AMDGPU::V_MAC_F16_e64_vi ||
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00005900 Opc == AMDGPU::V_FMAC_F32_e64_gfx10 ||
5901 Opc == AMDGPU::V_FMAC_F32_e64_vi ||
5902 Opc == AMDGPU::V_FMAC_F16_e64_gfx10) {
Sam Koltona3ec5c12016-10-07 14:46:06 +00005903 auto it = Inst.begin();
Sam Kolton10ac2fd2017-07-07 15:21:52 +00005904 std::advance(it, AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2_modifiers));
Sam Koltona3ec5c12016-10-07 14:46:06 +00005905 it = Inst.insert(it, MCOperand::createImm(0)); // no modifiers for src2
5906 ++it;
5907 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
5908 }
Tom Stellard45bb48e2015-06-13 03:28:10 +00005909}
5910
Sam Kolton10ac2fd2017-07-07 15:21:52 +00005911void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) {
Dmitry Preobrazhenskyc512d442017-03-27 15:57:17 +00005912 OptionalImmIndexMap OptionalIdx;
Sam Kolton10ac2fd2017-07-07 15:21:52 +00005913 cvtVOP3(Inst, Operands, OptionalIdx);
Dmitry Preobrazhenskyc512d442017-03-27 15:57:17 +00005914}
5915
Dmitry Preobrazhensky682a6542017-11-17 15:15:40 +00005916void AMDGPUAsmParser::cvtVOP3P(MCInst &Inst,
5917 const OperandVector &Operands) {
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00005918 OptionalImmIndexMap OptIdx;
Dmitry Preobrazhensky682a6542017-11-17 15:15:40 +00005919 const int Opc = Inst.getOpcode();
5920 const MCInstrDesc &Desc = MII.get(Opc);
5921
5922 const bool IsPacked = (Desc.TSFlags & SIInstrFlags::IsPacked) != 0;
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00005923
Sam Kolton10ac2fd2017-07-07 15:21:52 +00005924 cvtVOP3(Inst, Operands, OptIdx);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00005925
Matt Arsenaulte135c4c2017-09-20 20:53:49 +00005926 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in) != -1) {
5927 assert(!IsPacked);
5928 Inst.addOperand(Inst.getOperand(0));
5929 }
5930
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00005931 // FIXME: This is messy. Parse the modifiers as if it was a normal VOP3
5932 // instruction, and then figure out where to actually put the modifiers
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00005933
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00005934 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSel);
Dmitry Preobrazhenskyabf28392017-07-21 13:54:11 +00005935
5936 int OpSelHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel_hi);
5937 if (OpSelHiIdx != -1) {
Matt Arsenaultc8f8cda2017-08-30 22:18:40 +00005938 int DefaultVal = IsPacked ? -1 : 0;
5939 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSelHi,
5940 DefaultVal);
Dmitry Preobrazhenskyabf28392017-07-21 13:54:11 +00005941 }
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00005942
5943 int NegLoIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_lo);
5944 if (NegLoIdx != -1) {
Matt Arsenaultc8f8cda2017-08-30 22:18:40 +00005945 assert(IsPacked);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00005946 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegLo);
5947 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegHi);
5948 }
5949
5950 const int Ops[] = { AMDGPU::OpName::src0,
5951 AMDGPU::OpName::src1,
5952 AMDGPU::OpName::src2 };
5953 const int ModOps[] = { AMDGPU::OpName::src0_modifiers,
5954 AMDGPU::OpName::src1_modifiers,
5955 AMDGPU::OpName::src2_modifiers };
5956
5957 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00005958
5959 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
Dmitry Preobrazhenskyabf28392017-07-21 13:54:11 +00005960 unsigned OpSelHi = 0;
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00005961 unsigned NegLo = 0;
5962 unsigned NegHi = 0;
5963
Dmitry Preobrazhenskyabf28392017-07-21 13:54:11 +00005964 if (OpSelHiIdx != -1) {
5965 OpSelHi = Inst.getOperand(OpSelHiIdx).getImm();
5966 }
5967
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00005968 if (NegLoIdx != -1) {
5969 int NegHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_hi);
5970 NegLo = Inst.getOperand(NegLoIdx).getImm();
5971 NegHi = Inst.getOperand(NegHiIdx).getImm();
5972 }
5973
5974 for (int J = 0; J < 3; ++J) {
5975 int OpIdx = AMDGPU::getNamedOperandIdx(Opc, Ops[J]);
5976 if (OpIdx == -1)
5977 break;
5978
5979 uint32_t ModVal = 0;
5980
5981 if ((OpSel & (1 << J)) != 0)
5982 ModVal |= SISrcMods::OP_SEL_0;
5983
5984 if ((OpSelHi & (1 << J)) != 0)
5985 ModVal |= SISrcMods::OP_SEL_1;
5986
5987 if ((NegLo & (1 << J)) != 0)
5988 ModVal |= SISrcMods::NEG;
5989
5990 if ((NegHi & (1 << J)) != 0)
5991 ModVal |= SISrcMods::NEG_HI;
5992
5993 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
5994
Dmitry Preobrazhenskyb2d24e22017-07-07 14:29:06 +00005995 Inst.getOperand(ModIdx).setImm(Inst.getOperand(ModIdx).getImm() | ModVal);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00005996 }
5997}
5998
Sam Koltondfa29f72016-03-09 12:29:31 +00005999//===----------------------------------------------------------------------===//
6000// dpp
6001//===----------------------------------------------------------------------===//
6002
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006003bool AMDGPUOperand::isDPP8() const {
6004 return isImmTy(ImmTyDPP8);
6005}
6006
Sam Koltondfa29f72016-03-09 12:29:31 +00006007bool AMDGPUOperand::isDPPCtrl() const {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006008 using namespace AMDGPU::DPP;
6009
Sam Koltondfa29f72016-03-09 12:29:31 +00006010 bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm());
6011 if (result) {
6012 int64_t Imm = getImm();
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006013 return (Imm >= DppCtrl::QUAD_PERM_FIRST && Imm <= DppCtrl::QUAD_PERM_LAST) ||
6014 (Imm >= DppCtrl::ROW_SHL_FIRST && Imm <= DppCtrl::ROW_SHL_LAST) ||
6015 (Imm >= DppCtrl::ROW_SHR_FIRST && Imm <= DppCtrl::ROW_SHR_LAST) ||
6016 (Imm >= DppCtrl::ROW_ROR_FIRST && Imm <= DppCtrl::ROW_ROR_LAST) ||
6017 (Imm == DppCtrl::WAVE_SHL1) ||
6018 (Imm == DppCtrl::WAVE_ROL1) ||
6019 (Imm == DppCtrl::WAVE_SHR1) ||
6020 (Imm == DppCtrl::WAVE_ROR1) ||
6021 (Imm == DppCtrl::ROW_MIRROR) ||
6022 (Imm == DppCtrl::ROW_HALF_MIRROR) ||
6023 (Imm == DppCtrl::BCAST15) ||
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006024 (Imm == DppCtrl::BCAST31) ||
6025 (Imm >= DppCtrl::ROW_SHARE_FIRST && Imm <= DppCtrl::ROW_SHARE_LAST) ||
6026 (Imm >= DppCtrl::ROW_XMASK_FIRST && Imm <= DppCtrl::ROW_XMASK_LAST);
Sam Koltondfa29f72016-03-09 12:29:31 +00006027 }
6028 return false;
6029}
6030
Dmitry Preobrazhenskyc7d35a02017-04-26 15:34:19 +00006031bool AMDGPUOperand::isS16Imm() const {
6032 return isImm() && (isInt<16>(getImm()) || isUInt<16>(getImm()));
6033}
6034
6035bool AMDGPUOperand::isU16Imm() const {
6036 return isImm() && isUInt<16>(getImm());
6037}
6038
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00006039OperandMatchResultTy AMDGPUAsmParser::parseDim(OperandVector &Operands) {
6040 if (!isGFX10())
6041 return MatchOperand_NoMatch;
6042
6043 SMLoc S = Parser.getTok().getLoc();
6044
6045 if (getLexer().isNot(AsmToken::Identifier))
6046 return MatchOperand_NoMatch;
6047 if (getLexer().getTok().getString() != "dim")
6048 return MatchOperand_NoMatch;
6049
6050 Parser.Lex();
6051 if (getLexer().isNot(AsmToken::Colon))
6052 return MatchOperand_ParseFail;
6053
6054 Parser.Lex();
6055
6056 // We want to allow "dim:1D" etc., but the initial 1 is tokenized as an
6057 // integer.
6058 std::string Token;
6059 if (getLexer().is(AsmToken::Integer)) {
6060 SMLoc Loc = getLexer().getTok().getEndLoc();
6061 Token = getLexer().getTok().getString();
6062 Parser.Lex();
6063 if (getLexer().getTok().getLoc() != Loc)
6064 return MatchOperand_ParseFail;
6065 }
6066 if (getLexer().isNot(AsmToken::Identifier))
6067 return MatchOperand_ParseFail;
6068 Token += getLexer().getTok().getString();
6069
6070 StringRef DimId = Token;
6071 if (DimId.startswith("SQ_RSRC_IMG_"))
6072 DimId = DimId.substr(12);
6073
6074 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByAsmSuffix(DimId);
6075 if (!DimInfo)
6076 return MatchOperand_ParseFail;
6077
6078 Parser.Lex();
6079
6080 Operands.push_back(AMDGPUOperand::CreateImm(this, DimInfo->Encoding, S,
6081 AMDGPUOperand::ImmTyDim));
6082 return MatchOperand_Success;
6083}
6084
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006085OperandMatchResultTy AMDGPUAsmParser::parseDPP8(OperandVector &Operands) {
6086 SMLoc S = Parser.getTok().getLoc();
6087 StringRef Prefix;
6088
6089 if (getLexer().getKind() == AsmToken::Identifier) {
6090 Prefix = Parser.getTok().getString();
6091 } else {
6092 return MatchOperand_NoMatch;
6093 }
6094
6095 if (Prefix != "dpp8")
6096 return parseDPPCtrl(Operands);
6097 if (!isGFX10())
6098 return MatchOperand_NoMatch;
6099
6100 // dpp8:[%d,%d,%d,%d,%d,%d,%d,%d]
6101
6102 int64_t Sels[8];
6103
6104 Parser.Lex();
6105 if (getLexer().isNot(AsmToken::Colon))
6106 return MatchOperand_ParseFail;
6107
6108 Parser.Lex();
6109 if (getLexer().isNot(AsmToken::LBrac))
6110 return MatchOperand_ParseFail;
6111
6112 Parser.Lex();
6113 if (getParser().parseAbsoluteExpression(Sels[0]))
6114 return MatchOperand_ParseFail;
6115 if (0 > Sels[0] || 7 < Sels[0])
6116 return MatchOperand_ParseFail;
6117
6118 for (size_t i = 1; i < 8; ++i) {
6119 if (getLexer().isNot(AsmToken::Comma))
6120 return MatchOperand_ParseFail;
6121
6122 Parser.Lex();
6123 if (getParser().parseAbsoluteExpression(Sels[i]))
6124 return MatchOperand_ParseFail;
6125 if (0 > Sels[i] || 7 < Sels[i])
6126 return MatchOperand_ParseFail;
6127 }
6128
6129 if (getLexer().isNot(AsmToken::RBrac))
6130 return MatchOperand_ParseFail;
6131 Parser.Lex();
6132
6133 unsigned DPP8 = 0;
6134 for (size_t i = 0; i < 8; ++i)
6135 DPP8 |= (Sels[i] << (i * 3));
6136
6137 Operands.push_back(AMDGPUOperand::CreateImm(this, DPP8, S, AMDGPUOperand::ImmTyDPP8));
6138 return MatchOperand_Success;
6139}
6140
Alex Bradbury58eba092016-11-01 16:32:05 +00006141OperandMatchResultTy
Sam Kolton11de3702016-05-24 12:38:33 +00006142AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006143 using namespace AMDGPU::DPP;
6144
Sam Koltondfa29f72016-03-09 12:29:31 +00006145 SMLoc S = Parser.getTok().getLoc();
6146 StringRef Prefix;
6147 int64_t Int;
Sam Koltondfa29f72016-03-09 12:29:31 +00006148
Sam Koltona74cd522016-03-18 15:35:51 +00006149 if (getLexer().getKind() == AsmToken::Identifier) {
6150 Prefix = Parser.getTok().getString();
6151 } else {
6152 return MatchOperand_NoMatch;
6153 }
6154
6155 if (Prefix == "row_mirror") {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006156 Int = DppCtrl::ROW_MIRROR;
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006157 Parser.Lex();
Sam Koltona74cd522016-03-18 15:35:51 +00006158 } else if (Prefix == "row_half_mirror") {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006159 Int = DppCtrl::ROW_HALF_MIRROR;
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006160 Parser.Lex();
Sam Koltona74cd522016-03-18 15:35:51 +00006161 } else {
Sam Kolton201398e2016-04-21 13:14:24 +00006162 // Check to prevent parseDPPCtrlOps from eating invalid tokens
6163 if (Prefix != "quad_perm"
6164 && Prefix != "row_shl"
6165 && Prefix != "row_shr"
6166 && Prefix != "row_ror"
6167 && Prefix != "wave_shl"
6168 && Prefix != "wave_rol"
6169 && Prefix != "wave_shr"
6170 && Prefix != "wave_ror"
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006171 && Prefix != "row_bcast"
6172 && Prefix != "row_share"
6173 && Prefix != "row_xmask") {
Sam Kolton11de3702016-05-24 12:38:33 +00006174 return MatchOperand_NoMatch;
Sam Kolton201398e2016-04-21 13:14:24 +00006175 }
6176
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006177 if (!isGFX10() && (Prefix == "row_share" || Prefix == "row_xmask"))
6178 return MatchOperand_NoMatch;
6179
6180 if (!isVI() && !isGFX9() &&
6181 (Prefix == "wave_shl" || Prefix == "wave_shr" ||
6182 Prefix == "wave_rol" || Prefix == "wave_ror" ||
6183 Prefix == "row_bcast"))
6184 return MatchOperand_NoMatch;
6185
Sam Koltona74cd522016-03-18 15:35:51 +00006186 Parser.Lex();
6187 if (getLexer().isNot(AsmToken::Colon))
6188 return MatchOperand_ParseFail;
6189
6190 if (Prefix == "quad_perm") {
6191 // quad_perm:[%d,%d,%d,%d]
Sam Koltondfa29f72016-03-09 12:29:31 +00006192 Parser.Lex();
Sam Koltona74cd522016-03-18 15:35:51 +00006193 if (getLexer().isNot(AsmToken::LBrac))
Sam Koltondfa29f72016-03-09 12:29:31 +00006194 return MatchOperand_ParseFail;
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006195 Parser.Lex();
Sam Koltondfa29f72016-03-09 12:29:31 +00006196
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006197 if (getParser().parseAbsoluteExpression(Int) || !(0 <= Int && Int <=3))
Sam Koltondfa29f72016-03-09 12:29:31 +00006198 return MatchOperand_ParseFail;
6199
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006200 for (int i = 0; i < 3; ++i) {
6201 if (getLexer().isNot(AsmToken::Comma))
6202 return MatchOperand_ParseFail;
6203 Parser.Lex();
Sam Koltondfa29f72016-03-09 12:29:31 +00006204
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006205 int64_t Temp;
6206 if (getParser().parseAbsoluteExpression(Temp) || !(0 <= Temp && Temp <=3))
6207 return MatchOperand_ParseFail;
6208 const int shift = i*2 + 2;
6209 Int += (Temp << shift);
6210 }
Sam Koltona74cd522016-03-18 15:35:51 +00006211
Sam Koltona74cd522016-03-18 15:35:51 +00006212 if (getLexer().isNot(AsmToken::RBrac))
6213 return MatchOperand_ParseFail;
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006214 Parser.Lex();
Sam Koltona74cd522016-03-18 15:35:51 +00006215 } else {
6216 // sel:%d
6217 Parser.Lex();
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006218 if (getParser().parseAbsoluteExpression(Int))
Sam Koltona74cd522016-03-18 15:35:51 +00006219 return MatchOperand_ParseFail;
Sam Koltona74cd522016-03-18 15:35:51 +00006220
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006221 if (Prefix == "row_shl" && 1 <= Int && Int <= 15) {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006222 Int |= DppCtrl::ROW_SHL0;
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006223 } else if (Prefix == "row_shr" && 1 <= Int && Int <= 15) {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006224 Int |= DppCtrl::ROW_SHR0;
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006225 } else if (Prefix == "row_ror" && 1 <= Int && Int <= 15) {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006226 Int |= DppCtrl::ROW_ROR0;
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006227 } else if (Prefix == "wave_shl" && 1 == Int) {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006228 Int = DppCtrl::WAVE_SHL1;
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006229 } else if (Prefix == "wave_rol" && 1 == Int) {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006230 Int = DppCtrl::WAVE_ROL1;
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006231 } else if (Prefix == "wave_shr" && 1 == Int) {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006232 Int = DppCtrl::WAVE_SHR1;
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006233 } else if (Prefix == "wave_ror" && 1 == Int) {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006234 Int = DppCtrl::WAVE_ROR1;
Sam Koltona74cd522016-03-18 15:35:51 +00006235 } else if (Prefix == "row_bcast") {
6236 if (Int == 15) {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006237 Int = DppCtrl::BCAST15;
Sam Koltona74cd522016-03-18 15:35:51 +00006238 } else if (Int == 31) {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006239 Int = DppCtrl::BCAST31;
Sam Kolton7a2a3232016-07-14 14:50:35 +00006240 } else {
6241 return MatchOperand_ParseFail;
Sam Koltona74cd522016-03-18 15:35:51 +00006242 }
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006243 } else if (Prefix == "row_share" && 0 <= Int && Int <= 15) {
6244 Int |= DppCtrl::ROW_SHARE_FIRST;
6245 } else if (Prefix == "row_xmask" && 0 <= Int && Int <= 15) {
6246 Int |= DppCtrl::ROW_XMASK_FIRST;
Sam Koltona74cd522016-03-18 15:35:51 +00006247 } else {
Sam Kolton201398e2016-04-21 13:14:24 +00006248 return MatchOperand_ParseFail;
Sam Koltona74cd522016-03-18 15:35:51 +00006249 }
Sam Koltondfa29f72016-03-09 12:29:31 +00006250 }
Sam Koltondfa29f72016-03-09 12:29:31 +00006251 }
Sam Koltona74cd522016-03-18 15:35:51 +00006252
Sam Kolton1eeb11b2016-09-09 14:44:04 +00006253 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTyDppCtrl));
Sam Koltondfa29f72016-03-09 12:29:31 +00006254 return MatchOperand_Success;
6255}
6256
Sam Kolton5f10a132016-05-06 11:31:17 +00006257AMDGPUOperand::Ptr AMDGPUAsmParser::defaultRowMask() const {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00006258 return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppRowMask);
Sam Koltondfa29f72016-03-09 12:29:31 +00006259}
6260
David Stuttard20ea21c2019-03-12 09:52:58 +00006261AMDGPUOperand::Ptr AMDGPUAsmParser::defaultEndpgmImmOperands() const {
6262 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyEndpgm);
6263}
6264
Sam Kolton5f10a132016-05-06 11:31:17 +00006265AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBankMask() const {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00006266 return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppBankMask);
Sam Koltondfa29f72016-03-09 12:29:31 +00006267}
6268
Sam Kolton5f10a132016-05-06 11:31:17 +00006269AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBoundCtrl() const {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00006270 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDppBoundCtrl);
Sam Kolton5f10a132016-05-06 11:31:17 +00006271}
6272
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006273AMDGPUOperand::Ptr AMDGPUAsmParser::defaultFI() const {
6274 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDppFi);
6275}
6276
6277void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands, bool IsDPP8) {
Sam Koltondfa29f72016-03-09 12:29:31 +00006278 OptionalImmIndexMap OptionalIdx;
6279
6280 unsigned I = 1;
6281 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
6282 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
6283 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
6284 }
6285
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006286 int Fi = 0;
Sam Koltondfa29f72016-03-09 12:29:31 +00006287 for (unsigned E = Operands.size(); I != E; ++I) {
Valery Pykhtin3d9afa22018-11-30 14:21:56 +00006288 auto TiedTo = Desc.getOperandConstraint(Inst.getNumOperands(),
6289 MCOI::TIED_TO);
6290 if (TiedTo != -1) {
6291 assert((unsigned)TiedTo < Inst.getNumOperands());
6292 // handle tied old or src2 for MAC instructions
6293 Inst.addOperand(Inst.getOperand(TiedTo));
6294 }
Sam Koltondfa29f72016-03-09 12:29:31 +00006295 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
6296 // Add the register arguments
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00006297 if (Op.isReg() && Op.getReg() == AMDGPU::VCC) {
Sam Kolton07dbde22017-01-20 10:01:25 +00006298 // VOP2b (v_add_u32, v_sub_u32 ...) dpp use "vcc" token.
Sam Koltone66365e2016-12-27 10:06:42 +00006299 // Skip it.
6300 continue;
Simon Pilgrim6f349d82019-04-29 17:34:26 +00006301 }
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006302
6303 if (IsDPP8) {
6304 if (Op.isDPP8()) {
6305 Op.addImmOperands(Inst, 1);
6306 } else if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
6307 Op.addRegWithFPInputModsOperands(Inst, 2);
6308 } else if (Op.isFI()) {
6309 Fi = Op.getImm();
6310 } else if (Op.isReg()) {
6311 Op.addRegOperands(Inst, 1);
6312 } else {
6313 llvm_unreachable("Invalid operand type");
6314 }
Sam Koltondfa29f72016-03-09 12:29:31 +00006315 } else {
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006316 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
6317 Op.addRegWithFPInputModsOperands(Inst, 2);
6318 } else if (Op.isDPPCtrl()) {
6319 Op.addImmOperands(Inst, 1);
6320 } else if (Op.isImm()) {
6321 // Handle optional arguments
6322 OptionalIdx[Op.getImmTy()] = I;
6323 } else {
6324 llvm_unreachable("Invalid operand type");
6325 }
Sam Koltondfa29f72016-03-09 12:29:31 +00006326 }
6327 }
6328
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006329 if (IsDPP8) {
6330 using namespace llvm::AMDGPU::DPP;
6331 Inst.addOperand(MCOperand::createImm(Fi? DPP8_FI_1 : DPP8_FI_0));
6332 } else {
6333 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf);
6334 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf);
6335 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl);
6336 if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::fi) != -1) {
6337 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppFi);
6338 }
6339 }
Sam Koltondfa29f72016-03-09 12:29:31 +00006340}
Nikolay Haustov5bf46ac12016-03-04 10:39:50 +00006341
Sam Kolton3025e7f2016-04-26 13:33:56 +00006342//===----------------------------------------------------------------------===//
6343// sdwa
6344//===----------------------------------------------------------------------===//
6345
Alex Bradbury58eba092016-11-01 16:32:05 +00006346OperandMatchResultTy
Sam Kolton05ef1c92016-06-03 10:27:37 +00006347AMDGPUAsmParser::parseSDWASel(OperandVector &Operands, StringRef Prefix,
6348 AMDGPUOperand::ImmTy Type) {
Sam Koltona3ec5c12016-10-07 14:46:06 +00006349 using namespace llvm::AMDGPU::SDWA;
6350
Sam Kolton3025e7f2016-04-26 13:33:56 +00006351 SMLoc S = Parser.getTok().getLoc();
6352 StringRef Value;
Alex Bradbury58eba092016-11-01 16:32:05 +00006353 OperandMatchResultTy res;
Matt Arsenault37fefd62016-06-10 02:18:02 +00006354
Sam Kolton05ef1c92016-06-03 10:27:37 +00006355 res = parseStringWithPrefix(Prefix, Value);
6356 if (res != MatchOperand_Success) {
6357 return res;
Sam Kolton3025e7f2016-04-26 13:33:56 +00006358 }
Matt Arsenault37fefd62016-06-10 02:18:02 +00006359
Sam Kolton3025e7f2016-04-26 13:33:56 +00006360 int64_t Int;
6361 Int = StringSwitch<int64_t>(Value)
Sam Koltona3ec5c12016-10-07 14:46:06 +00006362 .Case("BYTE_0", SdwaSel::BYTE_0)
6363 .Case("BYTE_1", SdwaSel::BYTE_1)
6364 .Case("BYTE_2", SdwaSel::BYTE_2)
6365 .Case("BYTE_3", SdwaSel::BYTE_3)
6366 .Case("WORD_0", SdwaSel::WORD_0)
6367 .Case("WORD_1", SdwaSel::WORD_1)
6368 .Case("DWORD", SdwaSel::DWORD)
Sam Kolton3025e7f2016-04-26 13:33:56 +00006369 .Default(0xffffffff);
6370 Parser.Lex(); // eat last token
6371
6372 if (Int == 0xffffffff) {
6373 return MatchOperand_ParseFail;
6374 }
6375
Sam Kolton1eeb11b2016-09-09 14:44:04 +00006376 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, Type));
Sam Kolton3025e7f2016-04-26 13:33:56 +00006377 return MatchOperand_Success;
6378}
6379
Alex Bradbury58eba092016-11-01 16:32:05 +00006380OperandMatchResultTy
Sam Kolton3025e7f2016-04-26 13:33:56 +00006381AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) {
Sam Koltona3ec5c12016-10-07 14:46:06 +00006382 using namespace llvm::AMDGPU::SDWA;
6383
Sam Kolton3025e7f2016-04-26 13:33:56 +00006384 SMLoc S = Parser.getTok().getLoc();
6385 StringRef Value;
Alex Bradbury58eba092016-11-01 16:32:05 +00006386 OperandMatchResultTy res;
Sam Kolton3025e7f2016-04-26 13:33:56 +00006387
6388 res = parseStringWithPrefix("dst_unused", Value);
6389 if (res != MatchOperand_Success) {
6390 return res;
6391 }
6392
6393 int64_t Int;
6394 Int = StringSwitch<int64_t>(Value)
Sam Koltona3ec5c12016-10-07 14:46:06 +00006395 .Case("UNUSED_PAD", DstUnused::UNUSED_PAD)
6396 .Case("UNUSED_SEXT", DstUnused::UNUSED_SEXT)
6397 .Case("UNUSED_PRESERVE", DstUnused::UNUSED_PRESERVE)
Sam Kolton3025e7f2016-04-26 13:33:56 +00006398 .Default(0xffffffff);
6399 Parser.Lex(); // eat last token
6400
6401 if (Int == 0xffffffff) {
6402 return MatchOperand_ParseFail;
6403 }
6404
Sam Kolton1eeb11b2016-09-09 14:44:04 +00006405 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTySdwaDstUnused));
Sam Kolton3025e7f2016-04-26 13:33:56 +00006406 return MatchOperand_Success;
6407}
6408
Sam Kolton945231a2016-06-10 09:57:59 +00006409void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) {
Sam Kolton5196b882016-07-01 09:59:21 +00006410 cvtSDWA(Inst, Operands, SIInstrFlags::VOP1);
Sam Kolton05ef1c92016-06-03 10:27:37 +00006411}
6412
Sam Kolton945231a2016-06-10 09:57:59 +00006413void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) {
Sam Kolton5196b882016-07-01 09:59:21 +00006414 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2);
6415}
6416
Sam Koltonf7659d712017-05-23 10:08:55 +00006417void AMDGPUAsmParser::cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands) {
6418 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2, true);
6419}
6420
Sam Kolton5196b882016-07-01 09:59:21 +00006421void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) {
Sam Koltonf7659d712017-05-23 10:08:55 +00006422 cvtSDWA(Inst, Operands, SIInstrFlags::VOPC, isVI());
Sam Kolton05ef1c92016-06-03 10:27:37 +00006423}
6424
6425void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands,
Sam Koltonf7659d712017-05-23 10:08:55 +00006426 uint64_t BasicInstType, bool skipVcc) {
Sam Kolton9dffada2017-01-17 15:26:02 +00006427 using namespace llvm::AMDGPU::SDWA;
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00006428
Sam Kolton05ef1c92016-06-03 10:27:37 +00006429 OptionalImmIndexMap OptionalIdx;
Sam Koltonf7659d712017-05-23 10:08:55 +00006430 bool skippedVcc = false;
Sam Kolton05ef1c92016-06-03 10:27:37 +00006431
6432 unsigned I = 1;
6433 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
6434 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
6435 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
6436 }
6437
6438 for (unsigned E = Operands.size(); I != E; ++I) {
6439 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00006440 if (skipVcc && !skippedVcc && Op.isReg() && Op.getReg() == AMDGPU::VCC) {
Sam Koltonf7659d712017-05-23 10:08:55 +00006441 // VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst.
6442 // Skip it if it's 2nd (e.g. v_add_i32_sdwa v1, vcc, v2, v3)
6443 // or 4th (v_addc_u32_sdwa v1, vcc, v2, v3, vcc) operand.
6444 // Skip VCC only if we didn't skip it on previous iteration.
6445 if (BasicInstType == SIInstrFlags::VOP2 &&
6446 (Inst.getNumOperands() == 1 || Inst.getNumOperands() == 5)) {
6447 skippedVcc = true;
6448 continue;
6449 } else if (BasicInstType == SIInstrFlags::VOPC &&
6450 Inst.getNumOperands() == 0) {
6451 skippedVcc = true;
6452 continue;
6453 }
6454 }
6455 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
Dmitry Preobrazhensky6b65f7c2018-01-17 14:00:48 +00006456 Op.addRegOrImmWithInputModsOperands(Inst, 2);
Sam Kolton05ef1c92016-06-03 10:27:37 +00006457 } else if (Op.isImm()) {
6458 // Handle optional arguments
6459 OptionalIdx[Op.getImmTy()] = I;
6460 } else {
6461 llvm_unreachable("Invalid operand type");
6462 }
Sam Koltonf7659d712017-05-23 10:08:55 +00006463 skippedVcc = false;
Sam Kolton05ef1c92016-06-03 10:27:37 +00006464 }
6465
Stanislav Mekhanoshin4f331cb2019-04-26 23:16:16 +00006466 if (Inst.getOpcode() != AMDGPU::V_NOP_sdwa_gfx10 &&
6467 Inst.getOpcode() != AMDGPU::V_NOP_sdwa_gfx9 &&
Sam Koltonf7659d712017-05-23 10:08:55 +00006468 Inst.getOpcode() != AMDGPU::V_NOP_sdwa_vi) {
Sam Kolton549c89d2017-06-21 08:53:38 +00006469 // v_nop_sdwa_sdwa_vi/gfx9 has no optional sdwa arguments
Sam Koltona3ec5c12016-10-07 14:46:06 +00006470 switch (BasicInstType) {
Eugene Zelenko2bc2f332016-12-09 22:06:55 +00006471 case SIInstrFlags::VOP1:
Sam Koltonf7659d712017-05-23 10:08:55 +00006472 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
Sam Kolton549c89d2017-06-21 08:53:38 +00006473 if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) {
Sam Koltonf7659d712017-05-23 10:08:55 +00006474 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0);
6475 }
Sam Kolton9dffada2017-01-17 15:26:02 +00006476 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD);
6477 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE);
6478 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
Sam Koltona3ec5c12016-10-07 14:46:06 +00006479 break;
Eugene Zelenko2bc2f332016-12-09 22:06:55 +00006480
6481 case SIInstrFlags::VOP2:
Sam Koltonf7659d712017-05-23 10:08:55 +00006482 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
Sam Kolton549c89d2017-06-21 08:53:38 +00006483 if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) {
Sam Koltonf7659d712017-05-23 10:08:55 +00006484 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0);
6485 }
Sam Kolton9dffada2017-01-17 15:26:02 +00006486 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD);
6487 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE);
6488 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
6489 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD);
Sam Koltona3ec5c12016-10-07 14:46:06 +00006490 break;
Eugene Zelenko2bc2f332016-12-09 22:06:55 +00006491
6492 case SIInstrFlags::VOPC:
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00006493 if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::clamp) != -1)
6494 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
Sam Kolton9dffada2017-01-17 15:26:02 +00006495 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
6496 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD);
Sam Koltona3ec5c12016-10-07 14:46:06 +00006497 break;
Eugene Zelenko2bc2f332016-12-09 22:06:55 +00006498
Sam Koltona3ec5c12016-10-07 14:46:06 +00006499 default:
6500 llvm_unreachable("Invalid instruction type. Only VOP1, VOP2 and VOPC allowed");
6501 }
Sam Kolton05ef1c92016-06-03 10:27:37 +00006502 }
Matt Arsenaultf3dd8632016-11-01 00:55:14 +00006503
Konstantin Zhuravlyovf86e4b72016-11-13 07:01:11 +00006504 // special case v_mac_{f16, f32}:
Sam Koltona3ec5c12016-10-07 14:46:06 +00006505 // it has src2 register operand that is tied to dst operand
Sam Koltona568e3d2016-12-22 12:57:41 +00006506 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
6507 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
Sam Koltona3ec5c12016-10-07 14:46:06 +00006508 auto it = Inst.begin();
Konstantin Zhuravlyovf86e4b72016-11-13 07:01:11 +00006509 std::advance(
Sam Koltonf7659d712017-05-23 10:08:55 +00006510 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
Sam Koltona3ec5c12016-10-07 14:46:06 +00006511 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
Sam Kolton5196b882016-07-01 09:59:21 +00006512 }
Sam Kolton05ef1c92016-06-03 10:27:37 +00006513}
Nikolay Haustov2f684f12016-02-26 09:51:05 +00006514
Tom Stellard45bb48e2015-06-13 03:28:10 +00006515/// Force static initialization.
Tom Stellard4b0b2612019-06-11 03:21:13 +00006516extern "C" void LLVMInitializeAMDGPUAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00006517 RegisterMCAsmParser<AMDGPUAsmParser> A(getTheAMDGPUTarget());
6518 RegisterMCAsmParser<AMDGPUAsmParser> B(getTheGCNTarget());
Tom Stellard45bb48e2015-06-13 03:28:10 +00006519}
6520
6521#define GET_REGISTER_MATCHER
6522#define GET_MATCHER_IMPLEMENTATION
Matt Arsenaultf7f59b52017-12-20 18:52:57 +00006523#define GET_MNEMONIC_SPELL_CHECKER
Tom Stellard45bb48e2015-06-13 03:28:10 +00006524#include "AMDGPUGenAsmMatcher.inc"
Sam Kolton11de3702016-05-24 12:38:33 +00006525
Sam Kolton11de3702016-05-24 12:38:33 +00006526// This fuction should be defined after auto-generated include so that we have
6527// MatchClassKind enum defined
6528unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
6529 unsigned Kind) {
6530 // Tokens like "glc" would be parsed as immediate operands in ParseOperand().
Matt Arsenault37fefd62016-06-10 02:18:02 +00006531 // But MatchInstructionImpl() expects to meet token and fails to validate
Sam Kolton11de3702016-05-24 12:38:33 +00006532 // operand. This method checks if we are given immediate operand but expect to
6533 // get corresponding token.
6534 AMDGPUOperand &Operand = (AMDGPUOperand&)Op;
6535 switch (Kind) {
6536 case MCK_addr64:
6537 return Operand.isAddr64() ? Match_Success : Match_InvalidOperand;
6538 case MCK_gds:
6539 return Operand.isGDS() ? Match_Success : Match_InvalidOperand;
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +00006540 case MCK_lds:
6541 return Operand.isLDS() ? Match_Success : Match_InvalidOperand;
Sam Kolton11de3702016-05-24 12:38:33 +00006542 case MCK_glc:
6543 return Operand.isGLC() ? Match_Success : Match_InvalidOperand;
6544 case MCK_idxen:
6545 return Operand.isIdxen() ? Match_Success : Match_InvalidOperand;
6546 case MCK_offen:
6547 return Operand.isOffen() ? Match_Success : Match_InvalidOperand;
Sam Kolton1eeb11b2016-09-09 14:44:04 +00006548 case MCK_SSrcB32:
Tom Stellard89049702016-06-15 02:54:14 +00006549 // When operands have expression values, they will return true for isToken,
6550 // because it is not possible to distinguish between a token and an
6551 // expression at parse time. MatchInstructionImpl() will always try to
6552 // match an operand as a token, when isToken returns true, and when the
6553 // name of the expression is not a valid token, the match will fail,
6554 // so we need to handle it here.
Sam Kolton1eeb11b2016-09-09 14:44:04 +00006555 return Operand.isSSrcB32() ? Match_Success : Match_InvalidOperand;
6556 case MCK_SSrcF32:
6557 return Operand.isSSrcF32() ? Match_Success : Match_InvalidOperand;
Artem Tamazov53c9de02016-07-11 12:07:18 +00006558 case MCK_SoppBrTarget:
6559 return Operand.isSoppBrTarget() ? Match_Success : Match_InvalidOperand;
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00006560 case MCK_VReg32OrOff:
6561 return Operand.isVReg32OrOff() ? Match_Success : Match_InvalidOperand;
Matt Arsenault0e8a2992016-12-15 20:40:20 +00006562 case MCK_InterpSlot:
6563 return Operand.isInterpSlot() ? Match_Success : Match_InvalidOperand;
6564 case MCK_Attr:
6565 return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand;
6566 case MCK_AttrChan:
6567 return Operand.isAttrChan() ? Match_Success : Match_InvalidOperand;
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00006568 default:
6569 return Match_InvalidOperand;
Sam Kolton11de3702016-05-24 12:38:33 +00006570 }
6571}
David Stuttard20ea21c2019-03-12 09:52:58 +00006572
6573//===----------------------------------------------------------------------===//
6574// endpgm
6575//===----------------------------------------------------------------------===//
6576
6577OperandMatchResultTy AMDGPUAsmParser::parseEndpgmOp(OperandVector &Operands) {
6578 SMLoc S = Parser.getTok().getLoc();
6579 int64_t Imm = 0;
6580
6581 if (!parseExpr(Imm)) {
6582 // The operand is optional, if not present default to 0
6583 Imm = 0;
6584 }
6585
6586 if (!isUInt<16>(Imm)) {
6587 Error(S, "expected a 16-bit value");
6588 return MatchOperand_ParseFail;
6589 }
6590
6591 Operands.push_back(
6592 AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTyEndpgm));
6593 return MatchOperand_Success;
6594}
6595
6596bool AMDGPUOperand::isEndpgm() const { return isImmTy(ImmTyEndpgm); }