blob: 519f809cce67ac87fde64082ada5d9c0cd22962e [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
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +000072enum RegisterKind { IS_UNKNOWN, IS_VGPR, IS_SGPR, IS_AGPR, IS_TTMP, IS_SPECIAL };
Nikolay Haustovfb5c3072016-04-20 09:34:48 +000073
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,
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +0000182 ImmTyHigh,
183 ImmTyBLGP,
184 ImmTyCBSZ,
185 ImmTyABID,
David Stuttard20ea21c2019-03-12 09:52:58 +0000186 ImmTyEndpgm,
Tom Stellard45bb48e2015-06-13 03:28:10 +0000187 };
188
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +0000189private:
Tom Stellard45bb48e2015-06-13 03:28:10 +0000190 struct TokOp {
191 const char *Data;
192 unsigned Length;
193 };
194
195 struct ImmOp {
Tom Stellard45bb48e2015-06-13 03:28:10 +0000196 int64_t Val;
Matt Arsenault7f192982016-08-16 20:28:06 +0000197 ImmTy Type;
198 bool IsFPImm;
Sam Kolton945231a2016-06-10 09:57:59 +0000199 Modifiers Mods;
Tom Stellard45bb48e2015-06-13 03:28:10 +0000200 };
201
202 struct RegOp {
Matt Arsenault7f192982016-08-16 20:28:06 +0000203 unsigned RegNo;
Matt Arsenault7f192982016-08-16 20:28:06 +0000204 Modifiers Mods;
Tom Stellard45bb48e2015-06-13 03:28:10 +0000205 };
206
207 union {
208 TokOp Tok;
209 ImmOp Imm;
210 RegOp Reg;
211 const MCExpr *Expr;
212 };
213
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +0000214public:
Tom Stellard45bb48e2015-06-13 03:28:10 +0000215 bool isToken() const override {
Tom Stellard89049702016-06-15 02:54:14 +0000216 if (Kind == Token)
217 return true;
218
Tom Stellard89049702016-06-15 02:54:14 +0000219 // 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.
Dmitry Preobrazhensky4ccb7f82019-07-19 13:12:47 +0000223 return isSymbolRefExpr();
224 }
225
226 bool isSymbolRefExpr() const {
227 return isExpr() && Expr && isa<MCSymbolRefExpr>(Expr);
Tom Stellard45bb48e2015-06-13 03:28:10 +0000228 }
229
230 bool isImm() const override {
231 return Kind == Immediate;
232 }
233
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000234 bool isInlinableImm(MVT type) const;
235 bool isLiteralImm(MVT type) const;
Tom Stellard45bb48e2015-06-13 03:28:10 +0000236
Tom Stellard45bb48e2015-06-13 03:28:10 +0000237 bool isRegKind() const {
238 return Kind == Register;
239 }
240
241 bool isReg() const override {
Sam Kolton9772eb32017-01-11 11:46:30 +0000242 return isRegKind() && !hasModifiers();
Tom Stellard45bb48e2015-06-13 03:28:10 +0000243 }
244
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +0000245 bool isRegOrImmWithInputMods(unsigned RCID, MVT type) const {
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +0000246 return isRegClass(RCID) || isInlinableImm(type) || isLiteralImm(type);
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000247 }
248
Matt Arsenault4bd72362016-12-10 00:39:12 +0000249 bool isRegOrImmWithInt16InputMods() const {
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +0000250 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::i16);
Matt Arsenault4bd72362016-12-10 00:39:12 +0000251 }
252
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000253 bool isRegOrImmWithInt32InputMods() const {
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +0000254 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::i32);
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000255 }
256
257 bool isRegOrImmWithInt64InputMods() const {
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +0000258 return isRegOrImmWithInputMods(AMDGPU::VS_64RegClassID, MVT::i64);
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000259 }
260
Matt Arsenault4bd72362016-12-10 00:39:12 +0000261 bool isRegOrImmWithFP16InputMods() const {
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +0000262 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::f16);
Matt Arsenault4bd72362016-12-10 00:39:12 +0000263 }
264
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000265 bool isRegOrImmWithFP32InputMods() const {
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +0000266 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::f32);
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000267 }
268
269 bool isRegOrImmWithFP64InputMods() const {
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +0000270 return isRegOrImmWithInputMods(AMDGPU::VS_64RegClassID, MVT::f64);
Tom Stellarda90b9522016-02-11 03:28:15 +0000271 }
272
Sam Kolton9772eb32017-01-11 11:46:30 +0000273 bool isVReg() const {
274 return isRegClass(AMDGPU::VGPR_32RegClassID) ||
275 isRegClass(AMDGPU::VReg_64RegClassID) ||
276 isRegClass(AMDGPU::VReg_96RegClassID) ||
277 isRegClass(AMDGPU::VReg_128RegClassID) ||
Stanislav Mekhanoshin5cdacea2019-07-24 16:21:18 +0000278 isRegClass(AMDGPU::VReg_160RegClassID) ||
Sam Kolton9772eb32017-01-11 11:46:30 +0000279 isRegClass(AMDGPU::VReg_256RegClassID) ||
Stanislav Mekhanoshin5cdacea2019-07-24 16:21:18 +0000280 isRegClass(AMDGPU::VReg_512RegClassID) ||
281 isRegClass(AMDGPU::VReg_1024RegClassID);
Sam Kolton9772eb32017-01-11 11:46:30 +0000282 }
283
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +0000284 bool isVReg32() const {
285 return isRegClass(AMDGPU::VGPR_32RegClassID);
286 }
287
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +0000288 bool isVReg32OrOff() const {
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +0000289 return isOff() || isVReg32();
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +0000290 }
291
Dmitry Preobrazhensky6b65f7c2018-01-17 14:00:48 +0000292 bool isSDWAOperand(MVT type) const;
293 bool isSDWAFP16Operand() const;
294 bool isSDWAFP32Operand() const;
295 bool isSDWAInt16Operand() const;
296 bool isSDWAInt32Operand() const;
Sam Kolton549c89d2017-06-21 08:53:38 +0000297
Nikolay Haustov2f684f12016-02-26 09:51:05 +0000298 bool isImmTy(ImmTy ImmT) const {
299 return isImm() && Imm.Type == ImmT;
300 }
Matt Arsenaultf3dd8632016-11-01 00:55:14 +0000301
Nikolay Haustov2f684f12016-02-26 09:51:05 +0000302 bool isImmModifier() const {
Sam Kolton945231a2016-06-10 09:57:59 +0000303 return isImm() && Imm.Type != ImmTyNone;
Nikolay Haustov2f684f12016-02-26 09:51:05 +0000304 }
Matt Arsenaultf3dd8632016-11-01 00:55:14 +0000305
Sam Kolton945231a2016-06-10 09:57:59 +0000306 bool isClampSI() const { return isImmTy(ImmTyClampSI); }
307 bool isOModSI() const { return isImmTy(ImmTyOModSI); }
308 bool isDMask() const { return isImmTy(ImmTyDMask); }
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +0000309 bool isDim() const { return isImmTy(ImmTyDim); }
Nikolay Haustov2f684f12016-02-26 09:51:05 +0000310 bool isUNorm() const { return isImmTy(ImmTyUNorm); }
311 bool isDA() const { return isImmTy(ImmTyDA); }
Ryan Taylor1f334d02018-08-28 15:07:30 +0000312 bool isR128A16() const { return isImmTy(ImmTyR128A16); }
Nikolay Haustov2f684f12016-02-26 09:51:05 +0000313 bool isLWE() const { return isImmTy(ImmTyLWE); }
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +0000314 bool isOff() const { return isImmTy(ImmTyOff); }
315 bool isExpTgt() const { return isImmTy(ImmTyExpTgt); }
Matt Arsenault8a63cb92016-12-05 20:31:49 +0000316 bool isExpVM() const { return isImmTy(ImmTyExpVM); }
317 bool isExpCompr() const { return isImmTy(ImmTyExpCompr); }
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000318 bool isOffen() const { return isImmTy(ImmTyOffen); }
319 bool isIdxen() const { return isImmTy(ImmTyIdxen); }
320 bool isAddr64() const { return isImmTy(ImmTyAddr64); }
321 bool isOffset() const { return isImmTy(ImmTyOffset) && isUInt<16>(getImm()); }
Dmitry Preobrazhensky04bd1182019-03-20 17:13:58 +0000322 bool isOffset0() const { return isImmTy(ImmTyOffset0) && isUInt<8>(getImm()); }
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000323 bool isOffset1() const { return isImmTy(ImmTyOffset1) && isUInt<8>(getImm()); }
Matt Arsenaultfd023142017-06-12 15:55:58 +0000324
Dmitry Preobrazhensky2eff0312019-07-08 14:27:37 +0000325 bool isFlatOffset() const { return isImmTy(ImmTyOffset) || isImmTy(ImmTyInstOffset); }
Nikolay Haustovea8febd2016-03-01 08:34:43 +0000326 bool isGDS() const { return isImmTy(ImmTyGDS); }
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +0000327 bool isLDS() const { return isImmTy(ImmTyLDS); }
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +0000328 bool isDLC() const { return isImmTy(ImmTyDLC); }
Nikolay Haustovea8febd2016-03-01 08:34:43 +0000329 bool isGLC() const { return isImmTy(ImmTyGLC); }
330 bool isSLC() const { return isImmTy(ImmTySLC); }
331 bool isTFE() const { return isImmTy(ImmTyTFE); }
Dmitry Preobrazhensky4f321ae2018-01-29 14:20:42 +0000332 bool isD16() const { return isImmTy(ImmTyD16); }
Tim Renouf35484c92018-08-21 11:06:05 +0000333 bool isFORMAT() const { return isImmTy(ImmTyFORMAT) && isUInt<8>(getImm()); }
Sam Kolton945231a2016-06-10 09:57:59 +0000334 bool isBankMask() const { return isImmTy(ImmTyDppBankMask); }
335 bool isRowMask() const { return isImmTy(ImmTyDppRowMask); }
336 bool isBoundCtrl() const { return isImmTy(ImmTyDppBoundCtrl); }
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +0000337 bool isFI() const { return isImmTy(ImmTyDppFi); }
Sam Kolton945231a2016-06-10 09:57:59 +0000338 bool isSDWADstSel() const { return isImmTy(ImmTySdwaDstSel); }
339 bool isSDWASrc0Sel() const { return isImmTy(ImmTySdwaSrc0Sel); }
340 bool isSDWASrc1Sel() const { return isImmTy(ImmTySdwaSrc1Sel); }
341 bool isSDWADstUnused() const { return isImmTy(ImmTySdwaDstUnused); }
Matt Arsenault0e8a2992016-12-15 20:40:20 +0000342 bool isInterpSlot() const { return isImmTy(ImmTyInterpSlot); }
343 bool isInterpAttr() const { return isImmTy(ImmTyInterpAttr); }
344 bool isAttrChan() const { return isImmTy(ImmTyAttrChan); }
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000345 bool isOpSel() const { return isImmTy(ImmTyOpSel); }
346 bool isOpSelHi() const { return isImmTy(ImmTyOpSelHi); }
347 bool isNegLo() const { return isImmTy(ImmTyNegLo); }
348 bool isNegHi() const { return isImmTy(ImmTyNegHi); }
Dmitry Preobrazhensky50805a02017-08-07 13:14:12 +0000349 bool isHigh() const { return isImmTy(ImmTyHigh); }
Matt Arsenaultf3dd8632016-11-01 00:55:14 +0000350
Sam Kolton945231a2016-06-10 09:57:59 +0000351 bool isMod() const {
352 return isClampSI() || isOModSI();
Tom Stellard45bb48e2015-06-13 03:28:10 +0000353 }
354
355 bool isRegOrImm() const {
356 return isReg() || isImm();
357 }
358
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000359 bool isRegClass(unsigned RCID) const;
360
Dmitry Preobrazhensky137976f2019-03-20 15:40:52 +0000361 bool isInlineValue() const;
362
Sam Kolton9772eb32017-01-11 11:46:30 +0000363 bool isRegOrInlineNoMods(unsigned RCID, MVT type) const {
364 return (isRegClass(RCID) || isInlinableImm(type)) && !hasModifiers();
365 }
366
Matt Arsenault4bd72362016-12-10 00:39:12 +0000367 bool isSCSrcB16() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000368 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i16);
Matt Arsenault4bd72362016-12-10 00:39:12 +0000369 }
370
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000371 bool isSCSrcV2B16() const {
372 return isSCSrcB16();
373 }
374
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000375 bool isSCSrcB32() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000376 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i32);
Tom Stellard45bb48e2015-06-13 03:28:10 +0000377 }
378
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000379 bool isSCSrcB64() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000380 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::i64);
Tom Stellard45bb48e2015-06-13 03:28:10 +0000381 }
382
Stanislav Mekhanoshin8bcc9bb2019-06-13 19:18:29 +0000383 bool isBoolReg() const;
384
Matt Arsenault4bd72362016-12-10 00:39:12 +0000385 bool isSCSrcF16() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000386 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f16);
Matt Arsenault4bd72362016-12-10 00:39:12 +0000387 }
388
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000389 bool isSCSrcV2F16() const {
390 return isSCSrcF16();
391 }
392
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000393 bool isSCSrcF32() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000394 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f32);
Tom Stellardd93a34f2016-02-22 19:17:56 +0000395 }
396
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000397 bool isSCSrcF64() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000398 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::f64);
Tom Stellardd93a34f2016-02-22 19:17:56 +0000399 }
400
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000401 bool isSSrcB32() const {
402 return isSCSrcB32() || isLiteralImm(MVT::i32) || isExpr();
403 }
404
Matt Arsenault4bd72362016-12-10 00:39:12 +0000405 bool isSSrcB16() const {
406 return isSCSrcB16() || isLiteralImm(MVT::i16);
407 }
408
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000409 bool isSSrcV2B16() const {
410 llvm_unreachable("cannot happen");
411 return isSSrcB16();
412 }
413
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000414 bool isSSrcB64() const {
Tom Stellardd93a34f2016-02-22 19:17:56 +0000415 // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits.
416 // See isVSrc64().
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000417 return isSCSrcB64() || isLiteralImm(MVT::i64);
Matt Arsenault86d336e2015-09-08 21:15:00 +0000418 }
419
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000420 bool isSSrcF32() const {
421 return isSCSrcB32() || isLiteralImm(MVT::f32) || isExpr();
Tom Stellard45bb48e2015-06-13 03:28:10 +0000422 }
423
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000424 bool isSSrcF64() const {
425 return isSCSrcB64() || isLiteralImm(MVT::f64);
Tom Stellard45bb48e2015-06-13 03:28:10 +0000426 }
427
Matt Arsenault4bd72362016-12-10 00:39:12 +0000428 bool isSSrcF16() const {
429 return isSCSrcB16() || isLiteralImm(MVT::f16);
430 }
431
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000432 bool isSSrcV2F16() const {
433 llvm_unreachable("cannot happen");
434 return isSSrcF16();
435 }
436
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +0000437 bool isSSrcOrLdsB32() const {
438 return isRegOrInlineNoMods(AMDGPU::SRegOrLds_32RegClassID, MVT::i32) ||
439 isLiteralImm(MVT::i32) || isExpr();
440 }
441
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000442 bool isVCSrcB32() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000443 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i32);
Tom Stellard45bb48e2015-06-13 03:28:10 +0000444 }
445
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000446 bool isVCSrcB64() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000447 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::i64);
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000448 }
Matt Arsenaultf3dd8632016-11-01 00:55:14 +0000449
Matt Arsenault4bd72362016-12-10 00:39:12 +0000450 bool isVCSrcB16() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000451 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i16);
Matt Arsenault4bd72362016-12-10 00:39:12 +0000452 }
453
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000454 bool isVCSrcV2B16() const {
455 return isVCSrcB16();
456 }
457
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000458 bool isVCSrcF32() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000459 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f32);
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000460 }
461
462 bool isVCSrcF64() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000463 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::f64);
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000464 }
465
Matt Arsenault4bd72362016-12-10 00:39:12 +0000466 bool isVCSrcF16() const {
Sam Kolton9772eb32017-01-11 11:46:30 +0000467 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f16);
Matt Arsenault4bd72362016-12-10 00:39:12 +0000468 }
469
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000470 bool isVCSrcV2F16() const {
471 return isVCSrcF16();
472 }
473
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000474 bool isVSrcB32() const {
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +0000475 return isVCSrcF32() || isLiteralImm(MVT::i32) || isExpr();
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000476 }
477
478 bool isVSrcB64() const {
479 return isVCSrcF64() || isLiteralImm(MVT::i64);
480 }
481
Matt Arsenault4bd72362016-12-10 00:39:12 +0000482 bool isVSrcB16() const {
483 return isVCSrcF16() || isLiteralImm(MVT::i16);
484 }
485
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000486 bool isVSrcV2B16() const {
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +0000487 return isVSrcB16() || isLiteralImm(MVT::v2i16);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000488 }
489
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000490 bool isVSrcF32() const {
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +0000491 return isVCSrcF32() || isLiteralImm(MVT::f32) || isExpr();
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000492 }
493
494 bool isVSrcF64() const {
495 return isVCSrcF64() || isLiteralImm(MVT::f64);
496 }
497
Matt Arsenault4bd72362016-12-10 00:39:12 +0000498 bool isVSrcF16() const {
499 return isVCSrcF16() || isLiteralImm(MVT::f16);
500 }
501
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000502 bool isVSrcV2F16() const {
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +0000503 return isVSrcF16() || isLiteralImm(MVT::v2f16);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000504 }
505
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +0000506 bool isVISrcB32() const {
507 return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::i32);
508 }
509
510 bool isVISrcB16() const {
511 return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::i16);
512 }
513
514 bool isVISrcV2B16() const {
515 return isVISrcB16();
516 }
517
518 bool isVISrcF32() const {
519 return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::f32);
520 }
521
522 bool isVISrcF16() const {
523 return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::f16);
524 }
525
526 bool isVISrcV2F16() const {
527 return isVISrcF16() || isVISrcB32();
528 }
529
530 bool isAISrcB32() const {
531 return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::i32);
532 }
533
534 bool isAISrcB16() const {
535 return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::i16);
536 }
537
538 bool isAISrcV2B16() const {
539 return isAISrcB16();
540 }
541
542 bool isAISrcF32() const {
543 return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::f32);
544 }
545
546 bool isAISrcF16() const {
547 return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::f16);
548 }
549
550 bool isAISrcV2F16() const {
551 return isAISrcF16() || isAISrcB32();
552 }
553
554 bool isAISrc_128B32() const {
555 return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::i32);
556 }
557
558 bool isAISrc_128B16() const {
559 return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::i16);
560 }
561
562 bool isAISrc_128V2B16() const {
563 return isAISrc_128B16();
564 }
565
566 bool isAISrc_128F32() const {
567 return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::f32);
568 }
569
570 bool isAISrc_128F16() const {
571 return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::f16);
572 }
573
574 bool isAISrc_128V2F16() const {
575 return isAISrc_128F16() || isAISrc_128B32();
576 }
577
578 bool isAISrc_512B32() const {
579 return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::i32);
580 }
581
582 bool isAISrc_512B16() const {
583 return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::i16);
584 }
585
586 bool isAISrc_512V2B16() const {
587 return isAISrc_512B16();
588 }
589
590 bool isAISrc_512F32() const {
591 return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::f32);
592 }
593
594 bool isAISrc_512F16() const {
595 return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::f16);
596 }
597
598 bool isAISrc_512V2F16() const {
599 return isAISrc_512F16() || isAISrc_512B32();
600 }
601
602 bool isAISrc_1024B32() const {
603 return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::i32);
604 }
605
606 bool isAISrc_1024B16() const {
607 return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::i16);
608 }
609
610 bool isAISrc_1024V2B16() const {
611 return isAISrc_1024B16();
612 }
613
614 bool isAISrc_1024F32() const {
615 return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::f32);
616 }
617
618 bool isAISrc_1024F16() const {
619 return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::f16);
620 }
621
622 bool isAISrc_1024V2F16() const {
623 return isAISrc_1024F16() || isAISrc_1024B32();
624 }
625
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000626 bool isKImmFP32() const {
627 return isLiteralImm(MVT::f32);
Tom Stellard45bb48e2015-06-13 03:28:10 +0000628 }
629
Matt Arsenault4bd72362016-12-10 00:39:12 +0000630 bool isKImmFP16() const {
631 return isLiteralImm(MVT::f16);
632 }
633
Tom Stellard45bb48e2015-06-13 03:28:10 +0000634 bool isMem() const override {
635 return false;
636 }
637
638 bool isExpr() const {
639 return Kind == Expression;
640 }
641
642 bool isSoppBrTarget() const {
643 return isExpr() || isImm();
644 }
645
Sam Kolton945231a2016-06-10 09:57:59 +0000646 bool isSWaitCnt() const;
647 bool isHwreg() const;
648 bool isSendMsg() const;
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +0000649 bool isSwizzle() const;
Artem Tamazov54bfd542016-10-31 16:07:39 +0000650 bool isSMRDOffset8() const;
651 bool isSMRDOffset20() const;
Sam Kolton945231a2016-06-10 09:57:59 +0000652 bool isSMRDLiteralOffset() const;
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +0000653 bool isDPP8() const;
Sam Kolton945231a2016-06-10 09:57:59 +0000654 bool isDPPCtrl() const;
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +0000655 bool isBLGP() const;
656 bool isCBSZ() const;
657 bool isABID() const;
Matt Arsenaultcc88ce32016-10-12 18:00:51 +0000658 bool isGPRIdxMode() const;
Dmitry Preobrazhenskyc7d35a02017-04-26 15:34:19 +0000659 bool isS16Imm() const;
660 bool isU16Imm() const;
David Stuttard20ea21c2019-03-12 09:52:58 +0000661 bool isEndpgm() const;
Sam Kolton945231a2016-06-10 09:57:59 +0000662
Tom Stellard89049702016-06-15 02:54:14 +0000663 StringRef getExpressionAsToken() const {
664 assert(isExpr());
665 const MCSymbolRefExpr *S = cast<MCSymbolRefExpr>(Expr);
666 return S->getSymbol().getName();
667 }
668
Sam Kolton945231a2016-06-10 09:57:59 +0000669 StringRef getToken() const {
Tom Stellard89049702016-06-15 02:54:14 +0000670 assert(isToken());
671
672 if (Kind == Expression)
673 return getExpressionAsToken();
674
Sam Kolton945231a2016-06-10 09:57:59 +0000675 return StringRef(Tok.Data, Tok.Length);
676 }
677
678 int64_t getImm() const {
679 assert(isImm());
680 return Imm.Val;
681 }
682
Matt Arsenaultf15da6c2017-02-03 20:49:51 +0000683 ImmTy getImmTy() const {
Sam Kolton945231a2016-06-10 09:57:59 +0000684 assert(isImm());
685 return Imm.Type;
686 }
687
688 unsigned getReg() const override {
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +0000689 assert(isRegKind());
Sam Kolton945231a2016-06-10 09:57:59 +0000690 return Reg.RegNo;
691 }
692
Tom Stellard45bb48e2015-06-13 03:28:10 +0000693 SMLoc getStartLoc() const override {
694 return StartLoc;
695 }
696
Peter Collingbourne0da86302016-10-10 22:49:37 +0000697 SMLoc getEndLoc() const override {
Tom Stellard45bb48e2015-06-13 03:28:10 +0000698 return EndLoc;
699 }
700
Matt Arsenaultf7f59b52017-12-20 18:52:57 +0000701 SMRange getLocRange() const {
702 return SMRange(StartLoc, EndLoc);
703 }
704
Sam Kolton945231a2016-06-10 09:57:59 +0000705 Modifiers getModifiers() const {
706 assert(isRegKind() || isImmTy(ImmTyNone));
707 return isRegKind() ? Reg.Mods : Imm.Mods;
708 }
709
710 void setModifiers(Modifiers Mods) {
711 assert(isRegKind() || isImmTy(ImmTyNone));
712 if (isRegKind())
713 Reg.Mods = Mods;
714 else
715 Imm.Mods = Mods;
716 }
717
718 bool hasModifiers() const {
719 return getModifiers().hasModifiers();
720 }
Matt Arsenaultf3dd8632016-11-01 00:55:14 +0000721
Sam Kolton945231a2016-06-10 09:57:59 +0000722 bool hasFPModifiers() const {
723 return getModifiers().hasFPModifiers();
724 }
725
726 bool hasIntModifiers() const {
727 return getModifiers().hasIntModifiers();
728 }
729
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +0000730 uint64_t applyInputFPModifiers(uint64_t Val, unsigned Size) const;
731
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000732 void addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers = true) const;
Sam Kolton945231a2016-06-10 09:57:59 +0000733
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +0000734 void addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const;
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000735
Matt Arsenault4bd72362016-12-10 00:39:12 +0000736 template <unsigned Bitwidth>
737 void addKImmFPOperands(MCInst &Inst, unsigned N) const;
738
739 void addKImmFP16Operands(MCInst &Inst, unsigned N) const {
740 addKImmFPOperands<16>(Inst, N);
741 }
742
743 void addKImmFP32Operands(MCInst &Inst, unsigned N) const {
744 addKImmFPOperands<32>(Inst, N);
745 }
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000746
747 void addRegOperands(MCInst &Inst, unsigned N) const;
Sam Kolton945231a2016-06-10 09:57:59 +0000748
Stanislav Mekhanoshin8bcc9bb2019-06-13 19:18:29 +0000749 void addBoolRegOperands(MCInst &Inst, unsigned N) const {
750 addRegOperands(Inst, N);
751 }
752
Sam Kolton945231a2016-06-10 09:57:59 +0000753 void addRegOrImmOperands(MCInst &Inst, unsigned N) const {
754 if (isRegKind())
755 addRegOperands(Inst, N);
Tom Stellard89049702016-06-15 02:54:14 +0000756 else if (isExpr())
757 Inst.addOperand(MCOperand::createExpr(Expr));
Sam Kolton945231a2016-06-10 09:57:59 +0000758 else
759 addImmOperands(Inst, N);
760 }
761
762 void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const {
763 Modifiers Mods = getModifiers();
764 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
765 if (isRegKind()) {
766 addRegOperands(Inst, N);
767 } else {
768 addImmOperands(Inst, N, false);
769 }
770 }
771
772 void addRegOrImmWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
773 assert(!hasIntModifiers());
774 addRegOrImmWithInputModsOperands(Inst, N);
775 }
776
777 void addRegOrImmWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
778 assert(!hasFPModifiers());
779 addRegOrImmWithInputModsOperands(Inst, N);
780 }
781
Sam Kolton9772eb32017-01-11 11:46:30 +0000782 void addRegWithInputModsOperands(MCInst &Inst, unsigned N) const {
783 Modifiers Mods = getModifiers();
784 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
785 assert(isRegKind());
786 addRegOperands(Inst, N);
787 }
788
789 void addRegWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
790 assert(!hasIntModifiers());
791 addRegWithInputModsOperands(Inst, N);
792 }
793
794 void addRegWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
795 assert(!hasFPModifiers());
796 addRegWithInputModsOperands(Inst, N);
797 }
798
Sam Kolton945231a2016-06-10 09:57:59 +0000799 void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const {
800 if (isImm())
801 addImmOperands(Inst, N);
802 else {
803 assert(isExpr());
804 Inst.addOperand(MCOperand::createExpr(Expr));
805 }
806 }
807
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +0000808 static void printImmTy(raw_ostream& OS, ImmTy Type) {
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000809 switch (Type) {
810 case ImmTyNone: OS << "None"; break;
811 case ImmTyGDS: OS << "GDS"; break;
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +0000812 case ImmTyLDS: OS << "LDS"; break;
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000813 case ImmTyOffen: OS << "Offen"; break;
814 case ImmTyIdxen: OS << "Idxen"; break;
815 case ImmTyAddr64: OS << "Addr64"; break;
816 case ImmTyOffset: OS << "Offset"; break;
Dmitry Preobrazhenskydd2f1c92017-11-24 13:22:38 +0000817 case ImmTyInstOffset: OS << "InstOffset"; break;
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000818 case ImmTyOffset0: OS << "Offset0"; break;
819 case ImmTyOffset1: OS << "Offset1"; break;
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +0000820 case ImmTyDLC: OS << "DLC"; break;
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000821 case ImmTyGLC: OS << "GLC"; break;
822 case ImmTySLC: OS << "SLC"; break;
823 case ImmTyTFE: OS << "TFE"; break;
Dmitry Preobrazhensky4f321ae2018-01-29 14:20:42 +0000824 case ImmTyD16: OS << "D16"; break;
Tim Renouf35484c92018-08-21 11:06:05 +0000825 case ImmTyFORMAT: OS << "FORMAT"; break;
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000826 case ImmTyClampSI: OS << "ClampSI"; break;
827 case ImmTyOModSI: OS << "OModSI"; break;
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +0000828 case ImmTyDPP8: OS << "DPP8"; break;
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000829 case ImmTyDppCtrl: OS << "DppCtrl"; break;
830 case ImmTyDppRowMask: OS << "DppRowMask"; break;
831 case ImmTyDppBankMask: OS << "DppBankMask"; break;
832 case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break;
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +0000833 case ImmTyDppFi: OS << "FI"; break;
Sam Kolton05ef1c92016-06-03 10:27:37 +0000834 case ImmTySdwaDstSel: OS << "SdwaDstSel"; break;
835 case ImmTySdwaSrc0Sel: OS << "SdwaSrc0Sel"; break;
836 case ImmTySdwaSrc1Sel: OS << "SdwaSrc1Sel"; break;
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000837 case ImmTySdwaDstUnused: OS << "SdwaDstUnused"; break;
838 case ImmTyDMask: OS << "DMask"; break;
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +0000839 case ImmTyDim: OS << "Dim"; break;
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000840 case ImmTyUNorm: OS << "UNorm"; break;
841 case ImmTyDA: OS << "DA"; break;
Ryan Taylor1f334d02018-08-28 15:07:30 +0000842 case ImmTyR128A16: OS << "R128A16"; break;
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000843 case ImmTyLWE: OS << "LWE"; break;
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +0000844 case ImmTyOff: OS << "Off"; break;
845 case ImmTyExpTgt: OS << "ExpTgt"; break;
Matt Arsenault8a63cb92016-12-05 20:31:49 +0000846 case ImmTyExpCompr: OS << "ExpCompr"; break;
847 case ImmTyExpVM: OS << "ExpVM"; break;
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000848 case ImmTyHwreg: OS << "Hwreg"; break;
Artem Tamazovebe71ce2016-05-06 17:48:48 +0000849 case ImmTySendMsg: OS << "SendMsg"; break;
Matt Arsenault0e8a2992016-12-15 20:40:20 +0000850 case ImmTyInterpSlot: OS << "InterpSlot"; break;
851 case ImmTyInterpAttr: OS << "InterpAttr"; break;
852 case ImmTyAttrChan: OS << "AttrChan"; break;
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000853 case ImmTyOpSel: OS << "OpSel"; break;
854 case ImmTyOpSelHi: OS << "OpSelHi"; break;
855 case ImmTyNegLo: OS << "NegLo"; break;
856 case ImmTyNegHi: OS << "NegHi"; break;
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +0000857 case ImmTySwizzle: OS << "Swizzle"; break;
Dmitry Preobrazhenskyef920352019-02-27 13:12:12 +0000858 case ImmTyGprIdxMode: OS << "GprIdxMode"; break;
Dmitry Preobrazhensky50805a02017-08-07 13:14:12 +0000859 case ImmTyHigh: OS << "High"; break;
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +0000860 case ImmTyBLGP: OS << "BLGP"; break;
861 case ImmTyCBSZ: OS << "CBSZ"; break;
862 case ImmTyABID: OS << "ABID"; break;
863 case ImmTyEndpgm: OS << "Endpgm"; break;
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000864 }
865 }
866
Matt Arsenaultcbd75372015-08-08 00:41:51 +0000867 void print(raw_ostream &OS) const override {
868 switch (Kind) {
869 case Register:
Sam Kolton945231a2016-06-10 09:57:59 +0000870 OS << "<register " << getReg() << " mods: " << Reg.Mods << '>';
Matt Arsenaultcbd75372015-08-08 00:41:51 +0000871 break;
872 case Immediate:
Nikolay Haustov4f672a32016-04-29 09:02:30 +0000873 OS << '<' << getImm();
874 if (getImmTy() != ImmTyNone) {
875 OS << " type: "; printImmTy(OS, getImmTy());
876 }
Sam Kolton945231a2016-06-10 09:57:59 +0000877 OS << " mods: " << Imm.Mods << '>';
Matt Arsenaultcbd75372015-08-08 00:41:51 +0000878 break;
879 case Token:
880 OS << '\'' << getToken() << '\'';
881 break;
882 case Expression:
883 OS << "<expr " << *Expr << '>';
884 break;
885 }
886 }
Tom Stellard45bb48e2015-06-13 03:28:10 +0000887
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000888 static AMDGPUOperand::Ptr CreateImm(const AMDGPUAsmParser *AsmParser,
889 int64_t Val, SMLoc Loc,
Matt Arsenaultf15da6c2017-02-03 20:49:51 +0000890 ImmTy Type = ImmTyNone,
Sam Kolton5f10a132016-05-06 11:31:17 +0000891 bool IsFPImm = false) {
Jonas Devlieghere0eaee542019-08-15 15:54:37 +0000892 auto Op = std::make_unique<AMDGPUOperand>(Immediate, AsmParser);
Tom Stellard45bb48e2015-06-13 03:28:10 +0000893 Op->Imm.Val = Val;
894 Op->Imm.IsFPImm = IsFPImm;
895 Op->Imm.Type = Type;
Matt Arsenaultb55f6202016-12-03 18:22:49 +0000896 Op->Imm.Mods = Modifiers();
Tom Stellard45bb48e2015-06-13 03:28:10 +0000897 Op->StartLoc = Loc;
898 Op->EndLoc = Loc;
899 return Op;
900 }
901
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000902 static AMDGPUOperand::Ptr CreateToken(const AMDGPUAsmParser *AsmParser,
903 StringRef Str, SMLoc Loc,
Sam Kolton5f10a132016-05-06 11:31:17 +0000904 bool HasExplicitEncodingSize = true) {
Jonas Devlieghere0eaee542019-08-15 15:54:37 +0000905 auto Res = std::make_unique<AMDGPUOperand>(Token, AsmParser);
Tom Stellard45bb48e2015-06-13 03:28:10 +0000906 Res->Tok.Data = Str.data();
907 Res->Tok.Length = Str.size();
908 Res->StartLoc = Loc;
909 Res->EndLoc = Loc;
910 return Res;
911 }
912
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000913 static AMDGPUOperand::Ptr CreateReg(const AMDGPUAsmParser *AsmParser,
914 unsigned RegNo, SMLoc S,
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +0000915 SMLoc E) {
Jonas Devlieghere0eaee542019-08-15 15:54:37 +0000916 auto Op = std::make_unique<AMDGPUOperand>(Register, AsmParser);
Tom Stellard45bb48e2015-06-13 03:28:10 +0000917 Op->Reg.RegNo = RegNo;
Matt Arsenaultb55f6202016-12-03 18:22:49 +0000918 Op->Reg.Mods = Modifiers();
Tom Stellard45bb48e2015-06-13 03:28:10 +0000919 Op->StartLoc = S;
920 Op->EndLoc = E;
921 return Op;
922 }
923
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000924 static AMDGPUOperand::Ptr CreateExpr(const AMDGPUAsmParser *AsmParser,
925 const class MCExpr *Expr, SMLoc S) {
Jonas Devlieghere0eaee542019-08-15 15:54:37 +0000926 auto Op = std::make_unique<AMDGPUOperand>(Expression, AsmParser);
Tom Stellard45bb48e2015-06-13 03:28:10 +0000927 Op->Expr = Expr;
928 Op->StartLoc = S;
929 Op->EndLoc = S;
930 return Op;
931 }
Tom Stellard45bb48e2015-06-13 03:28:10 +0000932};
933
Sam Kolton945231a2016-06-10 09:57:59 +0000934raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) {
935 OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext;
936 return OS;
937}
938
Sam Kolton1eeb11b2016-09-09 14:44:04 +0000939//===----------------------------------------------------------------------===//
940// AsmParser
941//===----------------------------------------------------------------------===//
942
Artem Tamazova01cce82016-12-27 16:00:11 +0000943// Holds info related to the current kernel, e.g. count of SGPRs used.
944// Kernel scope begins at .amdgpu_hsa_kernel directive, ends at next
945// .amdgpu_hsa_kernel or at EOF.
946class KernelScopeInfo {
Eugene Zelenko66203762017-01-21 00:53:49 +0000947 int SgprIndexUnusedMin = -1;
948 int VgprIndexUnusedMin = -1;
949 MCContext *Ctx = nullptr;
Artem Tamazova01cce82016-12-27 16:00:11 +0000950
951 void usesSgprAt(int i) {
952 if (i >= SgprIndexUnusedMin) {
953 SgprIndexUnusedMin = ++i;
954 if (Ctx) {
955 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.sgpr_count"));
956 Sym->setVariableValue(MCConstantExpr::create(SgprIndexUnusedMin, *Ctx));
957 }
958 }
959 }
Eugene Zelenko66203762017-01-21 00:53:49 +0000960
Artem Tamazova01cce82016-12-27 16:00:11 +0000961 void usesVgprAt(int i) {
962 if (i >= VgprIndexUnusedMin) {
963 VgprIndexUnusedMin = ++i;
964 if (Ctx) {
965 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count"));
966 Sym->setVariableValue(MCConstantExpr::create(VgprIndexUnusedMin, *Ctx));
967 }
968 }
969 }
Eugene Zelenko66203762017-01-21 00:53:49 +0000970
Artem Tamazova01cce82016-12-27 16:00:11 +0000971public:
Eugene Zelenko66203762017-01-21 00:53:49 +0000972 KernelScopeInfo() = default;
973
Artem Tamazova01cce82016-12-27 16:00:11 +0000974 void initialize(MCContext &Context) {
975 Ctx = &Context;
976 usesSgprAt(SgprIndexUnusedMin = -1);
977 usesVgprAt(VgprIndexUnusedMin = -1);
978 }
Eugene Zelenko66203762017-01-21 00:53:49 +0000979
Artem Tamazova01cce82016-12-27 16:00:11 +0000980 void usesRegister(RegisterKind RegKind, unsigned DwordRegIndex, unsigned RegWidth) {
981 switch (RegKind) {
982 case IS_SGPR: usesSgprAt(DwordRegIndex + RegWidth - 1); break;
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +0000983 case IS_AGPR: // fall through
Artem Tamazova01cce82016-12-27 16:00:11 +0000984 case IS_VGPR: usesVgprAt(DwordRegIndex + RegWidth - 1); break;
985 default: break;
986 }
987 }
988};
989
Tom Stellard45bb48e2015-06-13 03:28:10 +0000990class AMDGPUAsmParser : public MCTargetAsmParser {
Tom Stellard45bb48e2015-06-13 03:28:10 +0000991 MCAsmParser &Parser;
992
Dmitry Preobrazhensky414e0532017-12-29 13:55:11 +0000993 // Number of extra operands parsed after the first optional operand.
994 // This may be necessary to skip hardcoded mandatory operands.
Dmitry Preobrazhensky4f321ae2018-01-29 14:20:42 +0000995 static const unsigned MAX_OPR_LOOKAHEAD = 8;
Dmitry Preobrazhensky414e0532017-12-29 13:55:11 +0000996
Eugene Zelenko66203762017-01-21 00:53:49 +0000997 unsigned ForcedEncodingSize = 0;
998 bool ForcedDPP = false;
999 bool ForcedSDWA = false;
Artem Tamazova01cce82016-12-27 16:00:11 +00001000 KernelScopeInfo KernelScope;
Matt Arsenault68802d32015-11-05 03:11:27 +00001001
Tom Stellard45bb48e2015-06-13 03:28:10 +00001002 /// @name Auto-generated Match Functions
1003 /// {
1004
1005#define GET_ASSEMBLER_HEADER
1006#include "AMDGPUGenAsmMatcher.inc"
1007
1008 /// }
1009
Tom Stellard347ac792015-06-26 21:15:07 +00001010private:
Artem Tamazov25478d82016-12-29 15:41:52 +00001011 bool ParseAsAbsoluteExpression(uint32_t &Ret);
Scott Linder1e8c2c72018-06-21 19:38:56 +00001012 bool OutOfRangeError(SMRange Range);
1013 /// Calculate VGPR/SGPR blocks required for given target, reserved
1014 /// registers, and user-specified NextFreeXGPR values.
1015 ///
1016 /// \param Features [in] Target features, used for bug corrections.
1017 /// \param VCCUsed [in] Whether VCC special SGPR is reserved.
1018 /// \param FlatScrUsed [in] Whether FLAT_SCRATCH special SGPR is reserved.
1019 /// \param XNACKUsed [in] Whether XNACK_MASK special SGPR is reserved.
Stanislav Mekhanoshin8bcc9bb2019-06-13 19:18:29 +00001020 /// \param EnableWavefrontSize32 [in] Value of ENABLE_WAVEFRONT_SIZE32 kernel
1021 /// descriptor field, if valid.
Scott Linder1e8c2c72018-06-21 19:38:56 +00001022 /// \param NextFreeVGPR [in] Max VGPR number referenced, plus one.
1023 /// \param VGPRRange [in] Token range, used for VGPR diagnostics.
1024 /// \param NextFreeSGPR [in] Max SGPR number referenced, plus one.
1025 /// \param SGPRRange [in] Token range, used for SGPR diagnostics.
1026 /// \param VGPRBlocks [out] Result VGPR block count.
1027 /// \param SGPRBlocks [out] Result SGPR block count.
1028 bool calculateGPRBlocks(const FeatureBitset &Features, bool VCCUsed,
1029 bool FlatScrUsed, bool XNACKUsed,
Stanislav Mekhanoshin8bcc9bb2019-06-13 19:18:29 +00001030 Optional<bool> EnableWavefrontSize32, unsigned NextFreeVGPR,
1031 SMRange VGPRRange, unsigned NextFreeSGPR,
1032 SMRange SGPRRange, unsigned &VGPRBlocks,
1033 unsigned &SGPRBlocks);
Scott Linder1e8c2c72018-06-21 19:38:56 +00001034 bool ParseDirectiveAMDGCNTarget();
1035 bool ParseDirectiveAMDHSAKernel();
Tom Stellard347ac792015-06-26 21:15:07 +00001036 bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor);
1037 bool ParseDirectiveHSACodeObjectVersion();
1038 bool ParseDirectiveHSACodeObjectISA();
Tom Stellardff7416b2015-06-26 21:58:31 +00001039 bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header);
1040 bool ParseDirectiveAMDKernelCodeT();
Matt Arsenault68802d32015-11-05 03:11:27 +00001041 bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const;
Tom Stellard1e1b05d2015-11-06 11:45:14 +00001042 bool ParseDirectiveAMDGPUHsaKernel();
Konstantin Zhuravlyovc3beb6a2017-10-11 22:41:09 +00001043
Konstantin Zhuravlyov9c05b2b2017-10-14 15:40:33 +00001044 bool ParseDirectiveISAVersion();
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +00001045 bool ParseDirectiveHSAMetadata();
Tim Renoufe7bd52f2019-03-20 18:47:21 +00001046 bool ParseDirectivePALMetadataBegin();
Konstantin Zhuravlyovc3beb6a2017-10-11 22:41:09 +00001047 bool ParseDirectivePALMetadata();
Nicolai Haehnle08e8cb52019-06-25 11:51:35 +00001048 bool ParseDirectiveAMDGPULDS();
Konstantin Zhuravlyovc3beb6a2017-10-11 22:41:09 +00001049
Tim Renoufe7bd52f2019-03-20 18:47:21 +00001050 /// Common code to parse out a block of text (typically YAML) between start and
1051 /// end directives.
1052 bool ParseToEndDirective(const char *AssemblerDirectiveBegin,
1053 const char *AssemblerDirectiveEnd,
1054 std::string &CollectString);
1055
Matt Arsenaultf15da6c2017-02-03 20:49:51 +00001056 bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth,
1057 RegisterKind RegKind, unsigned Reg1,
1058 unsigned RegNum);
1059 bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg,
1060 unsigned& RegNum, unsigned& RegWidth,
1061 unsigned *DwordRegIndex);
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00001062 bool isRegister();
1063 bool isRegister(const AsmToken &Token, const AsmToken &NextToken) const;
Scott Linder1e8c2c72018-06-21 19:38:56 +00001064 Optional<StringRef> getGprCountSymbolName(RegisterKind RegKind);
1065 void initializeGprCountSymbol(RegisterKind RegKind);
1066 bool updateGprCountSymbols(RegisterKind RegKind, unsigned DwordRegIndex,
1067 unsigned RegWidth);
Matt Arsenaultf15da6c2017-02-03 20:49:51 +00001068 void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands,
Dmitry Preobrazhenskyd98c97b2018-03-12 17:29:24 +00001069 bool IsAtomic, bool IsAtomicReturn, bool IsLds = false);
Matt Arsenaultf15da6c2017-02-03 20:49:51 +00001070 void cvtDSImpl(MCInst &Inst, const OperandVector &Operands,
1071 bool IsGdsHardcoded);
Tom Stellard347ac792015-06-26 21:15:07 +00001072
Tom Stellard45bb48e2015-06-13 03:28:10 +00001073public:
Tom Stellard88e0b252015-10-06 15:57:53 +00001074 enum AMDGPUMatchResultTy {
1075 Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY
1076 };
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00001077 enum OperandMode {
1078 OperandMode_Default,
1079 OperandMode_NSA,
1080 };
Tom Stellard88e0b252015-10-06 15:57:53 +00001081
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001082 using OptionalImmIndexMap = std::map<AMDGPUOperand::ImmTy, unsigned>;
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001083
Akira Hatanakab11ef082015-11-14 06:35:56 +00001084 AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser,
Tom Stellard45bb48e2015-06-13 03:28:10 +00001085 const MCInstrInfo &MII,
1086 const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +00001087 : MCTargetAsmParser(Options, STI, MII), Parser(_Parser) {
Akira Hatanakab11ef082015-11-14 06:35:56 +00001088 MCAsmParserExtension::Initialize(Parser);
1089
Konstantin Zhuravlyov972948b2017-02-27 07:55:17 +00001090 if (getFeatureBits().none()) {
Tom Stellard45bb48e2015-06-13 03:28:10 +00001091 // Set default features.
Matt Arsenault45c165b2019-04-03 00:01:03 +00001092 copySTI().ToggleFeature("southern-islands");
Tom Stellard45bb48e2015-06-13 03:28:10 +00001093 }
1094
Konstantin Zhuravlyov972948b2017-02-27 07:55:17 +00001095 setAvailableFeatures(ComputeAvailableFeatures(getFeatureBits()));
Artem Tamazov17091362016-06-14 15:03:59 +00001096
1097 {
1098 // TODO: make those pre-defined variables read-only.
1099 // Currently there is none suitable machinery in the core llvm-mc for this.
1100 // MCSymbol::isRedefinable is intended for another purpose, and
1101 // AsmParser::parseDirectiveSet() cannot be specialized for specific target.
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00001102 AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU());
Artem Tamazov17091362016-06-14 15:03:59 +00001103 MCContext &Ctx = getContext();
Scott Linder1e8c2c72018-06-21 19:38:56 +00001104 if (ISA.Major >= 6 && AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) {
1105 MCSymbol *Sym =
1106 Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_number"));
1107 Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx));
Dmitry Preobrazhensky62a03182019-02-08 13:51:31 +00001108 Sym = Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_minor"));
1109 Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx));
1110 Sym = Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_stepping"));
1111 Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx));
Scott Linder1e8c2c72018-06-21 19:38:56 +00001112 } else {
1113 MCSymbol *Sym =
1114 Ctx.getOrCreateSymbol(Twine(".option.machine_version_major"));
1115 Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx));
1116 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_minor"));
1117 Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx));
1118 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_stepping"));
1119 Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx));
1120 }
1121 if (ISA.Major >= 6 && AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) {
1122 initializeGprCountSymbol(IS_VGPR);
1123 initializeGprCountSymbol(IS_SGPR);
1124 } else
1125 KernelScope.initialize(getContext());
Artem Tamazov17091362016-06-14 15:03:59 +00001126 }
Tom Stellard45bb48e2015-06-13 03:28:10 +00001127 }
1128
Dmitry Preobrazhensky3afbd822018-01-10 14:22:19 +00001129 bool hasXNACK() const {
1130 return AMDGPU::hasXNACK(getSTI());
1131 }
1132
Dmitry Preobrazhenskye3271ae2018-02-05 12:45:43 +00001133 bool hasMIMG_R128() const {
1134 return AMDGPU::hasMIMG_R128(getSTI());
1135 }
1136
Dmitry Preobrazhensky0a1ff462018-02-05 14:18:53 +00001137 bool hasPackedD16() const {
1138 return AMDGPU::hasPackedD16(getSTI());
1139 }
1140
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001141 bool isSI() const {
1142 return AMDGPU::isSI(getSTI());
1143 }
1144
1145 bool isCI() const {
1146 return AMDGPU::isCI(getSTI());
1147 }
1148
1149 bool isVI() const {
1150 return AMDGPU::isVI(getSTI());
1151 }
1152
Sam Koltonf7659d712017-05-23 10:08:55 +00001153 bool isGFX9() const {
1154 return AMDGPU::isGFX9(getSTI());
1155 }
1156
Stanislav Mekhanoshincee607e2019-04-24 17:03:15 +00001157 bool isGFX10() const {
1158 return AMDGPU::isGFX10(getSTI());
1159 }
1160
Matt Arsenault26faed32016-12-05 22:26:17 +00001161 bool hasInv2PiInlineImm() const {
Konstantin Zhuravlyov972948b2017-02-27 07:55:17 +00001162 return getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm];
Matt Arsenault26faed32016-12-05 22:26:17 +00001163 }
1164
Matt Arsenaultfd023142017-06-12 15:55:58 +00001165 bool hasFlatOffsets() const {
1166 return getFeatureBits()[AMDGPU::FeatureFlatInstOffsets];
1167 }
1168
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001169 bool hasSGPR102_SGPR103() const {
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00001170 return !isVI() && !isGFX9();
1171 }
1172
1173 bool hasSGPR104_SGPR105() const {
1174 return isGFX10();
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001175 }
1176
Dmitry Preobrazhenskyff64aa52017-08-16 13:51:56 +00001177 bool hasIntClamp() const {
1178 return getFeatureBits()[AMDGPU::FeatureIntClamp];
1179 }
1180
Tom Stellard347ac792015-06-26 21:15:07 +00001181 AMDGPUTargetStreamer &getTargetStreamer() {
1182 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
1183 return static_cast<AMDGPUTargetStreamer &>(TS);
1184 }
Matt Arsenault37fefd62016-06-10 02:18:02 +00001185
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001186 const MCRegisterInfo *getMRI() const {
1187 // We need this const_cast because for some reason getContext() is not const
1188 // in MCAsmParser.
1189 return const_cast<AMDGPUAsmParser*>(this)->getContext().getRegisterInfo();
1190 }
1191
1192 const MCInstrInfo *getMII() const {
1193 return &MII;
1194 }
1195
Konstantin Zhuravlyov972948b2017-02-27 07:55:17 +00001196 const FeatureBitset &getFeatureBits() const {
1197 return getSTI().getFeatureBits();
1198 }
1199
Sam Kolton05ef1c92016-06-03 10:27:37 +00001200 void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; }
1201 void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; }
1202 void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; }
Tom Stellard347ac792015-06-26 21:15:07 +00001203
Sam Kolton05ef1c92016-06-03 10:27:37 +00001204 unsigned getForcedEncodingSize() const { return ForcedEncodingSize; }
1205 bool isForcedVOP3() const { return ForcedEncodingSize == 64; }
1206 bool isForcedDPP() const { return ForcedDPP; }
1207 bool isForcedSDWA() const { return ForcedSDWA; }
Matt Arsenault5f45e782017-01-09 18:44:11 +00001208 ArrayRef<unsigned> getMatchedVariants() const;
Tom Stellard45bb48e2015-06-13 03:28:10 +00001209
Valery Pykhtin0f97f172016-03-14 07:43:42 +00001210 std::unique_ptr<AMDGPUOperand> parseRegister();
Tom Stellard45bb48e2015-06-13 03:28:10 +00001211 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
1212 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
Sam Kolton11de3702016-05-24 12:38:33 +00001213 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
1214 unsigned Kind) override;
Tom Stellard45bb48e2015-06-13 03:28:10 +00001215 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1216 OperandVector &Operands, MCStreamer &Out,
1217 uint64_t &ErrorInfo,
1218 bool MatchingInlineAsm) override;
1219 bool ParseDirective(AsmToken DirectiveID) override;
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00001220 OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic,
1221 OperandMode Mode = OperandMode_Default);
Sam Kolton05ef1c92016-06-03 10:27:37 +00001222 StringRef parseMnemonicSuffix(StringRef Name);
Tom Stellard45bb48e2015-06-13 03:28:10 +00001223 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
1224 SMLoc NameLoc, OperandVector &Operands) override;
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001225 //bool ProcessInstruction(MCInst &Inst);
Tom Stellard45bb48e2015-06-13 03:28:10 +00001226
Sam Kolton11de3702016-05-24 12:38:33 +00001227 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001228
Eugene Zelenko2bc2f332016-12-09 22:06:55 +00001229 OperandMatchResultTy
1230 parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
Matt Arsenaultf15da6c2017-02-03 20:49:51 +00001231 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
Eugene Zelenko2bc2f332016-12-09 22:06:55 +00001232 bool (*ConvertResult)(int64_t &) = nullptr);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001233
Dmitry Preobrazhensky7773fc42019-05-22 13:59:01 +00001234 OperandMatchResultTy
1235 parseOperandArrayWithPrefix(const char *Prefix,
1236 OperandVector &Operands,
1237 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
1238 bool (*ConvertResult)(int64_t&) = nullptr);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001239
Eugene Zelenko2bc2f332016-12-09 22:06:55 +00001240 OperandMatchResultTy
1241 parseNamedBit(const char *Name, OperandVector &Operands,
Matt Arsenaultf15da6c2017-02-03 20:49:51 +00001242 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone);
Eugene Zelenko2bc2f332016-12-09 22:06:55 +00001243 OperandMatchResultTy parseStringWithPrefix(StringRef Prefix,
1244 StringRef &Value);
Tom Stellard45bb48e2015-06-13 03:28:10 +00001245
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +00001246 bool isModifier();
1247 bool isOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const;
1248 bool isRegOrOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const;
1249 bool isNamedOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const;
1250 bool isOpcodeModifierWithVal(const AsmToken &Token, const AsmToken &NextToken) const;
Dmitry Preobrazhenskye2707f52019-04-22 14:35:47 +00001251 bool parseSP3NegModifier();
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00001252 OperandMatchResultTy parseImm(OperandVector &Operands, bool HasSP3AbsModifier = false);
Sam Kolton9772eb32017-01-11 11:46:30 +00001253 OperandMatchResultTy parseReg(OperandVector &Operands);
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00001254 OperandMatchResultTy parseRegOrImm(OperandVector &Operands, bool HasSP3AbsMod = false);
Sam Kolton9772eb32017-01-11 11:46:30 +00001255 OperandMatchResultTy parseRegOrImmWithFPInputMods(OperandVector &Operands, bool AllowImm = true);
1256 OperandMatchResultTy parseRegOrImmWithIntInputMods(OperandVector &Operands, bool AllowImm = true);
1257 OperandMatchResultTy parseRegWithFPInputMods(OperandVector &Operands);
1258 OperandMatchResultTy parseRegWithIntInputMods(OperandVector &Operands);
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00001259 OperandMatchResultTy parseVReg32OrOff(OperandVector &Operands);
Tim Renouf35484c92018-08-21 11:06:05 +00001260 OperandMatchResultTy parseDfmtNfmt(OperandVector &Operands);
Sam Kolton1bdcef72016-05-23 09:59:02 +00001261
Tom Stellard45bb48e2015-06-13 03:28:10 +00001262 void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands);
Artem Tamazov43b61562017-02-03 12:47:30 +00001263 void cvtDS(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, false); }
1264 void cvtDSGds(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, true); }
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00001265 void cvtExp(MCInst &Inst, const OperandVector &Operands);
Tom Stellard45bb48e2015-06-13 03:28:10 +00001266
1267 bool parseCnt(int64_t &IntVal);
1268 OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);
Nikolay Haustov4f672a32016-04-29 09:02:30 +00001269 OperandMatchResultTy parseHwreg(OperandVector &Operands);
Sam Kolton11de3702016-05-24 12:38:33 +00001270
Artem Tamazovebe71ce2016-05-06 17:48:48 +00001271private:
1272 struct OperandInfoTy {
1273 int64_t Id;
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001274 bool IsSymbolic = false;
Dmitry Preobrazhensky1d572ce2019-06-28 14:14:02 +00001275 bool IsDefined = false;
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001276
1277 OperandInfoTy(int64_t Id_) : Id(Id_) {}
Artem Tamazovebe71ce2016-05-06 17:48:48 +00001278 };
Sam Kolton11de3702016-05-24 12:38:33 +00001279
Dmitry Preobrazhensky1d572ce2019-06-28 14:14:02 +00001280 bool parseSendMsgBody(OperandInfoTy &Msg, OperandInfoTy &Op, OperandInfoTy &Stream);
Dmitry Preobrazhenskyd12966c2019-06-28 15:22:47 +00001281 bool validateSendMsg(const OperandInfoTy &Msg,
Dmitry Preobrazhensky1d572ce2019-06-28 14:14:02 +00001282 const OperandInfoTy &Op,
1283 const OperandInfoTy &Stream,
1284 const SMLoc Loc);
1285
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00001286 bool parseHwregBody(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width);
Dmitry Preobrazhensky2eff0312019-07-08 14:27:37 +00001287 bool validateHwreg(const OperandInfoTy &HwReg,
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00001288 const int64_t Offset,
1289 const int64_t Width,
1290 const SMLoc Loc);
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00001291
1292 void errorExpTgt();
1293 OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val);
Dmitry Preobrazhensky2eff0312019-07-08 14:27:37 +00001294 SMLoc getFlatOffsetLoc(const OperandVector &Operands) const;
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00001295
Dmitry Preobrazhensky2eff0312019-07-08 14:27:37 +00001296 bool validateInstruction(const MCInst &Inst, const SMLoc &IDLoc, const OperandVector &Operands);
1297 bool validateFlatOffset(const MCInst &Inst, const OperandVector &Operands);
Dmitry Preobrazhensky61105ba2019-01-18 13:57:43 +00001298 bool validateSOPLiteral(const MCInst &Inst) const;
Dmitry Preobrazhenskydc4ac822017-06-21 14:41:34 +00001299 bool validateConstantBusLimitations(const MCInst &Inst);
1300 bool validateEarlyClobberLimitations(const MCInst &Inst);
Dmitry Preobrazhenskyff64aa52017-08-16 13:51:56 +00001301 bool validateIntClampSupported(const MCInst &Inst);
Dmitry Preobrazhensky70682812018-01-26 16:42:51 +00001302 bool validateMIMGAtomicDMask(const MCInst &Inst);
Dmitry Preobrazhenskyda4a7c02018-03-12 15:03:34 +00001303 bool validateMIMGGatherDMask(const MCInst &Inst);
Dmitry Preobrazhensky70682812018-01-26 16:42:51 +00001304 bool validateMIMGDataSize(const MCInst &Inst);
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00001305 bool validateMIMGAddrSize(const MCInst &Inst);
Dmitry Preobrazhenskye3271ae2018-02-05 12:45:43 +00001306 bool validateMIMGD16(const MCInst &Inst);
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00001307 bool validateMIMGDim(const MCInst &Inst);
Dmitry Preobrazhensky942c2732019-02-08 14:57:37 +00001308 bool validateLdsDirect(const MCInst &Inst);
Stanislav Mekhanoshin5f581c92019-06-12 17:52:51 +00001309 bool validateOpSel(const MCInst &Inst);
Stanislav Mekhanoshin8bcc9bb2019-06-13 19:18:29 +00001310 bool validateVccOperand(unsigned Reg) const;
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00001311 bool validateVOP3Literal(const MCInst &Inst) const;
Dmitry Preobrazhenskyfe2ee4c2019-09-02 12:50:05 +00001312 unsigned getConstantBusLimit(unsigned Opcode) const;
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00001313 bool usesConstantBus(const MCInst &Inst, unsigned OpIdx);
1314 bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const;
1315 unsigned findImplicitSGPRReadInVOP(const MCInst &Inst) const;
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00001316
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00001317 bool isId(const StringRef Id) const;
1318 bool isId(const AsmToken &Token, const StringRef Id) const;
1319 bool isToken(const AsmToken::TokenKind Kind) const;
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00001320 bool trySkipId(const StringRef Id);
Dmitry Preobrazhensky198611b2019-05-17 16:04:17 +00001321 bool trySkipId(const StringRef Id, const AsmToken::TokenKind Kind);
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00001322 bool trySkipToken(const AsmToken::TokenKind Kind);
1323 bool skipToken(const AsmToken::TokenKind Kind, const StringRef ErrMsg);
1324 bool parseString(StringRef &Val, const StringRef ErrMsg = "expected a string");
Dmitry Preobrazhenskye2707f52019-04-22 14:35:47 +00001325 void peekTokens(MutableArrayRef<AsmToken> Tokens);
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00001326 AsmToken::TokenKind getTokenKind() const;
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00001327 bool parseExpr(int64_t &Imm);
Dmitry Preobrazhensky4ccb7f82019-07-19 13:12:47 +00001328 bool parseExpr(OperandVector &Operands);
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00001329 StringRef getTokenStr() const;
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00001330 AsmToken peekToken();
1331 AsmToken getToken() const;
1332 SMLoc getLoc() const;
1333 void lex();
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00001334
Artem Tamazovebe71ce2016-05-06 17:48:48 +00001335public:
Sam Kolton11de3702016-05-24 12:38:33 +00001336 OperandMatchResultTy parseOptionalOperand(OperandVector &Operands);
Dmitry Preobrazhensky414e0532017-12-29 13:55:11 +00001337 OperandMatchResultTy parseOptionalOpr(OperandVector &Operands);
Sam Kolton11de3702016-05-24 12:38:33 +00001338
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00001339 OperandMatchResultTy parseExpTgt(OperandVector &Operands);
Artem Tamazovebe71ce2016-05-06 17:48:48 +00001340 OperandMatchResultTy parseSendMsgOp(OperandVector &Operands);
Matt Arsenault0e8a2992016-12-15 20:40:20 +00001341 OperandMatchResultTy parseInterpSlot(OperandVector &Operands);
1342 OperandMatchResultTy parseInterpAttr(OperandVector &Operands);
Tom Stellard45bb48e2015-06-13 03:28:10 +00001343 OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands);
Stanislav Mekhanoshin8bcc9bb2019-06-13 19:18:29 +00001344 OperandMatchResultTy parseBoolReg(OperandVector &Operands);
Tom Stellard45bb48e2015-06-13 03:28:10 +00001345
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00001346 bool parseSwizzleOperands(const unsigned OpNum, int64_t* Op,
1347 const unsigned MinVal,
1348 const unsigned MaxVal,
1349 const StringRef ErrMsg);
1350 OperandMatchResultTy parseSwizzleOp(OperandVector &Operands);
1351 bool parseSwizzleOffset(int64_t &Imm);
1352 bool parseSwizzleMacro(int64_t &Imm);
1353 bool parseSwizzleQuadPerm(int64_t &Imm);
1354 bool parseSwizzleBitmaskPerm(int64_t &Imm);
1355 bool parseSwizzleBroadcast(int64_t &Imm);
1356 bool parseSwizzleSwap(int64_t &Imm);
1357 bool parseSwizzleReverse(int64_t &Imm);
1358
Dmitry Preobrazhenskyef920352019-02-27 13:12:12 +00001359 OperandMatchResultTy parseGPRIdxMode(OperandVector &Operands);
1360 int64_t parseGPRIdxMacro();
1361
Artem Tamazov8ce1f712016-05-19 12:22:39 +00001362 void cvtMubuf(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false); }
1363 void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, false); }
1364 void cvtMubufAtomicReturn(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, true); }
Dmitry Preobrazhenskyd98c97b2018-03-12 17:29:24 +00001365 void cvtMubufLds(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false, true); }
David Stuttard70e8bc12017-06-22 16:29:22 +00001366 void cvtMtbuf(MCInst &Inst, const OperandVector &Operands);
1367
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00001368 AMDGPUOperand::Ptr defaultDLC() const;
Sam Kolton5f10a132016-05-06 11:31:17 +00001369 AMDGPUOperand::Ptr defaultGLC() const;
1370 AMDGPUOperand::Ptr defaultSLC() const;
Sam Kolton5f10a132016-05-06 11:31:17 +00001371
Artem Tamazov54bfd542016-10-31 16:07:39 +00001372 AMDGPUOperand::Ptr defaultSMRDOffset8() const;
1373 AMDGPUOperand::Ptr defaultSMRDOffset20() const;
Sam Kolton5f10a132016-05-06 11:31:17 +00001374 AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const;
Dmitry Preobrazhensky2eff0312019-07-08 14:27:37 +00001375 AMDGPUOperand::Ptr defaultFlatOffset() const;
Matt Arsenault37fefd62016-06-10 02:18:02 +00001376
Nikolay Haustov4f672a32016-04-29 09:02:30 +00001377 OperandMatchResultTy parseOModOperand(OperandVector &Operands);
1378
Sam Kolton10ac2fd2017-07-07 15:21:52 +00001379 void cvtVOP3(MCInst &Inst, const OperandVector &Operands,
1380 OptionalImmIndexMap &OptionalIdx);
Dmitry Preobrazhenskyabf28392017-07-21 13:54:11 +00001381 void cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands);
Tom Stellard45bb48e2015-06-13 03:28:10 +00001382 void cvtVOP3(MCInst &Inst, const OperandVector &Operands);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001383 void cvtVOP3P(MCInst &Inst, const OperandVector &Operands);
Nikolay Haustov2f684f12016-02-26 09:51:05 +00001384
Dmitry Preobrazhensky50805a02017-08-07 13:14:12 +00001385 void cvtVOP3Interp(MCInst &Inst, const OperandVector &Operands);
1386
Sam Kolton10ac2fd2017-07-07 15:21:52 +00001387 void cvtMIMG(MCInst &Inst, const OperandVector &Operands,
1388 bool IsAtomic = false);
Nikolay Haustov5bf46ac12016-03-04 10:39:50 +00001389 void cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands);
Sam Koltondfa29f72016-03-09 12:29:31 +00001390
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00001391 OperandMatchResultTy parseDim(OperandVector &Operands);
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00001392 OperandMatchResultTy parseDPP8(OperandVector &Operands);
Sam Kolton11de3702016-05-24 12:38:33 +00001393 OperandMatchResultTy parseDPPCtrl(OperandVector &Operands);
Sam Kolton5f10a132016-05-06 11:31:17 +00001394 AMDGPUOperand::Ptr defaultRowMask() const;
1395 AMDGPUOperand::Ptr defaultBankMask() const;
1396 AMDGPUOperand::Ptr defaultBoundCtrl() const;
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00001397 AMDGPUOperand::Ptr defaultFI() const;
1398 void cvtDPP(MCInst &Inst, const OperandVector &Operands, bool IsDPP8 = false);
1399 void cvtDPP8(MCInst &Inst, const OperandVector &Operands) { cvtDPP(Inst, Operands, true); }
Sam Kolton3025e7f2016-04-26 13:33:56 +00001400
Sam Kolton05ef1c92016-06-03 10:27:37 +00001401 OperandMatchResultTy parseSDWASel(OperandVector &Operands, StringRef Prefix,
1402 AMDGPUOperand::ImmTy Type);
Sam Kolton3025e7f2016-04-26 13:33:56 +00001403 OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands);
Sam Kolton945231a2016-06-10 09:57:59 +00001404 void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands);
1405 void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands);
Sam Koltonf7659d712017-05-23 10:08:55 +00001406 void cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands);
Sam Kolton5196b882016-07-01 09:59:21 +00001407 void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands);
1408 void cvtSDWA(MCInst &Inst, const OperandVector &Operands,
Sam Koltonf7659d712017-05-23 10:08:55 +00001409 uint64_t BasicInstType, bool skipVcc = false);
David Stuttard20ea21c2019-03-12 09:52:58 +00001410
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +00001411 AMDGPUOperand::Ptr defaultBLGP() const;
1412 AMDGPUOperand::Ptr defaultCBSZ() const;
1413 AMDGPUOperand::Ptr defaultABID() const;
1414
David Stuttard20ea21c2019-03-12 09:52:58 +00001415 OperandMatchResultTy parseEndpgmOp(OperandVector &Operands);
1416 AMDGPUOperand::Ptr defaultEndpgmImmOperands() const;
Tom Stellard45bb48e2015-06-13 03:28:10 +00001417};
1418
1419struct OptionalOperand {
1420 const char *Name;
1421 AMDGPUOperand::ImmTy Type;
1422 bool IsBit;
Tom Stellard45bb48e2015-06-13 03:28:10 +00001423 bool (*ConvertResult)(int64_t&);
1424};
1425
Eugene Zelenko2bc2f332016-12-09 22:06:55 +00001426} // end anonymous namespace
1427
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001428// May be called with integer type with equivalent bitwidth.
Matt Arsenault4bd72362016-12-10 00:39:12 +00001429static const fltSemantics *getFltSemantics(unsigned Size) {
1430 switch (Size) {
1431 case 4:
Stephan Bergmann17c7f702016-12-14 11:57:17 +00001432 return &APFloat::IEEEsingle();
Matt Arsenault4bd72362016-12-10 00:39:12 +00001433 case 8:
Stephan Bergmann17c7f702016-12-14 11:57:17 +00001434 return &APFloat::IEEEdouble();
Matt Arsenault4bd72362016-12-10 00:39:12 +00001435 case 2:
Stephan Bergmann17c7f702016-12-14 11:57:17 +00001436 return &APFloat::IEEEhalf();
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001437 default:
1438 llvm_unreachable("unsupported fp type");
1439 }
1440}
1441
Matt Arsenault4bd72362016-12-10 00:39:12 +00001442static const fltSemantics *getFltSemantics(MVT VT) {
1443 return getFltSemantics(VT.getSizeInBits() / 8);
1444}
1445
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001446static const fltSemantics *getOpFltSemantics(uint8_t OperandType) {
1447 switch (OperandType) {
1448 case AMDGPU::OPERAND_REG_IMM_INT32:
1449 case AMDGPU::OPERAND_REG_IMM_FP32:
1450 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1451 case AMDGPU::OPERAND_REG_INLINE_C_FP32:
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +00001452 case AMDGPU::OPERAND_REG_INLINE_AC_INT32:
1453 case AMDGPU::OPERAND_REG_INLINE_AC_FP32:
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001454 return &APFloat::IEEEsingle();
1455 case AMDGPU::OPERAND_REG_IMM_INT64:
1456 case AMDGPU::OPERAND_REG_IMM_FP64:
1457 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
1458 case AMDGPU::OPERAND_REG_INLINE_C_FP64:
1459 return &APFloat::IEEEdouble();
1460 case AMDGPU::OPERAND_REG_IMM_INT16:
1461 case AMDGPU::OPERAND_REG_IMM_FP16:
1462 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1463 case AMDGPU::OPERAND_REG_INLINE_C_FP16:
1464 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1465 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +00001466 case AMDGPU::OPERAND_REG_INLINE_AC_INT16:
1467 case AMDGPU::OPERAND_REG_INLINE_AC_FP16:
1468 case AMDGPU::OPERAND_REG_INLINE_AC_V2INT16:
1469 case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16:
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00001470 case AMDGPU::OPERAND_REG_IMM_V2INT16:
1471 case AMDGPU::OPERAND_REG_IMM_V2FP16:
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001472 return &APFloat::IEEEhalf();
1473 default:
1474 llvm_unreachable("unsupported fp type");
1475 }
1476}
1477
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001478//===----------------------------------------------------------------------===//
1479// Operand
1480//===----------------------------------------------------------------------===//
1481
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001482static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT) {
1483 bool Lost;
1484
1485 // Convert literal to single precision
1486 APFloat::opStatus Status = FPLiteral.convert(*getFltSemantics(VT),
1487 APFloat::rmNearestTiesToEven,
1488 &Lost);
1489 // We allow precision lost but not overflow or underflow
1490 if (Status != APFloat::opOK &&
1491 Lost &&
1492 ((Status & APFloat::opOverflow) != 0 ||
1493 (Status & APFloat::opUnderflow) != 0)) {
1494 return false;
1495 }
1496
1497 return true;
1498}
1499
Dmitry Preobrazhenskyd6827ce2019-03-29 14:50:20 +00001500static bool isSafeTruncation(int64_t Val, unsigned Size) {
1501 return isUIntN(Size, Val) || isIntN(Size, Val);
1502}
1503
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001504bool AMDGPUOperand::isInlinableImm(MVT type) const {
Dmitry Preobrazhensky137976f2019-03-20 15:40:52 +00001505
1506 // This is a hack to enable named inline values like
1507 // shared_base with both 32-bit and 64-bit operands.
1508 // Note that these values are defined as
1509 // 32-bit operands only.
1510 if (isInlineValue()) {
1511 return true;
1512 }
1513
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001514 if (!isImmTy(ImmTyNone)) {
1515 // Only plain immediates are inlinable (e.g. "clamp" attribute is not)
1516 return false;
1517 }
1518 // TODO: We should avoid using host float here. It would be better to
1519 // check the float bit values which is what a few other places do.
1520 // We've had bot failures before due to weird NaN support on mips hosts.
1521
1522 APInt Literal(64, Imm.Val);
1523
1524 if (Imm.IsFPImm) { // We got fp literal token
1525 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
Matt Arsenault26faed32016-12-05 22:26:17 +00001526 return AMDGPU::isInlinableLiteral64(Imm.Val,
1527 AsmParser->hasInv2PiInlineImm());
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001528 }
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001529
Stephan Bergmann17c7f702016-12-14 11:57:17 +00001530 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001531 if (!canLosslesslyConvertToFPType(FPLiteral, type))
1532 return false;
1533
Sam Kolton9dffada2017-01-17 15:26:02 +00001534 if (type.getScalarSizeInBits() == 16) {
1535 return AMDGPU::isInlinableLiteral16(
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001536 static_cast<int16_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
Sam Kolton9dffada2017-01-17 15:26:02 +00001537 AsmParser->hasInv2PiInlineImm());
1538 }
1539
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001540 // Check if single precision literal is inlinable
1541 return AMDGPU::isInlinableLiteral32(
1542 static_cast<int32_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
Matt Arsenault26faed32016-12-05 22:26:17 +00001543 AsmParser->hasInv2PiInlineImm());
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001544 }
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001545
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001546 // We got int literal token.
1547 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
Matt Arsenault26faed32016-12-05 22:26:17 +00001548 return AMDGPU::isInlinableLiteral64(Imm.Val,
1549 AsmParser->hasInv2PiInlineImm());
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001550 }
1551
Dmitry Preobrazhenskyd6827ce2019-03-29 14:50:20 +00001552 if (!isSafeTruncation(Imm.Val, type.getScalarSizeInBits())) {
1553 return false;
1554 }
1555
Matt Arsenault4bd72362016-12-10 00:39:12 +00001556 if (type.getScalarSizeInBits() == 16) {
1557 return AMDGPU::isInlinableLiteral16(
1558 static_cast<int16_t>(Literal.getLoBits(16).getSExtValue()),
1559 AsmParser->hasInv2PiInlineImm());
1560 }
1561
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001562 return AMDGPU::isInlinableLiteral32(
1563 static_cast<int32_t>(Literal.getLoBits(32).getZExtValue()),
Matt Arsenault26faed32016-12-05 22:26:17 +00001564 AsmParser->hasInv2PiInlineImm());
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001565}
1566
1567bool AMDGPUOperand::isLiteralImm(MVT type) const {
Hiroshi Inoue7f46baf2017-07-16 08:11:56 +00001568 // Check that this immediate can be added as literal
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001569 if (!isImmTy(ImmTyNone)) {
1570 return false;
1571 }
1572
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001573 if (!Imm.IsFPImm) {
1574 // We got int literal token.
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001575
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +00001576 if (type == MVT::f64 && hasFPModifiers()) {
1577 // Cannot apply fp modifiers to int literals preserving the same semantics
1578 // for VOP1/2/C and VOP3 because of integer truncation. To avoid ambiguity,
1579 // disable these cases.
1580 return false;
1581 }
1582
Matt Arsenault4bd72362016-12-10 00:39:12 +00001583 unsigned Size = type.getSizeInBits();
1584 if (Size == 64)
1585 Size = 32;
1586
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001587 // FIXME: 64-bit operands can zero extend, sign extend, or pad zeroes for FP
1588 // types.
Dmitry Preobrazhenskyd6827ce2019-03-29 14:50:20 +00001589 return isSafeTruncation(Imm.Val, Size);
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001590 }
Matt Arsenaultc7f28a52016-12-05 22:07:21 +00001591
1592 // We got fp literal token
1593 if (type == MVT::f64) { // Expected 64-bit fp operand
1594 // We would set low 64-bits of literal to zeroes but we accept this literals
1595 return true;
1596 }
1597
1598 if (type == MVT::i64) { // Expected 64-bit int operand
1599 // We don't allow fp literals in 64-bit integer instructions. It is
1600 // unclear how we should encode them.
1601 return false;
1602 }
1603
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00001604 // We allow fp literals with f16x2 operands assuming that the specified
1605 // literal goes into the lower half and the upper half is zero. We also
1606 // require that the literal may be losslesly converted to f16.
1607 MVT ExpectedType = (type == MVT::v2f16)? MVT::f16 :
1608 (type == MVT::v2i16)? MVT::i16 : type;
1609
Stephan Bergmann17c7f702016-12-14 11:57:17 +00001610 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00001611 return canLosslesslyConvertToFPType(FPLiteral, ExpectedType);
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001612}
1613
1614bool AMDGPUOperand::isRegClass(unsigned RCID) const {
Sam Kolton9772eb32017-01-11 11:46:30 +00001615 return isRegKind() && AsmParser->getMRI()->getRegClass(RCID).contains(getReg());
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001616}
1617
Dmitry Preobrazhensky6b65f7c2018-01-17 14:00:48 +00001618bool AMDGPUOperand::isSDWAOperand(MVT type) const {
Sam Kolton549c89d2017-06-21 08:53:38 +00001619 if (AsmParser->isVI())
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +00001620 return isVReg32();
Stanislav Mekhanoshincee607e2019-04-24 17:03:15 +00001621 else if (AsmParser->isGFX9() || AsmParser->isGFX10())
Dmitry Preobrazhensky79042312019-02-27 13:58:48 +00001622 return isRegClass(AMDGPU::VS_32RegClassID) || isInlinableImm(type);
Sam Kolton549c89d2017-06-21 08:53:38 +00001623 else
1624 return false;
1625}
1626
Dmitry Preobrazhensky6b65f7c2018-01-17 14:00:48 +00001627bool AMDGPUOperand::isSDWAFP16Operand() const {
1628 return isSDWAOperand(MVT::f16);
1629}
1630
1631bool AMDGPUOperand::isSDWAFP32Operand() const {
1632 return isSDWAOperand(MVT::f32);
1633}
1634
1635bool AMDGPUOperand::isSDWAInt16Operand() const {
1636 return isSDWAOperand(MVT::i16);
1637}
1638
1639bool AMDGPUOperand::isSDWAInt32Operand() const {
1640 return isSDWAOperand(MVT::i32);
1641}
1642
Stanislav Mekhanoshin8bcc9bb2019-06-13 19:18:29 +00001643bool AMDGPUOperand::isBoolReg() const {
Dmitry Preobrazhensky5e1dd022019-07-24 16:50:17 +00001644 return (AsmParser->getFeatureBits()[AMDGPU::FeatureWavefrontSize64] && isSCSrcB64()) ||
1645 (AsmParser->getFeatureBits()[AMDGPU::FeatureWavefrontSize32] && isSCSrcB32());
Stanislav Mekhanoshin8bcc9bb2019-06-13 19:18:29 +00001646}
1647
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +00001648uint64_t AMDGPUOperand::applyInputFPModifiers(uint64_t Val, unsigned Size) const
1649{
1650 assert(isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
1651 assert(Size == 2 || Size == 4 || Size == 8);
1652
1653 const uint64_t FpSignMask = (1ULL << (Size * 8 - 1));
1654
1655 if (Imm.Mods.Abs) {
1656 Val &= ~FpSignMask;
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001657 }
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +00001658 if (Imm.Mods.Neg) {
1659 Val ^= FpSignMask;
1660 }
1661
1662 return Val;
1663}
1664
1665void AMDGPUOperand::addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers) const {
Matt Arsenault4bd72362016-12-10 00:39:12 +00001666 if (AMDGPU::isSISrcOperand(AsmParser->getMII()->get(Inst.getOpcode()),
1667 Inst.getNumOperands())) {
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +00001668 addLiteralImmOperand(Inst, Imm.Val,
1669 ApplyModifiers &
1670 isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001671 } else {
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +00001672 assert(!isImmTy(ImmTyNone) || !hasModifiers());
1673 Inst.addOperand(MCOperand::createImm(Imm.Val));
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001674 }
1675}
1676
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +00001677void AMDGPUOperand::addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001678 const auto& InstDesc = AsmParser->getMII()->get(Inst.getOpcode());
1679 auto OpNum = Inst.getNumOperands();
1680 // Check that this operand accepts literals
1681 assert(AMDGPU::isSISrcOperand(InstDesc, OpNum));
1682
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +00001683 if (ApplyModifiers) {
1684 assert(AMDGPU::isSISrcFPOperand(InstDesc, OpNum));
1685 const unsigned Size = Imm.IsFPImm ? sizeof(double) : getOperandSize(InstDesc, OpNum);
1686 Val = applyInputFPModifiers(Val, Size);
1687 }
1688
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001689 APInt Literal(64, Val);
1690 uint8_t OpTy = InstDesc.OpInfo[OpNum].OperandType;
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001691
1692 if (Imm.IsFPImm) { // We got fp literal token
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001693 switch (OpTy) {
1694 case AMDGPU::OPERAND_REG_IMM_INT64:
1695 case AMDGPU::OPERAND_REG_IMM_FP64:
1696 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001697 case AMDGPU::OPERAND_REG_INLINE_C_FP64:
Matt Arsenault26faed32016-12-05 22:26:17 +00001698 if (AMDGPU::isInlinableLiteral64(Literal.getZExtValue(),
1699 AsmParser->hasInv2PiInlineImm())) {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001700 Inst.addOperand(MCOperand::createImm(Literal.getZExtValue()));
Matt Arsenault4bd72362016-12-10 00:39:12 +00001701 return;
1702 }
1703
1704 // Non-inlineable
1705 if (AMDGPU::isSISrcFPOperand(InstDesc, OpNum)) { // Expected 64-bit fp operand
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001706 // For fp operands we check if low 32 bits are zeros
1707 if (Literal.getLoBits(32) != 0) {
1708 const_cast<AMDGPUAsmParser *>(AsmParser)->Warning(Inst.getLoc(),
Matt Arsenault4bd72362016-12-10 00:39:12 +00001709 "Can't encode literal as exact 64-bit floating-point operand. "
1710 "Low 32-bits will be set to zero");
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001711 }
Matt Arsenault4bd72362016-12-10 00:39:12 +00001712
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001713 Inst.addOperand(MCOperand::createImm(Literal.lshr(32).getZExtValue()));
Matt Arsenault4bd72362016-12-10 00:39:12 +00001714 return;
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001715 }
Matt Arsenault4bd72362016-12-10 00:39:12 +00001716
1717 // We don't allow fp literals in 64-bit integer instructions. It is
1718 // unclear how we should encode them. This case should be checked earlier
1719 // in predicate methods (isLiteralImm())
1720 llvm_unreachable("fp literal in 64-bit integer instruction.");
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001721
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001722 case AMDGPU::OPERAND_REG_IMM_INT32:
1723 case AMDGPU::OPERAND_REG_IMM_FP32:
1724 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1725 case AMDGPU::OPERAND_REG_INLINE_C_FP32:
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +00001726 case AMDGPU::OPERAND_REG_INLINE_AC_INT32:
1727 case AMDGPU::OPERAND_REG_INLINE_AC_FP32:
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001728 case AMDGPU::OPERAND_REG_IMM_INT16:
1729 case AMDGPU::OPERAND_REG_IMM_FP16:
1730 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1731 case AMDGPU::OPERAND_REG_INLINE_C_FP16:
1732 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00001733 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +00001734 case AMDGPU::OPERAND_REG_INLINE_AC_INT16:
1735 case AMDGPU::OPERAND_REG_INLINE_AC_FP16:
1736 case AMDGPU::OPERAND_REG_INLINE_AC_V2INT16:
1737 case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16:
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00001738 case AMDGPU::OPERAND_REG_IMM_V2INT16:
1739 case AMDGPU::OPERAND_REG_IMM_V2FP16: {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001740 bool lost;
Stephan Bergmann17c7f702016-12-14 11:57:17 +00001741 APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001742 // Convert literal to single precision
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001743 FPLiteral.convert(*getOpFltSemantics(OpTy),
Matt Arsenault4bd72362016-12-10 00:39:12 +00001744 APFloat::rmNearestTiesToEven, &lost);
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001745 // We allow precision lost but not overflow or underflow. This should be
1746 // checked earlier in isLiteralImm()
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001747
1748 uint64_t ImmVal = FPLiteral.bitcastToAPInt().getZExtValue();
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001749 Inst.addOperand(MCOperand::createImm(ImmVal));
Matt Arsenault4bd72362016-12-10 00:39:12 +00001750 return;
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001751 }
Matt Arsenault4bd72362016-12-10 00:39:12 +00001752 default:
1753 llvm_unreachable("invalid operand size");
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001754 }
Matt Arsenault4bd72362016-12-10 00:39:12 +00001755
1756 return;
1757 }
1758
Dmitry Preobrazhenskyd6827ce2019-03-29 14:50:20 +00001759 // We got int literal token.
Matt Arsenault4bd72362016-12-10 00:39:12 +00001760 // Only sign extend inline immediates.
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001761 switch (OpTy) {
1762 case AMDGPU::OPERAND_REG_IMM_INT32:
1763 case AMDGPU::OPERAND_REG_IMM_FP32:
1764 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001765 case AMDGPU::OPERAND_REG_INLINE_C_FP32:
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +00001766 case AMDGPU::OPERAND_REG_INLINE_AC_INT32:
1767 case AMDGPU::OPERAND_REG_INLINE_AC_FP32:
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00001768 case AMDGPU::OPERAND_REG_IMM_V2INT16:
1769 case AMDGPU::OPERAND_REG_IMM_V2FP16:
Dmitry Preobrazhenskyd6827ce2019-03-29 14:50:20 +00001770 if (isSafeTruncation(Val, 32) &&
Matt Arsenault4bd72362016-12-10 00:39:12 +00001771 AMDGPU::isInlinableLiteral32(static_cast<int32_t>(Val),
1772 AsmParser->hasInv2PiInlineImm())) {
1773 Inst.addOperand(MCOperand::createImm(Val));
1774 return;
1775 }
1776
1777 Inst.addOperand(MCOperand::createImm(Val & 0xffffffff));
1778 return;
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001779
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001780 case AMDGPU::OPERAND_REG_IMM_INT64:
1781 case AMDGPU::OPERAND_REG_IMM_FP64:
1782 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001783 case AMDGPU::OPERAND_REG_INLINE_C_FP64:
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001784 if (AMDGPU::isInlinableLiteral64(Val, AsmParser->hasInv2PiInlineImm())) {
Matt Arsenault4bd72362016-12-10 00:39:12 +00001785 Inst.addOperand(MCOperand::createImm(Val));
1786 return;
1787 }
1788
1789 Inst.addOperand(MCOperand::createImm(Lo_32(Val)));
1790 return;
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001791
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001792 case AMDGPU::OPERAND_REG_IMM_INT16:
1793 case AMDGPU::OPERAND_REG_IMM_FP16:
1794 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001795 case AMDGPU::OPERAND_REG_INLINE_C_FP16:
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +00001796 case AMDGPU::OPERAND_REG_INLINE_AC_INT16:
1797 case AMDGPU::OPERAND_REG_INLINE_AC_FP16:
Dmitry Preobrazhenskyd6827ce2019-03-29 14:50:20 +00001798 if (isSafeTruncation(Val, 16) &&
Matt Arsenault4bd72362016-12-10 00:39:12 +00001799 AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val),
1800 AsmParser->hasInv2PiInlineImm())) {
1801 Inst.addOperand(MCOperand::createImm(Val));
1802 return;
1803 }
1804
1805 Inst.addOperand(MCOperand::createImm(Val & 0xffff));
1806 return;
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00001807
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001808 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +00001809 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
1810 case AMDGPU::OPERAND_REG_INLINE_AC_V2INT16:
1811 case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16: {
Dmitry Preobrazhenskyd6827ce2019-03-29 14:50:20 +00001812 assert(isSafeTruncation(Val, 16));
1813 assert(AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val),
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001814 AsmParser->hasInv2PiInlineImm()));
Eugene Zelenko66203762017-01-21 00:53:49 +00001815
Dmitry Preobrazhenskyd6827ce2019-03-29 14:50:20 +00001816 Inst.addOperand(MCOperand::createImm(Val));
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00001817 return;
1818 }
Matt Arsenault4bd72362016-12-10 00:39:12 +00001819 default:
1820 llvm_unreachable("invalid operand size");
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001821 }
1822}
1823
Matt Arsenault4bd72362016-12-10 00:39:12 +00001824template <unsigned Bitwidth>
1825void AMDGPUOperand::addKImmFPOperands(MCInst &Inst, unsigned N) const {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001826 APInt Literal(64, Imm.Val);
Matt Arsenault4bd72362016-12-10 00:39:12 +00001827
1828 if (!Imm.IsFPImm) {
1829 // We got int literal token.
1830 Inst.addOperand(MCOperand::createImm(Literal.getLoBits(Bitwidth).getZExtValue()));
1831 return;
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001832 }
Matt Arsenault4bd72362016-12-10 00:39:12 +00001833
1834 bool Lost;
Stephan Bergmann17c7f702016-12-14 11:57:17 +00001835 APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
Matt Arsenault4bd72362016-12-10 00:39:12 +00001836 FPLiteral.convert(*getFltSemantics(Bitwidth / 8),
1837 APFloat::rmNearestTiesToEven, &Lost);
1838 Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue()));
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001839}
1840
1841void AMDGPUOperand::addRegOperands(MCInst &Inst, unsigned N) const {
1842 Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), AsmParser->getSTI())));
1843}
1844
Dmitry Preobrazhensky137976f2019-03-20 15:40:52 +00001845static bool isInlineValue(unsigned Reg) {
1846 switch (Reg) {
1847 case AMDGPU::SRC_SHARED_BASE:
1848 case AMDGPU::SRC_SHARED_LIMIT:
1849 case AMDGPU::SRC_PRIVATE_BASE:
1850 case AMDGPU::SRC_PRIVATE_LIMIT:
1851 case AMDGPU::SRC_POPS_EXITING_WAVE_ID:
1852 return true;
Dmitry Preobrazhensky9111f352019-06-03 13:51:24 +00001853 case AMDGPU::SRC_VCCZ:
1854 case AMDGPU::SRC_EXECZ:
1855 case AMDGPU::SRC_SCC:
1856 return true;
Dmitry Preobrazhensky9c68edd2019-09-02 13:42:25 +00001857 case AMDGPU::SGPR_NULL:
1858 return true;
Dmitry Preobrazhensky137976f2019-03-20 15:40:52 +00001859 default:
1860 return false;
1861 }
1862}
1863
1864bool AMDGPUOperand::isInlineValue() const {
1865 return isRegKind() && ::isInlineValue(getReg());
1866}
1867
Sam Kolton1eeb11b2016-09-09 14:44:04 +00001868//===----------------------------------------------------------------------===//
1869// AsmParser
1870//===----------------------------------------------------------------------===//
1871
Artem Tamazoveb4d5a92016-04-13 16:18:41 +00001872static int getRegClass(RegisterKind Is, unsigned RegWidth) {
1873 if (Is == IS_VGPR) {
Tom Stellard45bb48e2015-06-13 03:28:10 +00001874 switch (RegWidth) {
Matt Arsenault967c2f52015-11-03 22:50:32 +00001875 default: return -1;
Tom Stellard45bb48e2015-06-13 03:28:10 +00001876 case 1: return AMDGPU::VGPR_32RegClassID;
1877 case 2: return AMDGPU::VReg_64RegClassID;
1878 case 3: return AMDGPU::VReg_96RegClassID;
1879 case 4: return AMDGPU::VReg_128RegClassID;
Stanislav Mekhanoshin5cdacea2019-07-24 16:21:18 +00001880 case 5: return AMDGPU::VReg_160RegClassID;
Tom Stellard45bb48e2015-06-13 03:28:10 +00001881 case 8: return AMDGPU::VReg_256RegClassID;
1882 case 16: return AMDGPU::VReg_512RegClassID;
Stanislav Mekhanoshin5cdacea2019-07-24 16:21:18 +00001883 case 32: return AMDGPU::VReg_1024RegClassID;
Tom Stellard45bb48e2015-06-13 03:28:10 +00001884 }
Artem Tamazoveb4d5a92016-04-13 16:18:41 +00001885 } else if (Is == IS_TTMP) {
1886 switch (RegWidth) {
1887 default: return -1;
1888 case 1: return AMDGPU::TTMP_32RegClassID;
1889 case 2: return AMDGPU::TTMP_64RegClassID;
Artem Tamazov38e496b2016-04-29 17:04:50 +00001890 case 4: return AMDGPU::TTMP_128RegClassID;
Dmitry Preobrazhensky27134952017-12-22 15:18:06 +00001891 case 8: return AMDGPU::TTMP_256RegClassID;
1892 case 16: return AMDGPU::TTMP_512RegClassID;
Artem Tamazoveb4d5a92016-04-13 16:18:41 +00001893 }
1894 } else if (Is == IS_SGPR) {
1895 switch (RegWidth) {
1896 default: return -1;
1897 case 1: return AMDGPU::SGPR_32RegClassID;
1898 case 2: return AMDGPU::SGPR_64RegClassID;
Artem Tamazov38e496b2016-04-29 17:04:50 +00001899 case 4: return AMDGPU::SGPR_128RegClassID;
Dmitry Preobrazhensky27134952017-12-22 15:18:06 +00001900 case 8: return AMDGPU::SGPR_256RegClassID;
1901 case 16: return AMDGPU::SGPR_512RegClassID;
Artem Tamazoveb4d5a92016-04-13 16:18:41 +00001902 }
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +00001903 } else if (Is == IS_AGPR) {
1904 switch (RegWidth) {
1905 default: return -1;
1906 case 1: return AMDGPU::AGPR_32RegClassID;
1907 case 2: return AMDGPU::AReg_64RegClassID;
1908 case 4: return AMDGPU::AReg_128RegClassID;
1909 case 16: return AMDGPU::AReg_512RegClassID;
1910 case 32: return AMDGPU::AReg_1024RegClassID;
1911 }
Tom Stellard45bb48e2015-06-13 03:28:10 +00001912 }
Artem Tamazoveb4d5a92016-04-13 16:18:41 +00001913 return -1;
Tom Stellard45bb48e2015-06-13 03:28:10 +00001914}
1915
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001916static unsigned getSpecialRegForName(StringRef RegName) {
Tom Stellard45bb48e2015-06-13 03:28:10 +00001917 return StringSwitch<unsigned>(RegName)
1918 .Case("exec", AMDGPU::EXEC)
1919 .Case("vcc", AMDGPU::VCC)
Matt Arsenaultaac9b492015-11-03 22:50:34 +00001920 .Case("flat_scratch", AMDGPU::FLAT_SCR)
Dmitry Preobrazhensky3afbd822018-01-10 14:22:19 +00001921 .Case("xnack_mask", AMDGPU::XNACK_MASK)
Dmitry Preobrazhensky137976f2019-03-20 15:40:52 +00001922 .Case("shared_base", AMDGPU::SRC_SHARED_BASE)
1923 .Case("src_shared_base", AMDGPU::SRC_SHARED_BASE)
1924 .Case("shared_limit", AMDGPU::SRC_SHARED_LIMIT)
1925 .Case("src_shared_limit", AMDGPU::SRC_SHARED_LIMIT)
1926 .Case("private_base", AMDGPU::SRC_PRIVATE_BASE)
1927 .Case("src_private_base", AMDGPU::SRC_PRIVATE_BASE)
1928 .Case("private_limit", AMDGPU::SRC_PRIVATE_LIMIT)
1929 .Case("src_private_limit", AMDGPU::SRC_PRIVATE_LIMIT)
1930 .Case("pops_exiting_wave_id", AMDGPU::SRC_POPS_EXITING_WAVE_ID)
1931 .Case("src_pops_exiting_wave_id", AMDGPU::SRC_POPS_EXITING_WAVE_ID)
Dmitry Preobrazhensky942c2732019-02-08 14:57:37 +00001932 .Case("lds_direct", AMDGPU::LDS_DIRECT)
1933 .Case("src_lds_direct", AMDGPU::LDS_DIRECT)
Tom Stellard45bb48e2015-06-13 03:28:10 +00001934 .Case("m0", AMDGPU::M0)
Dmitry Preobrazhensky9111f352019-06-03 13:51:24 +00001935 .Case("vccz", AMDGPU::SRC_VCCZ)
1936 .Case("src_vccz", AMDGPU::SRC_VCCZ)
1937 .Case("execz", AMDGPU::SRC_EXECZ)
1938 .Case("src_execz", AMDGPU::SRC_EXECZ)
1939 .Case("scc", AMDGPU::SRC_SCC)
1940 .Case("src_scc", AMDGPU::SRC_SCC)
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001941 .Case("tba", AMDGPU::TBA)
1942 .Case("tma", AMDGPU::TMA)
Matt Arsenaultaac9b492015-11-03 22:50:34 +00001943 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
1944 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
Dmitry Preobrazhensky3afbd822018-01-10 14:22:19 +00001945 .Case("xnack_mask_lo", AMDGPU::XNACK_MASK_LO)
1946 .Case("xnack_mask_hi", AMDGPU::XNACK_MASK_HI)
Tom Stellard45bb48e2015-06-13 03:28:10 +00001947 .Case("vcc_lo", AMDGPU::VCC_LO)
1948 .Case("vcc_hi", AMDGPU::VCC_HI)
1949 .Case("exec_lo", AMDGPU::EXEC_LO)
1950 .Case("exec_hi", AMDGPU::EXEC_HI)
Artem Tamazoveb4d5a92016-04-13 16:18:41 +00001951 .Case("tma_lo", AMDGPU::TMA_LO)
1952 .Case("tma_hi", AMDGPU::TMA_HI)
1953 .Case("tba_lo", AMDGPU::TBA_LO)
1954 .Case("tba_hi", AMDGPU::TBA_HI)
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00001955 .Case("null", AMDGPU::SGPR_NULL)
Tom Stellard45bb48e2015-06-13 03:28:10 +00001956 .Default(0);
1957}
1958
Eugene Zelenko66203762017-01-21 00:53:49 +00001959bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1960 SMLoc &EndLoc) {
Valery Pykhtin0f97f172016-03-14 07:43:42 +00001961 auto R = parseRegister();
1962 if (!R) return true;
1963 assert(R->isReg());
1964 RegNo = R->getReg();
1965 StartLoc = R->getStartLoc();
1966 EndLoc = R->getEndLoc();
1967 return false;
1968}
1969
Eugene Zelenko66203762017-01-21 00:53:49 +00001970bool AMDGPUAsmParser::AddNextRegisterToList(unsigned &Reg, unsigned &RegWidth,
1971 RegisterKind RegKind, unsigned Reg1,
1972 unsigned RegNum) {
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00001973 switch (RegKind) {
1974 case IS_SPECIAL:
Eugene Zelenko66203762017-01-21 00:53:49 +00001975 if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) {
1976 Reg = AMDGPU::EXEC;
1977 RegWidth = 2;
1978 return true;
1979 }
1980 if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) {
1981 Reg = AMDGPU::FLAT_SCR;
1982 RegWidth = 2;
1983 return true;
1984 }
Dmitry Preobrazhensky3afbd822018-01-10 14:22:19 +00001985 if (Reg == AMDGPU::XNACK_MASK_LO && Reg1 == AMDGPU::XNACK_MASK_HI) {
1986 Reg = AMDGPU::XNACK_MASK;
1987 RegWidth = 2;
1988 return true;
1989 }
Eugene Zelenko66203762017-01-21 00:53:49 +00001990 if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) {
1991 Reg = AMDGPU::VCC;
1992 RegWidth = 2;
1993 return true;
1994 }
1995 if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) {
1996 Reg = AMDGPU::TBA;
1997 RegWidth = 2;
1998 return true;
1999 }
2000 if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) {
2001 Reg = AMDGPU::TMA;
2002 RegWidth = 2;
2003 return true;
2004 }
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002005 return false;
2006 case IS_VGPR:
2007 case IS_SGPR:
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +00002008 case IS_AGPR:
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002009 case IS_TTMP:
Eugene Zelenko66203762017-01-21 00:53:49 +00002010 if (Reg1 != Reg + RegWidth) {
2011 return false;
2012 }
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002013 RegWidth++;
2014 return true;
2015 default:
Matt Arsenault92b355b2016-11-15 19:34:37 +00002016 llvm_unreachable("unexpected register kind");
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002017 }
2018}
2019
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00002020static const StringRef Registers[] = {
2021 { "v" },
2022 { "s" },
2023 { "ttmp" },
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +00002024 { "acc" },
2025 { "a" },
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00002026};
2027
2028bool
2029AMDGPUAsmParser::isRegister(const AsmToken &Token,
2030 const AsmToken &NextToken) const {
2031
2032 // A list of consecutive registers: [s0,s1,s2,s3]
2033 if (Token.is(AsmToken::LBrac))
2034 return true;
2035
2036 if (!Token.is(AsmToken::Identifier))
2037 return false;
2038
2039 // A single register like s0 or a range of registers like s[0:1]
2040
2041 StringRef RegName = Token.getString();
2042
2043 for (StringRef Reg : Registers) {
2044 if (RegName.startswith(Reg)) {
2045 if (Reg.size() < RegName.size()) {
2046 unsigned RegNum;
2047 // A single register with an index: rXX
2048 if (!RegName.substr(Reg.size()).getAsInteger(10, RegNum))
2049 return true;
2050 } else {
2051 // A range of registers: r[XX:YY].
2052 if (NextToken.is(AsmToken::LBrac))
2053 return true;
2054 }
2055 }
2056 }
2057
2058 return getSpecialRegForName(RegName);
2059}
2060
2061bool
2062AMDGPUAsmParser::isRegister()
2063{
2064 return isRegister(getToken(), peekToken());
2065}
2066
Eugene Zelenko66203762017-01-21 00:53:49 +00002067bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg,
2068 unsigned &RegNum, unsigned &RegWidth,
2069 unsigned *DwordRegIndex) {
Artem Tamazova01cce82016-12-27 16:00:11 +00002070 if (DwordRegIndex) { *DwordRegIndex = 0; }
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002071 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
2072 if (getLexer().is(AsmToken::Identifier)) {
2073 StringRef RegName = Parser.getTok().getString();
2074 if ((Reg = getSpecialRegForName(RegName))) {
2075 Parser.Lex();
2076 RegKind = IS_SPECIAL;
2077 } else {
2078 unsigned RegNumIndex = 0;
Artem Tamazovf88397c2016-06-03 14:41:17 +00002079 if (RegName[0] == 'v') {
2080 RegNumIndex = 1;
2081 RegKind = IS_VGPR;
2082 } else if (RegName[0] == 's') {
2083 RegNumIndex = 1;
2084 RegKind = IS_SGPR;
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +00002085 } else if (RegName[0] == 'a') {
2086 RegNumIndex = RegName.startswith("acc") ? 3 : 1;
2087 RegKind = IS_AGPR;
Artem Tamazovf88397c2016-06-03 14:41:17 +00002088 } else if (RegName.startswith("ttmp")) {
2089 RegNumIndex = strlen("ttmp");
2090 RegKind = IS_TTMP;
2091 } else {
2092 return false;
2093 }
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002094 if (RegName.size() > RegNumIndex) {
2095 // Single 32-bit register: vXX.
Artem Tamazovf88397c2016-06-03 14:41:17 +00002096 if (RegName.substr(RegNumIndex).getAsInteger(10, RegNum))
2097 return false;
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002098 Parser.Lex();
2099 RegWidth = 1;
2100 } else {
Artem Tamazov7da9b822016-05-27 12:50:13 +00002101 // Range of registers: v[XX:YY]. ":YY" is optional.
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002102 Parser.Lex();
2103 int64_t RegLo, RegHi;
Artem Tamazovf88397c2016-06-03 14:41:17 +00002104 if (getLexer().isNot(AsmToken::LBrac))
2105 return false;
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002106 Parser.Lex();
2107
Artem Tamazovf88397c2016-06-03 14:41:17 +00002108 if (getParser().parseAbsoluteExpression(RegLo))
2109 return false;
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002110
Artem Tamazov7da9b822016-05-27 12:50:13 +00002111 const bool isRBrace = getLexer().is(AsmToken::RBrac);
Artem Tamazovf88397c2016-06-03 14:41:17 +00002112 if (!isRBrace && getLexer().isNot(AsmToken::Colon))
2113 return false;
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002114 Parser.Lex();
2115
Artem Tamazov7da9b822016-05-27 12:50:13 +00002116 if (isRBrace) {
2117 RegHi = RegLo;
2118 } else {
Artem Tamazovf88397c2016-06-03 14:41:17 +00002119 if (getParser().parseAbsoluteExpression(RegHi))
2120 return false;
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002121
Artem Tamazovf88397c2016-06-03 14:41:17 +00002122 if (getLexer().isNot(AsmToken::RBrac))
2123 return false;
Artem Tamazov7da9b822016-05-27 12:50:13 +00002124 Parser.Lex();
2125 }
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002126 RegNum = (unsigned) RegLo;
2127 RegWidth = (RegHi - RegLo) + 1;
2128 }
2129 }
2130 } else if (getLexer().is(AsmToken::LBrac)) {
2131 // List of consecutive registers: [s0,s1,s2,s3]
2132 Parser.Lex();
Artem Tamazova01cce82016-12-27 16:00:11 +00002133 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, nullptr))
Artem Tamazovf88397c2016-06-03 14:41:17 +00002134 return false;
2135 if (RegWidth != 1)
2136 return false;
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002137 RegisterKind RegKind1;
2138 unsigned Reg1, RegNum1, RegWidth1;
2139 do {
2140 if (getLexer().is(AsmToken::Comma)) {
2141 Parser.Lex();
2142 } else if (getLexer().is(AsmToken::RBrac)) {
2143 Parser.Lex();
2144 break;
Artem Tamazova01cce82016-12-27 16:00:11 +00002145 } else if (ParseAMDGPURegister(RegKind1, Reg1, RegNum1, RegWidth1, nullptr)) {
Artem Tamazovf88397c2016-06-03 14:41:17 +00002146 if (RegWidth1 != 1) {
2147 return false;
2148 }
2149 if (RegKind1 != RegKind) {
2150 return false;
2151 }
2152 if (!AddNextRegisterToList(Reg, RegWidth, RegKind1, Reg1, RegNum1)) {
2153 return false;
2154 }
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002155 } else {
2156 return false;
2157 }
2158 } while (true);
2159 } else {
2160 return false;
2161 }
2162 switch (RegKind) {
2163 case IS_SPECIAL:
2164 RegNum = 0;
2165 RegWidth = 1;
2166 break;
2167 case IS_VGPR:
2168 case IS_SGPR:
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +00002169 case IS_AGPR:
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002170 case IS_TTMP:
2171 {
2172 unsigned Size = 1;
2173 if (RegKind == IS_SGPR || RegKind == IS_TTMP) {
Artem Tamazova01cce82016-12-27 16:00:11 +00002174 // SGPR and TTMP registers must be aligned. Max required alignment is 4 dwords.
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002175 Size = std::min(RegWidth, 4u);
2176 }
Artem Tamazovf88397c2016-06-03 14:41:17 +00002177 if (RegNum % Size != 0)
2178 return false;
Artem Tamazova01cce82016-12-27 16:00:11 +00002179 if (DwordRegIndex) { *DwordRegIndex = RegNum; }
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002180 RegNum = RegNum / Size;
2181 int RCID = getRegClass(RegKind, RegWidth);
Artem Tamazovf88397c2016-06-03 14:41:17 +00002182 if (RCID == -1)
2183 return false;
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002184 const MCRegisterClass RC = TRI->getRegClass(RCID);
Artem Tamazovf88397c2016-06-03 14:41:17 +00002185 if (RegNum >= RC.getNumRegs())
2186 return false;
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002187 Reg = RC.getRegister(RegNum);
2188 break;
2189 }
2190
2191 default:
Matt Arsenault92b355b2016-11-15 19:34:37 +00002192 llvm_unreachable("unexpected register kind");
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002193 }
2194
Artem Tamazovf88397c2016-06-03 14:41:17 +00002195 if (!subtargetHasRegister(*TRI, Reg))
2196 return false;
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002197 return true;
2198}
2199
Scott Linder1e8c2c72018-06-21 19:38:56 +00002200Optional<StringRef>
2201AMDGPUAsmParser::getGprCountSymbolName(RegisterKind RegKind) {
2202 switch (RegKind) {
2203 case IS_VGPR:
2204 return StringRef(".amdgcn.next_free_vgpr");
2205 case IS_SGPR:
2206 return StringRef(".amdgcn.next_free_sgpr");
2207 default:
2208 return None;
2209 }
2210}
2211
2212void AMDGPUAsmParser::initializeGprCountSymbol(RegisterKind RegKind) {
2213 auto SymbolName = getGprCountSymbolName(RegKind);
2214 assert(SymbolName && "initializing invalid register kind");
2215 MCSymbol *Sym = getContext().getOrCreateSymbol(*SymbolName);
2216 Sym->setVariableValue(MCConstantExpr::create(0, getContext()));
2217}
2218
2219bool AMDGPUAsmParser::updateGprCountSymbols(RegisterKind RegKind,
2220 unsigned DwordRegIndex,
2221 unsigned RegWidth) {
2222 // Symbols are only defined for GCN targets
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00002223 if (AMDGPU::getIsaVersion(getSTI().getCPU()).Major < 6)
Scott Linder1e8c2c72018-06-21 19:38:56 +00002224 return true;
2225
2226 auto SymbolName = getGprCountSymbolName(RegKind);
2227 if (!SymbolName)
2228 return true;
2229 MCSymbol *Sym = getContext().getOrCreateSymbol(*SymbolName);
2230
2231 int64_t NewMax = DwordRegIndex + RegWidth - 1;
2232 int64_t OldCount;
2233
2234 if (!Sym->isVariable())
2235 return !Error(getParser().getTok().getLoc(),
2236 ".amdgcn.next_free_{v,s}gpr symbols must be variable");
2237 if (!Sym->getVariableValue(false)->evaluateAsAbsolute(OldCount))
2238 return !Error(
2239 getParser().getTok().getLoc(),
2240 ".amdgcn.next_free_{v,s}gpr symbols must be absolute expressions");
2241
2242 if (OldCount <= NewMax)
2243 Sym->setVariableValue(MCConstantExpr::create(NewMax + 1, getContext()));
2244
2245 return true;
2246}
2247
Valery Pykhtin0f97f172016-03-14 07:43:42 +00002248std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() {
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002249 const auto &Tok = Parser.getTok();
Valery Pykhtin0f97f172016-03-14 07:43:42 +00002250 SMLoc StartLoc = Tok.getLoc();
2251 SMLoc EndLoc = Tok.getEndLoc();
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002252 RegisterKind RegKind;
Artem Tamazova01cce82016-12-27 16:00:11 +00002253 unsigned Reg, RegNum, RegWidth, DwordRegIndex;
Tom Stellard45bb48e2015-06-13 03:28:10 +00002254
Artem Tamazova01cce82016-12-27 16:00:11 +00002255 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, &DwordRegIndex)) {
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00002256 //FIXME: improve error messages (bug 41303).
2257 Error(StartLoc, "not a valid operand.");
Nikolay Haustovfb5c3072016-04-20 09:34:48 +00002258 return nullptr;
Tom Stellard45bb48e2015-06-13 03:28:10 +00002259 }
Scott Linder1e8c2c72018-06-21 19:38:56 +00002260 if (AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) {
2261 if (!updateGprCountSymbols(RegKind, DwordRegIndex, RegWidth))
2262 return nullptr;
2263 } else
2264 KernelScope.usesRegister(RegKind, DwordRegIndex, RegWidth);
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002265 return AMDGPUOperand::CreateReg(this, Reg, StartLoc, EndLoc);
Tom Stellard45bb48e2015-06-13 03:28:10 +00002266}
2267
Alex Bradbury58eba092016-11-01 16:32:05 +00002268OperandMatchResultTy
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00002269AMDGPUAsmParser::parseImm(OperandVector &Operands, bool HasSP3AbsModifier) {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00002270 // TODO: add syntactic sugar for 1/(2*PI)
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00002271
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +00002272 assert(!isRegister());
2273 assert(!isModifier());
2274
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00002275 const auto& Tok = getToken();
2276 const auto& NextTok = peekToken();
2277 bool IsReal = Tok.is(AsmToken::Real);
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +00002278 SMLoc S = getLoc();
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00002279 bool Negate = false;
2280
2281 if (!IsReal && Tok.is(AsmToken::Minus) && NextTok.is(AsmToken::Real)) {
2282 lex();
2283 IsReal = true;
2284 Negate = true;
Sam Kolton1bdcef72016-05-23 09:59:02 +00002285 }
2286
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00002287 if (IsReal) {
2288 // Floating-point expressions are not supported.
2289 // Can only allow floating-point literals with an
2290 // optional sign.
2291
2292 StringRef Num = getTokenStr();
2293 lex();
2294
2295 APFloat RealVal(APFloat::IEEEdouble());
2296 auto roundMode = APFloat::rmNearestTiesToEven;
2297 if (RealVal.convertFromString(Num, roundMode) == APFloat::opInvalidOp) {
Sam Kolton1bdcef72016-05-23 09:59:02 +00002298 return MatchOperand_ParseFail;
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00002299 }
2300 if (Negate)
2301 RealVal.changeSign();
2302
2303 Operands.push_back(
2304 AMDGPUOperand::CreateImm(this, RealVal.bitcastToAPInt().getZExtValue(), S,
2305 AMDGPUOperand::ImmTyNone, true));
2306
2307 return MatchOperand_Success;
2308
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +00002309 } else {
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00002310 int64_t IntVal;
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +00002311 const MCExpr *Expr;
2312 SMLoc S = getLoc();
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00002313
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +00002314 if (HasSP3AbsModifier) {
2315 // This is a workaround for handling expressions
2316 // as arguments of SP3 'abs' modifier, for example:
2317 // |1.0|
2318 // |-1|
2319 // |1+x|
2320 // This syntax is not compatible with syntax of standard
2321 // MC expressions (due to the trailing '|').
2322 SMLoc EndLoc;
2323 if (getParser().parsePrimaryExpr(Expr, EndLoc))
2324 return MatchOperand_ParseFail;
2325 } else {
2326 if (Parser.parseExpression(Expr))
2327 return MatchOperand_ParseFail;
2328 }
2329
2330 if (Expr->evaluateAsAbsolute(IntVal)) {
2331 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S));
2332 } else {
2333 Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S));
2334 }
2335
Sam Kolton1bdcef72016-05-23 09:59:02 +00002336 return MatchOperand_Success;
2337 }
Sam Kolton1bdcef72016-05-23 09:59:02 +00002338
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00002339 return MatchOperand_NoMatch;
Sam Kolton1bdcef72016-05-23 09:59:02 +00002340}
2341
Alex Bradbury58eba092016-11-01 16:32:05 +00002342OperandMatchResultTy
Sam Kolton9772eb32017-01-11 11:46:30 +00002343AMDGPUAsmParser::parseReg(OperandVector &Operands) {
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00002344 if (!isRegister())
2345 return MatchOperand_NoMatch;
2346
Sam Kolton1bdcef72016-05-23 09:59:02 +00002347 if (auto R = parseRegister()) {
2348 assert(R->isReg());
Sam Kolton1bdcef72016-05-23 09:59:02 +00002349 Operands.push_back(std::move(R));
2350 return MatchOperand_Success;
2351 }
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00002352 return MatchOperand_ParseFail;
Sam Kolton1bdcef72016-05-23 09:59:02 +00002353}
2354
Alex Bradbury58eba092016-11-01 16:32:05 +00002355OperandMatchResultTy
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002356AMDGPUAsmParser::parseRegOrImm(OperandVector &Operands, bool HasSP3AbsMod) {
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00002357 auto res = parseReg(Operands);
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +00002358 if (res != MatchOperand_NoMatch) {
2359 return res;
2360 } else if (isModifier()) {
2361 return MatchOperand_NoMatch;
2362 } else {
2363 return parseImm(Operands, HasSP3AbsMod);
2364 }
2365}
2366
2367bool
2368AMDGPUAsmParser::isNamedOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const {
2369 if (Token.is(AsmToken::Identifier) && NextToken.is(AsmToken::LParen)) {
2370 const auto &str = Token.getString();
2371 return str == "abs" || str == "neg" || str == "sext";
2372 }
2373 return false;
2374}
2375
2376bool
2377AMDGPUAsmParser::isOpcodeModifierWithVal(const AsmToken &Token, const AsmToken &NextToken) const {
2378 return Token.is(AsmToken::Identifier) && NextToken.is(AsmToken::Colon);
2379}
2380
2381bool
2382AMDGPUAsmParser::isOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const {
2383 return isNamedOperandModifier(Token, NextToken) || Token.is(AsmToken::Pipe);
2384}
2385
2386bool
2387AMDGPUAsmParser::isRegOrOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const {
2388 return isRegister(Token, NextToken) || isOperandModifier(Token, NextToken);
2389}
2390
2391// Check if this is an operand modifier or an opcode modifier
2392// which may look like an expression but it is not. We should
2393// avoid parsing these modifiers as expressions. Currently
2394// recognized sequences are:
2395// |...|
2396// abs(...)
2397// neg(...)
2398// sext(...)
2399// -reg
2400// -|...|
2401// -abs(...)
2402// name:...
2403// Note that simple opcode modifiers like 'gds' may be parsed as
2404// expressions; this is a special case. See getExpressionAsToken.
2405//
2406bool
2407AMDGPUAsmParser::isModifier() {
2408
2409 AsmToken Tok = getToken();
2410 AsmToken NextToken[2];
2411 peekTokens(NextToken);
2412
2413 return isOperandModifier(Tok, NextToken[0]) ||
2414 (Tok.is(AsmToken::Minus) && isRegOrOperandModifier(NextToken[0], NextToken[1])) ||
2415 isOpcodeModifierWithVal(Tok, NextToken[0]);
Sam Kolton9772eb32017-01-11 11:46:30 +00002416}
2417
Dmitry Preobrazhenskye2707f52019-04-22 14:35:47 +00002418// Check if the current token is an SP3 'neg' modifier.
2419// Currently this modifier is allowed in the following context:
2420//
2421// 1. Before a register, e.g. "-v0", "-v[...]" or "-[v0,v1]".
2422// 2. Before an 'abs' modifier: -abs(...)
2423// 3. Before an SP3 'abs' modifier: -|...|
2424//
2425// In all other cases "-" is handled as a part
2426// of an expression that follows the sign.
2427//
2428// Note: When "-" is followed by an integer literal,
2429// this is interpreted as integer negation rather
2430// than a floating-point NEG modifier applied to N.
2431// Beside being contr-intuitive, such use of floating-point
2432// NEG modifier would have resulted in different meaning
2433// of integer literals used with VOP1/2/C and VOP3,
2434// for example:
2435// v_exp_f32_e32 v5, -1 // VOP1: src0 = 0xFFFFFFFF
2436// v_exp_f32_e64 v5, -1 // VOP3: src0 = 0x80000001
2437// Negative fp literals with preceding "-" are
2438// handled likewise for unifomtity
2439//
2440bool
2441AMDGPUAsmParser::parseSP3NegModifier() {
2442
2443 AsmToken NextToken[2];
2444 peekTokens(NextToken);
2445
2446 if (isToken(AsmToken::Minus) &&
2447 (isRegister(NextToken[0], NextToken[1]) ||
2448 NextToken[0].is(AsmToken::Pipe) ||
2449 isId(NextToken[0], "abs"))) {
2450 lex();
2451 return true;
2452 }
2453
2454 return false;
2455}
2456
Sam Kolton9772eb32017-01-11 11:46:30 +00002457OperandMatchResultTy
Eugene Zelenko66203762017-01-21 00:53:49 +00002458AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands,
2459 bool AllowImm) {
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002460 bool Neg, SP3Neg;
2461 bool Abs, SP3Abs;
2462 SMLoc Loc;
Sam Kolton1bdcef72016-05-23 09:59:02 +00002463
Dmitry Preobrazhenskye2707f52019-04-22 14:35:47 +00002464 // Disable ambiguous constructs like '--1' etc. Should use neg(-1) instead.
2465 if (isToken(AsmToken::Minus) && peekToken().is(AsmToken::Minus)) {
2466 Error(getLoc(), "invalid syntax, expected 'neg' modifier");
2467 return MatchOperand_ParseFail;
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +00002468 }
2469
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002470 SP3Neg = parseSP3NegModifier();
Dmitry Preobrazhenskye2707f52019-04-22 14:35:47 +00002471
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002472 Loc = getLoc();
2473 Neg = trySkipId("neg");
2474 if (Neg && SP3Neg) {
2475 Error(Loc, "expected register or immediate");
2476 return MatchOperand_ParseFail;
Sam Kolton1bdcef72016-05-23 09:59:02 +00002477 }
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002478 if (Neg && !skipToken(AsmToken::LParen, "expected left paren after neg"))
2479 return MatchOperand_ParseFail;
Sam Kolton1bdcef72016-05-23 09:59:02 +00002480
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002481 Abs = trySkipId("abs");
2482 if (Abs && !skipToken(AsmToken::LParen, "expected left paren after abs"))
2483 return MatchOperand_ParseFail;
Sam Kolton1bdcef72016-05-23 09:59:02 +00002484
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002485 Loc = getLoc();
2486 SP3Abs = trySkipToken(AsmToken::Pipe);
2487 if (Abs && SP3Abs) {
2488 Error(Loc, "expected register or immediate");
2489 return MatchOperand_ParseFail;
Sam Kolton1bdcef72016-05-23 09:59:02 +00002490 }
2491
Sam Kolton9772eb32017-01-11 11:46:30 +00002492 OperandMatchResultTy Res;
2493 if (AllowImm) {
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002494 Res = parseRegOrImm(Operands, SP3Abs);
Sam Kolton9772eb32017-01-11 11:46:30 +00002495 } else {
2496 Res = parseReg(Operands);
2497 }
Sam Kolton1bdcef72016-05-23 09:59:02 +00002498 if (Res != MatchOperand_Success) {
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002499 return (SP3Neg || Neg || SP3Abs || Abs)? MatchOperand_ParseFail : Res;
Sam Kolton1bdcef72016-05-23 09:59:02 +00002500 }
2501
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002502 if (SP3Abs && !skipToken(AsmToken::Pipe, "expected vertical bar"))
2503 return MatchOperand_ParseFail;
2504 if (Abs && !skipToken(AsmToken::RParen, "expected closing parentheses"))
2505 return MatchOperand_ParseFail;
2506 if (Neg && !skipToken(AsmToken::RParen, "expected closing parentheses"))
2507 return MatchOperand_ParseFail;
2508
Matt Arsenaultb55f6202016-12-03 18:22:49 +00002509 AMDGPUOperand::Modifiers Mods;
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002510 Mods.Abs = Abs || SP3Abs;
2511 Mods.Neg = Neg || SP3Neg;
Dmitry Preobrazhensky40af9c32017-03-20 14:50:35 +00002512
Sam Kolton945231a2016-06-10 09:57:59 +00002513 if (Mods.hasFPModifiers()) {
Sam Kolton1bdcef72016-05-23 09:59:02 +00002514 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +00002515 if (Op.isExpr()) {
2516 Error(Op.getStartLoc(), "expected an absolute expression");
2517 return MatchOperand_ParseFail;
2518 }
Sam Kolton945231a2016-06-10 09:57:59 +00002519 Op.setModifiers(Mods);
Sam Kolton1bdcef72016-05-23 09:59:02 +00002520 }
2521 return MatchOperand_Success;
2522}
2523
Alex Bradbury58eba092016-11-01 16:32:05 +00002524OperandMatchResultTy
Eugene Zelenko66203762017-01-21 00:53:49 +00002525AMDGPUAsmParser::parseRegOrImmWithIntInputMods(OperandVector &Operands,
2526 bool AllowImm) {
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002527 bool Sext = trySkipId("sext");
2528 if (Sext && !skipToken(AsmToken::LParen, "expected left paren after sext"))
2529 return MatchOperand_ParseFail;
Sam Kolton945231a2016-06-10 09:57:59 +00002530
Sam Kolton9772eb32017-01-11 11:46:30 +00002531 OperandMatchResultTy Res;
2532 if (AllowImm) {
2533 Res = parseRegOrImm(Operands);
2534 } else {
2535 Res = parseReg(Operands);
2536 }
Sam Kolton945231a2016-06-10 09:57:59 +00002537 if (Res != MatchOperand_Success) {
Dmitry Preobrazhenskye2707f52019-04-22 14:35:47 +00002538 return Sext? MatchOperand_ParseFail : Res;
Sam Kolton945231a2016-06-10 09:57:59 +00002539 }
2540
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002541 if (Sext && !skipToken(AsmToken::RParen, "expected closing parentheses"))
2542 return MatchOperand_ParseFail;
2543
Matt Arsenaultb55f6202016-12-03 18:22:49 +00002544 AMDGPUOperand::Modifiers Mods;
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00002545 Mods.Sext = Sext;
Matt Arsenaultf3dd8632016-11-01 00:55:14 +00002546
Sam Kolton945231a2016-06-10 09:57:59 +00002547 if (Mods.hasIntModifiers()) {
Sam Koltona9cd6aa2016-07-05 14:01:11 +00002548 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +00002549 if (Op.isExpr()) {
2550 Error(Op.getStartLoc(), "expected an absolute expression");
2551 return MatchOperand_ParseFail;
2552 }
Sam Kolton945231a2016-06-10 09:57:59 +00002553 Op.setModifiers(Mods);
2554 }
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00002555
Sam Kolton945231a2016-06-10 09:57:59 +00002556 return MatchOperand_Success;
2557}
Sam Kolton1bdcef72016-05-23 09:59:02 +00002558
Sam Kolton9772eb32017-01-11 11:46:30 +00002559OperandMatchResultTy
2560AMDGPUAsmParser::parseRegWithFPInputMods(OperandVector &Operands) {
2561 return parseRegOrImmWithFPInputMods(Operands, false);
2562}
2563
2564OperandMatchResultTy
2565AMDGPUAsmParser::parseRegWithIntInputMods(OperandVector &Operands) {
2566 return parseRegOrImmWithIntInputMods(Operands, false);
2567}
2568
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00002569OperandMatchResultTy AMDGPUAsmParser::parseVReg32OrOff(OperandVector &Operands) {
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00002570 auto Loc = getLoc();
2571 if (trySkipId("off")) {
2572 Operands.push_back(AMDGPUOperand::CreateImm(this, 0, Loc,
2573 AMDGPUOperand::ImmTyOff, false));
2574 return MatchOperand_Success;
2575 }
2576
2577 if (!isRegister())
2578 return MatchOperand_NoMatch;
2579
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00002580 std::unique_ptr<AMDGPUOperand> Reg = parseRegister();
2581 if (Reg) {
2582 Operands.push_back(std::move(Reg));
2583 return MatchOperand_Success;
2584 }
2585
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00002586 return MatchOperand_ParseFail;
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00002587
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00002588}
2589
Tom Stellard45bb48e2015-06-13 03:28:10 +00002590unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Tom Stellard45bb48e2015-06-13 03:28:10 +00002591 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
2592
2593 if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) ||
Sam Kolton05ef1c92016-06-03 10:27:37 +00002594 (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3)) ||
2595 (isForcedDPP() && !(TSFlags & SIInstrFlags::DPP)) ||
2596 (isForcedSDWA() && !(TSFlags & SIInstrFlags::SDWA)) )
Tom Stellard45bb48e2015-06-13 03:28:10 +00002597 return Match_InvalidOperand;
2598
Tom Stellard88e0b252015-10-06 15:57:53 +00002599 if ((TSFlags & SIInstrFlags::VOP3) &&
2600 (TSFlags & SIInstrFlags::VOPAsmPrefer32Bit) &&
2601 getForcedEncodingSize() != 64)
2602 return Match_PreferE32;
2603
Sam Koltona568e3d2016-12-22 12:57:41 +00002604 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
2605 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
Sam Koltona3ec5c12016-10-07 14:46:06 +00002606 // v_mac_f32/16 allow only dst_sel == DWORD;
Konstantin Zhuravlyovf86e4b72016-11-13 07:01:11 +00002607 auto OpNum =
2608 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::dst_sel);
Sam Koltona3ec5c12016-10-07 14:46:06 +00002609 const auto &Op = Inst.getOperand(OpNum);
2610 if (!Op.isImm() || Op.getImm() != AMDGPU::SDWA::SdwaSel::DWORD) {
2611 return Match_InvalidOperand;
2612 }
2613 }
2614
Tom Stellard45bb48e2015-06-13 03:28:10 +00002615 return Match_Success;
2616}
2617
Matt Arsenault5f45e782017-01-09 18:44:11 +00002618// What asm variants we should check
2619ArrayRef<unsigned> AMDGPUAsmParser::getMatchedVariants() const {
2620 if (getForcedEncodingSize() == 32) {
2621 static const unsigned Variants[] = {AMDGPUAsmVariants::DEFAULT};
2622 return makeArrayRef(Variants);
2623 }
2624
2625 if (isForcedVOP3()) {
2626 static const unsigned Variants[] = {AMDGPUAsmVariants::VOP3};
2627 return makeArrayRef(Variants);
2628 }
2629
2630 if (isForcedSDWA()) {
Sam Koltonf7659d712017-05-23 10:08:55 +00002631 static const unsigned Variants[] = {AMDGPUAsmVariants::SDWA,
2632 AMDGPUAsmVariants::SDWA9};
Matt Arsenault5f45e782017-01-09 18:44:11 +00002633 return makeArrayRef(Variants);
2634 }
2635
2636 if (isForcedDPP()) {
2637 static const unsigned Variants[] = {AMDGPUAsmVariants::DPP};
2638 return makeArrayRef(Variants);
2639 }
2640
2641 static const unsigned Variants[] = {
2642 AMDGPUAsmVariants::DEFAULT, AMDGPUAsmVariants::VOP3,
Sam Koltonf7659d712017-05-23 10:08:55 +00002643 AMDGPUAsmVariants::SDWA, AMDGPUAsmVariants::SDWA9, AMDGPUAsmVariants::DPP
Matt Arsenault5f45e782017-01-09 18:44:11 +00002644 };
2645
2646 return makeArrayRef(Variants);
2647}
2648
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002649unsigned AMDGPUAsmParser::findImplicitSGPRReadInVOP(const MCInst &Inst) const {
2650 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2651 const unsigned Num = Desc.getNumImplicitUses();
2652 for (unsigned i = 0; i < Num; ++i) {
2653 unsigned Reg = Desc.ImplicitUses[i];
2654 switch (Reg) {
2655 case AMDGPU::FLAT_SCR:
2656 case AMDGPU::VCC:
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00002657 case AMDGPU::VCC_LO:
2658 case AMDGPU::VCC_HI:
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002659 case AMDGPU::M0:
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00002660 case AMDGPU::SGPR_NULL:
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002661 return Reg;
2662 default:
2663 break;
2664 }
2665 }
2666 return AMDGPU::NoRegister;
2667}
2668
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002669// NB: This code is correct only when used to check constant
2670// bus limitations because GFX7 support no f16 inline constants.
2671// Note that there are no cases when a GFX7 opcode violates
2672// constant bus limitations due to the use of an f16 constant.
2673bool AMDGPUAsmParser::isInlineConstant(const MCInst &Inst,
2674 unsigned OpIdx) const {
2675 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2676
2677 if (!AMDGPU::isSISrcOperand(Desc, OpIdx)) {
2678 return false;
2679 }
2680
2681 const MCOperand &MO = Inst.getOperand(OpIdx);
2682
2683 int64_t Val = MO.getImm();
2684 auto OpSize = AMDGPU::getOperandSize(Desc, OpIdx);
2685
2686 switch (OpSize) { // expected operand size
2687 case 8:
2688 return AMDGPU::isInlinableLiteral64(Val, hasInv2PiInlineImm());
2689 case 4:
2690 return AMDGPU::isInlinableLiteral32(Val, hasInv2PiInlineImm());
2691 case 2: {
2692 const unsigned OperandType = Desc.OpInfo[OpIdx].OperandType;
2693 if (OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2INT16 ||
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00002694 OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2FP16 ||
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +00002695 OperandType == AMDGPU::OPERAND_REG_INLINE_AC_V2INT16 ||
2696 OperandType == AMDGPU::OPERAND_REG_INLINE_AC_V2FP16 ||
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00002697 OperandType == AMDGPU::OPERAND_REG_IMM_V2INT16 ||
2698 OperandType == AMDGPU::OPERAND_REG_IMM_V2FP16) {
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002699 return AMDGPU::isInlinableLiteralV216(Val, hasInv2PiInlineImm());
2700 } else {
2701 return AMDGPU::isInlinableLiteral16(Val, hasInv2PiInlineImm());
2702 }
2703 }
2704 default:
2705 llvm_unreachable("invalid operand size");
2706 }
2707}
2708
Dmitry Preobrazhenskyfe2ee4c2019-09-02 12:50:05 +00002709unsigned AMDGPUAsmParser::getConstantBusLimit(unsigned Opcode) const {
2710 if (!isGFX10())
2711 return 1;
2712
2713 switch (Opcode) {
2714 // 64-bit shift instructions can use only one scalar value input
2715 case AMDGPU::V_LSHLREV_B64:
2716 case AMDGPU::V_LSHLREV_B64_gfx10:
2717 case AMDGPU::V_LSHL_B64:
2718 case AMDGPU::V_LSHRREV_B64:
2719 case AMDGPU::V_LSHRREV_B64_gfx10:
2720 case AMDGPU::V_LSHR_B64:
2721 case AMDGPU::V_ASHRREV_I64:
2722 case AMDGPU::V_ASHRREV_I64_gfx10:
2723 case AMDGPU::V_ASHR_I64:
2724 return 1;
2725 default:
2726 return 2;
2727 }
2728}
2729
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002730bool AMDGPUAsmParser::usesConstantBus(const MCInst &Inst, unsigned OpIdx) {
2731 const MCOperand &MO = Inst.getOperand(OpIdx);
2732 if (MO.isImm()) {
2733 return !isInlineConstant(Inst, OpIdx);
2734 }
Sam Koltonf7659d712017-05-23 10:08:55 +00002735 return !MO.isReg() ||
2736 isSGPR(mc2PseudoReg(MO.getReg()), getContext().getRegisterInfo());
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002737}
2738
Dmitry Preobrazhenskydc4ac822017-06-21 14:41:34 +00002739bool AMDGPUAsmParser::validateConstantBusLimitations(const MCInst &Inst) {
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002740 const unsigned Opcode = Inst.getOpcode();
2741 const MCInstrDesc &Desc = MII.get(Opcode);
2742 unsigned ConstantBusUseCount = 0;
Stanislav Mekhanoshinf2baae02019-05-02 03:47:23 +00002743 unsigned NumLiterals = 0;
2744 unsigned LiteralSize;
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002745
2746 if (Desc.TSFlags &
2747 (SIInstrFlags::VOPC |
2748 SIInstrFlags::VOP1 | SIInstrFlags::VOP2 |
Sam Koltonf7659d712017-05-23 10:08:55 +00002749 SIInstrFlags::VOP3 | SIInstrFlags::VOP3P |
2750 SIInstrFlags::SDWA)) {
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002751 // Check special imm operands (used by madmk, etc)
2752 if (AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm) != -1) {
2753 ++ConstantBusUseCount;
2754 }
2755
Stanislav Mekhanoshinf2baae02019-05-02 03:47:23 +00002756 SmallDenseSet<unsigned> SGPRsUsed;
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002757 unsigned SGPRUsed = findImplicitSGPRReadInVOP(Inst);
2758 if (SGPRUsed != AMDGPU::NoRegister) {
Stanislav Mekhanoshinf2baae02019-05-02 03:47:23 +00002759 SGPRsUsed.insert(SGPRUsed);
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002760 ++ConstantBusUseCount;
2761 }
2762
2763 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
2764 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
2765 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
2766
2767 const int OpIndices[] = { Src0Idx, Src1Idx, Src2Idx };
2768
2769 for (int OpIdx : OpIndices) {
2770 if (OpIdx == -1) break;
2771
2772 const MCOperand &MO = Inst.getOperand(OpIdx);
2773 if (usesConstantBus(Inst, OpIdx)) {
2774 if (MO.isReg()) {
2775 const unsigned Reg = mc2PseudoReg(MO.getReg());
2776 // Pairs of registers with a partial intersections like these
2777 // s0, s[0:1]
2778 // flat_scratch_lo, flat_scratch
2779 // flat_scratch_lo, flat_scratch_hi
2780 // are theoretically valid but they are disabled anyway.
2781 // Note that this code mimics SIInstrInfo::verifyInstruction
Stanislav Mekhanoshinf2baae02019-05-02 03:47:23 +00002782 if (!SGPRsUsed.count(Reg)) {
2783 SGPRsUsed.insert(Reg);
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002784 ++ConstantBusUseCount;
2785 }
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002786 } else { // Expression or a literal
Stanislav Mekhanoshinf2baae02019-05-02 03:47:23 +00002787
2788 if (Desc.OpInfo[OpIdx].OperandType == MCOI::OPERAND_IMMEDIATE)
2789 continue; // special operand like VINTERP attr_chan
2790
2791 // An instruction may use only one literal.
2792 // This has been validated on the previous step.
2793 // See validateVOP3Literal.
2794 // This literal may be used as more than one operand.
2795 // If all these operands are of the same size,
2796 // this literal counts as one scalar value.
2797 // Otherwise it counts as 2 scalar values.
2798 // See "GFX10 Shader Programming", section 3.6.2.3.
2799
2800 unsigned Size = AMDGPU::getOperandSize(Desc, OpIdx);
2801 if (Size < 4) Size = 4;
2802
2803 if (NumLiterals == 0) {
2804 NumLiterals = 1;
2805 LiteralSize = Size;
2806 } else if (LiteralSize != Size) {
2807 NumLiterals = 2;
2808 }
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002809 }
2810 }
2811 }
2812 }
Stanislav Mekhanoshinf2baae02019-05-02 03:47:23 +00002813 ConstantBusUseCount += NumLiterals;
2814
Dmitry Preobrazhenskyfe2ee4c2019-09-02 12:50:05 +00002815 return ConstantBusUseCount <= getConstantBusLimit(Opcode);
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00002816}
2817
Dmitry Preobrazhenskydc4ac822017-06-21 14:41:34 +00002818bool AMDGPUAsmParser::validateEarlyClobberLimitations(const MCInst &Inst) {
Dmitry Preobrazhenskydc4ac822017-06-21 14:41:34 +00002819 const unsigned Opcode = Inst.getOpcode();
2820 const MCInstrDesc &Desc = MII.get(Opcode);
2821
2822 const int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
2823 if (DstIdx == -1 ||
2824 Desc.getOperandConstraint(DstIdx, MCOI::EARLY_CLOBBER) == -1) {
2825 return true;
2826 }
2827
2828 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
2829
2830 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
2831 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
2832 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
2833
2834 assert(DstIdx != -1);
2835 const MCOperand &Dst = Inst.getOperand(DstIdx);
2836 assert(Dst.isReg());
2837 const unsigned DstReg = mc2PseudoReg(Dst.getReg());
2838
2839 const int SrcIndices[] = { Src0Idx, Src1Idx, Src2Idx };
2840
2841 for (int SrcIdx : SrcIndices) {
2842 if (SrcIdx == -1) break;
2843 const MCOperand &Src = Inst.getOperand(SrcIdx);
2844 if (Src.isReg()) {
2845 const unsigned SrcReg = mc2PseudoReg(Src.getReg());
2846 if (isRegIntersect(DstReg, SrcReg, TRI)) {
2847 return false;
2848 }
2849 }
2850 }
2851
2852 return true;
2853}
2854
Dmitry Preobrazhenskyff64aa52017-08-16 13:51:56 +00002855bool AMDGPUAsmParser::validateIntClampSupported(const MCInst &Inst) {
2856
2857 const unsigned Opc = Inst.getOpcode();
2858 const MCInstrDesc &Desc = MII.get(Opc);
2859
2860 if ((Desc.TSFlags & SIInstrFlags::IntClamp) != 0 && !hasIntClamp()) {
2861 int ClampIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp);
2862 assert(ClampIdx != -1);
2863 return Inst.getOperand(ClampIdx).getImm() == 0;
2864 }
2865
2866 return true;
2867}
2868
Dmitry Preobrazhensky70682812018-01-26 16:42:51 +00002869bool AMDGPUAsmParser::validateMIMGDataSize(const MCInst &Inst) {
2870
2871 const unsigned Opc = Inst.getOpcode();
2872 const MCInstrDesc &Desc = MII.get(Opc);
2873
2874 if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0)
2875 return true;
2876
Dmitry Preobrazhensky70682812018-01-26 16:42:51 +00002877 int VDataIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
2878 int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask);
2879 int TFEIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::tfe);
2880
2881 assert(VDataIdx != -1);
2882 assert(DMaskIdx != -1);
2883 assert(TFEIdx != -1);
2884
2885 unsigned VDataSize = AMDGPU::getRegOperandSize(getMRI(), Desc, VDataIdx);
2886 unsigned TFESize = Inst.getOperand(TFEIdx).getImm()? 1 : 0;
2887 unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf;
2888 if (DMask == 0)
2889 DMask = 1;
2890
Nicolai Haehnlef2674312018-06-21 13:36:01 +00002891 unsigned DataSize =
2892 (Desc.TSFlags & SIInstrFlags::Gather4) ? 4 : countPopulation(DMask);
2893 if (hasPackedD16()) {
2894 int D16Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::d16);
2895 if (D16Idx >= 0 && Inst.getOperand(D16Idx).getImm())
2896 DataSize = (DataSize + 1) / 2;
Dmitry Preobrazhensky0a1ff462018-02-05 14:18:53 +00002897 }
2898
2899 return (VDataSize / 4) == DataSize + TFESize;
Dmitry Preobrazhensky70682812018-01-26 16:42:51 +00002900}
2901
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00002902bool AMDGPUAsmParser::validateMIMGAddrSize(const MCInst &Inst) {
2903 const unsigned Opc = Inst.getOpcode();
2904 const MCInstrDesc &Desc = MII.get(Opc);
2905
2906 if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0 || !isGFX10())
2907 return true;
2908
2909 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opc);
2910 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
2911 AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
2912 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
2913 int SrsrcIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::srsrc);
2914 int DimIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dim);
2915
2916 assert(VAddr0Idx != -1);
2917 assert(SrsrcIdx != -1);
2918 assert(DimIdx != -1);
2919 assert(SrsrcIdx > VAddr0Idx);
2920
2921 unsigned Dim = Inst.getOperand(DimIdx).getImm();
2922 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByEncoding(Dim);
2923 bool IsNSA = SrsrcIdx - VAddr0Idx > 1;
2924 unsigned VAddrSize =
2925 IsNSA ? SrsrcIdx - VAddr0Idx
2926 : AMDGPU::getRegOperandSize(getMRI(), Desc, VAddr0Idx) / 4;
2927
2928 unsigned AddrSize = BaseOpcode->NumExtraArgs +
2929 (BaseOpcode->Gradients ? DimInfo->NumGradients : 0) +
2930 (BaseOpcode->Coordinates ? DimInfo->NumCoords : 0) +
2931 (BaseOpcode->LodOrClampOrMip ? 1 : 0);
2932 if (!IsNSA) {
2933 if (AddrSize > 8)
2934 AddrSize = 16;
2935 else if (AddrSize > 4)
2936 AddrSize = 8;
2937 }
2938
2939 return VAddrSize == AddrSize;
2940}
2941
Dmitry Preobrazhensky70682812018-01-26 16:42:51 +00002942bool AMDGPUAsmParser::validateMIMGAtomicDMask(const MCInst &Inst) {
2943
2944 const unsigned Opc = Inst.getOpcode();
2945 const MCInstrDesc &Desc = MII.get(Opc);
2946
2947 if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0)
2948 return true;
2949 if (!Desc.mayLoad() || !Desc.mayStore())
2950 return true; // Not atomic
2951
2952 int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask);
2953 unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf;
2954
2955 // This is an incomplete check because image_atomic_cmpswap
2956 // may only use 0x3 and 0xf while other atomic operations
2957 // may use 0x1 and 0x3. However these limitations are
2958 // verified when we check that dmask matches dst size.
2959 return DMask == 0x1 || DMask == 0x3 || DMask == 0xf;
2960}
2961
Dmitry Preobrazhenskyda4a7c02018-03-12 15:03:34 +00002962bool AMDGPUAsmParser::validateMIMGGatherDMask(const MCInst &Inst) {
2963
2964 const unsigned Opc = Inst.getOpcode();
2965 const MCInstrDesc &Desc = MII.get(Opc);
2966
2967 if ((Desc.TSFlags & SIInstrFlags::Gather4) == 0)
2968 return true;
2969
2970 int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask);
2971 unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf;
2972
2973 // GATHER4 instructions use dmask in a different fashion compared to
2974 // other MIMG instructions. The only useful DMASK values are
2975 // 1=red, 2=green, 4=blue, 8=alpha. (e.g. 1 returns
2976 // (red,red,red,red) etc.) The ISA document doesn't mention
2977 // this.
2978 return DMask == 0x1 || DMask == 0x2 || DMask == 0x4 || DMask == 0x8;
2979}
2980
Dmitry Preobrazhenskye3271ae2018-02-05 12:45:43 +00002981bool AMDGPUAsmParser::validateMIMGD16(const MCInst &Inst) {
2982
2983 const unsigned Opc = Inst.getOpcode();
2984 const MCInstrDesc &Desc = MII.get(Opc);
2985
2986 if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0)
2987 return true;
Dmitry Preobrazhenskye3271ae2018-02-05 12:45:43 +00002988
Nicolai Haehnlef2674312018-06-21 13:36:01 +00002989 int D16Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::d16);
2990 if (D16Idx >= 0 && Inst.getOperand(D16Idx).getImm()) {
2991 if (isCI() || isSI())
2992 return false;
2993 }
2994
2995 return true;
Dmitry Preobrazhenskye3271ae2018-02-05 12:45:43 +00002996}
2997
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00002998bool AMDGPUAsmParser::validateMIMGDim(const MCInst &Inst) {
2999 const unsigned Opc = Inst.getOpcode();
3000 const MCInstrDesc &Desc = MII.get(Opc);
3001
3002 if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0)
3003 return true;
3004
3005 int DimIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dim);
3006 if (DimIdx < 0)
3007 return true;
3008
3009 long Imm = Inst.getOperand(DimIdx).getImm();
3010 if (Imm < 0 || Imm >= 8)
3011 return false;
3012
3013 return true;
3014}
3015
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003016static bool IsRevOpcode(const unsigned Opcode)
3017{
3018 switch (Opcode) {
3019 case AMDGPU::V_SUBREV_F32_e32:
3020 case AMDGPU::V_SUBREV_F32_e64:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003021 case AMDGPU::V_SUBREV_F32_e32_gfx10:
3022 case AMDGPU::V_SUBREV_F32_e32_gfx6_gfx7:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003023 case AMDGPU::V_SUBREV_F32_e32_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003024 case AMDGPU::V_SUBREV_F32_e64_gfx10:
3025 case AMDGPU::V_SUBREV_F32_e64_gfx6_gfx7:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003026 case AMDGPU::V_SUBREV_F32_e64_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003027
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003028 case AMDGPU::V_SUBREV_I32_e32:
3029 case AMDGPU::V_SUBREV_I32_e64:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003030 case AMDGPU::V_SUBREV_I32_e32_gfx6_gfx7:
3031 case AMDGPU::V_SUBREV_I32_e64_gfx6_gfx7:
3032
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003033 case AMDGPU::V_SUBBREV_U32_e32:
3034 case AMDGPU::V_SUBBREV_U32_e64:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003035 case AMDGPU::V_SUBBREV_U32_e32_gfx6_gfx7:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003036 case AMDGPU::V_SUBBREV_U32_e32_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003037 case AMDGPU::V_SUBBREV_U32_e64_gfx6_gfx7:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003038 case AMDGPU::V_SUBBREV_U32_e64_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003039
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003040 case AMDGPU::V_SUBREV_U32_e32:
3041 case AMDGPU::V_SUBREV_U32_e64:
3042 case AMDGPU::V_SUBREV_U32_e32_gfx9:
3043 case AMDGPU::V_SUBREV_U32_e32_vi:
3044 case AMDGPU::V_SUBREV_U32_e64_gfx9:
3045 case AMDGPU::V_SUBREV_U32_e64_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003046
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003047 case AMDGPU::V_SUBREV_F16_e32:
3048 case AMDGPU::V_SUBREV_F16_e64:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003049 case AMDGPU::V_SUBREV_F16_e32_gfx10:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003050 case AMDGPU::V_SUBREV_F16_e32_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003051 case AMDGPU::V_SUBREV_F16_e64_gfx10:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003052 case AMDGPU::V_SUBREV_F16_e64_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003053
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003054 case AMDGPU::V_SUBREV_U16_e32:
3055 case AMDGPU::V_SUBREV_U16_e64:
3056 case AMDGPU::V_SUBREV_U16_e32_vi:
3057 case AMDGPU::V_SUBREV_U16_e64_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003058
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003059 case AMDGPU::V_SUBREV_CO_U32_e32_gfx9:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003060 case AMDGPU::V_SUBREV_CO_U32_e64_gfx10:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003061 case AMDGPU::V_SUBREV_CO_U32_e64_gfx9:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003062
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003063 case AMDGPU::V_SUBBREV_CO_U32_e32_gfx9:
3064 case AMDGPU::V_SUBBREV_CO_U32_e64_gfx9:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003065
3066 case AMDGPU::V_SUBREV_NC_U32_e32_gfx10:
3067 case AMDGPU::V_SUBREV_NC_U32_e64_gfx10:
3068
3069 case AMDGPU::V_SUBREV_CO_CI_U32_e32_gfx10:
3070 case AMDGPU::V_SUBREV_CO_CI_U32_e64_gfx10:
3071
3072 case AMDGPU::V_LSHRREV_B32_e32:
3073 case AMDGPU::V_LSHRREV_B32_e64:
3074 case AMDGPU::V_LSHRREV_B32_e32_gfx6_gfx7:
3075 case AMDGPU::V_LSHRREV_B32_e64_gfx6_gfx7:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003076 case AMDGPU::V_LSHRREV_B32_e32_vi:
3077 case AMDGPU::V_LSHRREV_B32_e64_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003078 case AMDGPU::V_LSHRREV_B32_e32_gfx10:
3079 case AMDGPU::V_LSHRREV_B32_e64_gfx10:
3080
3081 case AMDGPU::V_ASHRREV_I32_e32:
3082 case AMDGPU::V_ASHRREV_I32_e64:
3083 case AMDGPU::V_ASHRREV_I32_e32_gfx10:
3084 case AMDGPU::V_ASHRREV_I32_e32_gfx6_gfx7:
3085 case AMDGPU::V_ASHRREV_I32_e32_vi:
3086 case AMDGPU::V_ASHRREV_I32_e64_gfx10:
3087 case AMDGPU::V_ASHRREV_I32_e64_gfx6_gfx7:
3088 case AMDGPU::V_ASHRREV_I32_e64_vi:
3089
3090 case AMDGPU::V_LSHLREV_B32_e32:
3091 case AMDGPU::V_LSHLREV_B32_e64:
3092 case AMDGPU::V_LSHLREV_B32_e32_gfx10:
3093 case AMDGPU::V_LSHLREV_B32_e32_gfx6_gfx7:
3094 case AMDGPU::V_LSHLREV_B32_e32_vi:
3095 case AMDGPU::V_LSHLREV_B32_e64_gfx10:
3096 case AMDGPU::V_LSHLREV_B32_e64_gfx6_gfx7:
3097 case AMDGPU::V_LSHLREV_B32_e64_vi:
3098
3099 case AMDGPU::V_LSHLREV_B16_e32:
3100 case AMDGPU::V_LSHLREV_B16_e64:
3101 case AMDGPU::V_LSHLREV_B16_e32_vi:
3102 case AMDGPU::V_LSHLREV_B16_e64_vi:
Stanislav Mekhanoshin61beff02019-04-26 17:56:03 +00003103 case AMDGPU::V_LSHLREV_B16_gfx10:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003104
3105 case AMDGPU::V_LSHRREV_B16_e32:
3106 case AMDGPU::V_LSHRREV_B16_e64:
3107 case AMDGPU::V_LSHRREV_B16_e32_vi:
3108 case AMDGPU::V_LSHRREV_B16_e64_vi:
Stanislav Mekhanoshin61beff02019-04-26 17:56:03 +00003109 case AMDGPU::V_LSHRREV_B16_gfx10:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003110
3111 case AMDGPU::V_ASHRREV_I16_e32:
3112 case AMDGPU::V_ASHRREV_I16_e64:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003113 case AMDGPU::V_ASHRREV_I16_e32_vi:
3114 case AMDGPU::V_ASHRREV_I16_e64_vi:
Stanislav Mekhanoshin61beff02019-04-26 17:56:03 +00003115 case AMDGPU::V_ASHRREV_I16_gfx10:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003116
3117 case AMDGPU::V_LSHLREV_B64:
Stanislav Mekhanoshin61beff02019-04-26 17:56:03 +00003118 case AMDGPU::V_LSHLREV_B64_gfx10:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003119 case AMDGPU::V_LSHLREV_B64_vi:
3120
3121 case AMDGPU::V_LSHRREV_B64:
Stanislav Mekhanoshin61beff02019-04-26 17:56:03 +00003122 case AMDGPU::V_LSHRREV_B64_gfx10:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003123 case AMDGPU::V_LSHRREV_B64_vi:
3124
3125 case AMDGPU::V_ASHRREV_I64:
Stanislav Mekhanoshin61beff02019-04-26 17:56:03 +00003126 case AMDGPU::V_ASHRREV_I64_gfx10:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003127 case AMDGPU::V_ASHRREV_I64_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003128
3129 case AMDGPU::V_PK_LSHLREV_B16:
Stanislav Mekhanoshin61beff02019-04-26 17:56:03 +00003130 case AMDGPU::V_PK_LSHLREV_B16_gfx10:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003131 case AMDGPU::V_PK_LSHLREV_B16_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003132
3133 case AMDGPU::V_PK_LSHRREV_B16:
Stanislav Mekhanoshin61beff02019-04-26 17:56:03 +00003134 case AMDGPU::V_PK_LSHRREV_B16_gfx10:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003135 case AMDGPU::V_PK_LSHRREV_B16_vi:
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00003136 case AMDGPU::V_PK_ASHRREV_I16:
Stanislav Mekhanoshin61beff02019-04-26 17:56:03 +00003137 case AMDGPU::V_PK_ASHRREV_I16_gfx10:
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003138 case AMDGPU::V_PK_ASHRREV_I16_vi:
3139 return true;
3140 default:
3141 return false;
3142 }
3143}
3144
Dmitry Preobrazhensky942c2732019-02-08 14:57:37 +00003145bool AMDGPUAsmParser::validateLdsDirect(const MCInst &Inst) {
3146
3147 using namespace SIInstrFlags;
3148 const unsigned Opcode = Inst.getOpcode();
3149 const MCInstrDesc &Desc = MII.get(Opcode);
3150
3151 // lds_direct register is defined so that it can be used
3152 // with 9-bit operands only. Ignore encodings which do not accept these.
3153 if ((Desc.TSFlags & (VOP1 | VOP2 | VOP3 | VOPC | VOP3P | SIInstrFlags::SDWA)) == 0)
3154 return true;
3155
3156 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
3157 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
3158 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
3159
3160 const int SrcIndices[] = { Src1Idx, Src2Idx };
3161
3162 // lds_direct cannot be specified as either src1 or src2.
3163 for (int SrcIdx : SrcIndices) {
3164 if (SrcIdx == -1) break;
3165 const MCOperand &Src = Inst.getOperand(SrcIdx);
3166 if (Src.isReg() && Src.getReg() == LDS_DIRECT) {
3167 return false;
3168 }
3169 }
3170
3171 if (Src0Idx == -1)
3172 return true;
3173
3174 const MCOperand &Src = Inst.getOperand(Src0Idx);
3175 if (!Src.isReg() || Src.getReg() != LDS_DIRECT)
3176 return true;
3177
3178 // lds_direct is specified as src0. Check additional limitations.
Dmitry Preobrazhensky6023d592019-03-04 12:48:32 +00003179 return (Desc.TSFlags & SIInstrFlags::SDWA) == 0 && !IsRevOpcode(Opcode);
Dmitry Preobrazhensky942c2732019-02-08 14:57:37 +00003180}
3181
Dmitry Preobrazhensky2eff0312019-07-08 14:27:37 +00003182SMLoc AMDGPUAsmParser::getFlatOffsetLoc(const OperandVector &Operands) const {
3183 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
3184 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
3185 if (Op.isFlatOffset())
3186 return Op.getStartLoc();
3187 }
3188 return getLoc();
3189}
3190
3191bool AMDGPUAsmParser::validateFlatOffset(const MCInst &Inst,
3192 const OperandVector &Operands) {
3193 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
3194 if ((TSFlags & SIInstrFlags::FLAT) == 0)
3195 return true;
3196
3197 auto Opcode = Inst.getOpcode();
3198 auto OpNum = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::offset);
3199 assert(OpNum != -1);
3200
3201 const auto &Op = Inst.getOperand(OpNum);
3202 if (!hasFlatOffsets() && Op.getImm() != 0) {
3203 Error(getFlatOffsetLoc(Operands),
3204 "flat offset modifier is not supported on this GPU");
3205 return false;
3206 }
3207
3208 // Address offset is 12-bit signed for GFX10, 13-bit for GFX9.
3209 // For FLAT segment the offset must be positive;
3210 // MSB is ignored and forced to zero.
3211 unsigned OffsetSize = isGFX9() ? 13 : 12;
3212 if (TSFlags & SIInstrFlags::IsNonFlatSeg) {
3213 if (!isIntN(OffsetSize, Op.getImm())) {
3214 Error(getFlatOffsetLoc(Operands),
3215 isGFX9() ? "expected a 13-bit signed offset" :
3216 "expected a 12-bit signed offset");
3217 return false;
3218 }
3219 } else {
3220 if (!isUIntN(OffsetSize - 1, Op.getImm())) {
3221 Error(getFlatOffsetLoc(Operands),
3222 isGFX9() ? "expected a 12-bit unsigned offset" :
3223 "expected an 11-bit unsigned offset");
3224 return false;
3225 }
3226 }
3227
3228 return true;
3229}
3230
Dmitry Preobrazhensky61105ba2019-01-18 13:57:43 +00003231bool AMDGPUAsmParser::validateSOPLiteral(const MCInst &Inst) const {
3232 unsigned Opcode = Inst.getOpcode();
3233 const MCInstrDesc &Desc = MII.get(Opcode);
3234 if (!(Desc.TSFlags & (SIInstrFlags::SOP2 | SIInstrFlags::SOPC)))
3235 return true;
3236
3237 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
3238 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
3239
3240 const int OpIndices[] = { Src0Idx, Src1Idx };
3241
3242 unsigned NumLiterals = 0;
3243 uint32_t LiteralValue;
3244
3245 for (int OpIdx : OpIndices) {
3246 if (OpIdx == -1) break;
3247
3248 const MCOperand &MO = Inst.getOperand(OpIdx);
3249 if (MO.isImm() &&
3250 // Exclude special imm operands (like that used by s_set_gpr_idx_on)
3251 AMDGPU::isSISrcOperand(Desc, OpIdx) &&
3252 !isInlineConstant(Inst, OpIdx)) {
3253 uint32_t Value = static_cast<uint32_t>(MO.getImm());
3254 if (NumLiterals == 0 || LiteralValue != Value) {
3255 LiteralValue = Value;
3256 ++NumLiterals;
3257 }
3258 }
3259 }
3260
3261 return NumLiterals <= 1;
3262}
3263
Stanislav Mekhanoshin5f581c92019-06-12 17:52:51 +00003264bool AMDGPUAsmParser::validateOpSel(const MCInst &Inst) {
3265 const unsigned Opc = Inst.getOpcode();
3266 if (Opc == AMDGPU::V_PERMLANE16_B32_gfx10 ||
3267 Opc == AMDGPU::V_PERMLANEX16_B32_gfx10) {
3268 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
3269 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
3270
3271 if (OpSel & ~3)
3272 return false;
3273 }
3274 return true;
3275}
3276
Stanislav Mekhanoshin8bcc9bb2019-06-13 19:18:29 +00003277// Check if VCC register matches wavefront size
3278bool AMDGPUAsmParser::validateVccOperand(unsigned Reg) const {
3279 auto FB = getFeatureBits();
3280 return (FB[AMDGPU::FeatureWavefrontSize64] && Reg == AMDGPU::VCC) ||
3281 (FB[AMDGPU::FeatureWavefrontSize32] && Reg == AMDGPU::VCC_LO);
3282}
3283
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00003284// VOP3 literal is only allowed in GFX10+ and only one can be used
3285bool AMDGPUAsmParser::validateVOP3Literal(const MCInst &Inst) const {
3286 unsigned Opcode = Inst.getOpcode();
3287 const MCInstrDesc &Desc = MII.get(Opcode);
3288 if (!(Desc.TSFlags & (SIInstrFlags::VOP3 | SIInstrFlags::VOP3P)))
3289 return true;
3290
3291 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
3292 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
3293 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
3294
3295 const int OpIndices[] = { Src0Idx, Src1Idx, Src2Idx };
3296
3297 unsigned NumLiterals = 0;
3298 uint32_t LiteralValue;
3299
3300 for (int OpIdx : OpIndices) {
3301 if (OpIdx == -1) break;
3302
3303 const MCOperand &MO = Inst.getOperand(OpIdx);
3304 if (!MO.isImm() || !AMDGPU::isSISrcOperand(Desc, OpIdx))
3305 continue;
3306
Stanislav Mekhanoshinb37d6a72019-08-23 22:22:49 +00003307 if (OpIdx == Src2Idx && (Desc.TSFlags & SIInstrFlags::IsMAI) &&
3308 getFeatureBits()[AMDGPU::FeatureMFMAInlineLiteralBug])
3309 return false;
3310
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00003311 if (!isInlineConstant(Inst, OpIdx)) {
3312 uint32_t Value = static_cast<uint32_t>(MO.getImm());
3313 if (NumLiterals == 0 || LiteralValue != Value) {
3314 LiteralValue = Value;
3315 ++NumLiterals;
3316 }
3317 }
3318 }
3319
3320 return !NumLiterals ||
3321 (NumLiterals == 1 && getFeatureBits()[AMDGPU::FeatureVOP3Literal]);
3322}
3323
Dmitry Preobrazhenskydc4ac822017-06-21 14:41:34 +00003324bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst,
Dmitry Preobrazhensky2eff0312019-07-08 14:27:37 +00003325 const SMLoc &IDLoc,
3326 const OperandVector &Operands) {
Dmitry Preobrazhensky942c2732019-02-08 14:57:37 +00003327 if (!validateLdsDirect(Inst)) {
3328 Error(IDLoc,
3329 "invalid use of lds_direct");
3330 return false;
3331 }
Dmitry Preobrazhensky61105ba2019-01-18 13:57:43 +00003332 if (!validateSOPLiteral(Inst)) {
3333 Error(IDLoc,
3334 "only one literal operand is allowed");
3335 return false;
3336 }
Stanislav Mekhanoshin5cf81672019-05-02 04:01:39 +00003337 if (!validateVOP3Literal(Inst)) {
3338 Error(IDLoc,
3339 "invalid literal operand");
3340 return false;
3341 }
Dmitry Preobrazhenskydc4ac822017-06-21 14:41:34 +00003342 if (!validateConstantBusLimitations(Inst)) {
3343 Error(IDLoc,
3344 "invalid operand (violates constant bus restrictions)");
3345 return false;
3346 }
3347 if (!validateEarlyClobberLimitations(Inst)) {
3348 Error(IDLoc,
3349 "destination must be different than all sources");
3350 return false;
3351 }
Dmitry Preobrazhenskyff64aa52017-08-16 13:51:56 +00003352 if (!validateIntClampSupported(Inst)) {
3353 Error(IDLoc,
3354 "integer clamping is not supported on this GPU");
3355 return false;
3356 }
Stanislav Mekhanoshin5f581c92019-06-12 17:52:51 +00003357 if (!validateOpSel(Inst)) {
3358 Error(IDLoc,
3359 "invalid op_sel operand");
3360 return false;
3361 }
Dmitry Preobrazhenskye3271ae2018-02-05 12:45:43 +00003362 // For MUBUF/MTBUF d16 is a part of opcode, so there is nothing to validate.
3363 if (!validateMIMGD16(Inst)) {
3364 Error(IDLoc,
3365 "d16 modifier is not supported on this GPU");
3366 return false;
3367 }
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00003368 if (!validateMIMGDim(Inst)) {
3369 Error(IDLoc, "dim modifier is required on this GPU");
3370 return false;
3371 }
Dmitry Preobrazhensky0a1ff462018-02-05 14:18:53 +00003372 if (!validateMIMGDataSize(Inst)) {
3373 Error(IDLoc,
3374 "image data size does not match dmask and tfe");
3375 return false;
3376 }
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00003377 if (!validateMIMGAddrSize(Inst)) {
3378 Error(IDLoc,
3379 "image address size does not match dim and a16");
3380 return false;
3381 }
Dmitry Preobrazhensky0a1ff462018-02-05 14:18:53 +00003382 if (!validateMIMGAtomicDMask(Inst)) {
3383 Error(IDLoc,
3384 "invalid atomic image dmask");
3385 return false;
3386 }
Dmitry Preobrazhenskyda4a7c02018-03-12 15:03:34 +00003387 if (!validateMIMGGatherDMask(Inst)) {
3388 Error(IDLoc,
3389 "invalid image_gather dmask: only one bit must be set");
3390 return false;
3391 }
Dmitry Preobrazhensky2eff0312019-07-08 14:27:37 +00003392 if (!validateFlatOffset(Inst, Operands)) {
3393 return false;
3394 }
Dmitry Preobrazhenskydc4ac822017-06-21 14:41:34 +00003395
3396 return true;
3397}
3398
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00003399static std::string AMDGPUMnemonicSpellCheck(StringRef S,
3400 const FeatureBitset &FBS,
Matt Arsenaultf7f59b52017-12-20 18:52:57 +00003401 unsigned VariantID = 0);
3402
Tom Stellard45bb48e2015-06-13 03:28:10 +00003403bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3404 OperandVector &Operands,
3405 MCStreamer &Out,
3406 uint64_t &ErrorInfo,
3407 bool MatchingInlineAsm) {
3408 MCInst Inst;
Sam Koltond63d8a72016-09-09 09:37:51 +00003409 unsigned Result = Match_Success;
Matt Arsenault5f45e782017-01-09 18:44:11 +00003410 for (auto Variant : getMatchedVariants()) {
Sam Koltond63d8a72016-09-09 09:37:51 +00003411 uint64_t EI;
3412 auto R = MatchInstructionImpl(Operands, Inst, EI, MatchingInlineAsm,
3413 Variant);
3414 // We order match statuses from least to most specific. We use most specific
3415 // status as resulting
3416 // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature < Match_PreferE32
3417 if ((R == Match_Success) ||
3418 (R == Match_PreferE32) ||
3419 (R == Match_MissingFeature && Result != Match_PreferE32) ||
3420 (R == Match_InvalidOperand && Result != Match_MissingFeature
3421 && Result != Match_PreferE32) ||
3422 (R == Match_MnemonicFail && Result != Match_InvalidOperand
3423 && Result != Match_MissingFeature
3424 && Result != Match_PreferE32)) {
3425 Result = R;
3426 ErrorInfo = EI;
Tom Stellard45bb48e2015-06-13 03:28:10 +00003427 }
Sam Koltond63d8a72016-09-09 09:37:51 +00003428 if (R == Match_Success)
3429 break;
3430 }
3431
3432 switch (Result) {
3433 default: break;
3434 case Match_Success:
Dmitry Preobrazhensky2eff0312019-07-08 14:27:37 +00003435 if (!validateInstruction(Inst, IDLoc, Operands)) {
Dmitry Preobrazhenskydc4ac822017-06-21 14:41:34 +00003436 return true;
Dmitry Preobrazhensky03880f82017-03-03 14:31:06 +00003437 }
Sam Koltond63d8a72016-09-09 09:37:51 +00003438 Inst.setLoc(IDLoc);
3439 Out.EmitInstruction(Inst, getSTI());
3440 return false;
3441
3442 case Match_MissingFeature:
3443 return Error(IDLoc, "instruction not supported on this GPU");
3444
Matt Arsenaultf7f59b52017-12-20 18:52:57 +00003445 case Match_MnemonicFail: {
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00003446 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
Matt Arsenaultf7f59b52017-12-20 18:52:57 +00003447 std::string Suggestion = AMDGPUMnemonicSpellCheck(
3448 ((AMDGPUOperand &)*Operands[0]).getToken(), FBS);
3449 return Error(IDLoc, "invalid instruction" + Suggestion,
3450 ((AMDGPUOperand &)*Operands[0]).getLocRange());
3451 }
Sam Koltond63d8a72016-09-09 09:37:51 +00003452
3453 case Match_InvalidOperand: {
3454 SMLoc ErrorLoc = IDLoc;
3455 if (ErrorInfo != ~0ULL) {
3456 if (ErrorInfo >= Operands.size()) {
3457 return Error(IDLoc, "too few operands for instruction");
3458 }
3459 ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc();
3460 if (ErrorLoc == SMLoc())
3461 ErrorLoc = IDLoc;
3462 }
3463 return Error(ErrorLoc, "invalid operand for instruction");
3464 }
3465
3466 case Match_PreferE32:
3467 return Error(IDLoc, "internal error: instruction without _e64 suffix "
3468 "should be encoded as e32");
Tom Stellard45bb48e2015-06-13 03:28:10 +00003469 }
3470 llvm_unreachable("Implement any new match types added!");
3471}
3472
Artem Tamazov25478d82016-12-29 15:41:52 +00003473bool AMDGPUAsmParser::ParseAsAbsoluteExpression(uint32_t &Ret) {
3474 int64_t Tmp = -1;
3475 if (getLexer().isNot(AsmToken::Integer) && getLexer().isNot(AsmToken::Identifier)) {
3476 return true;
3477 }
3478 if (getParser().parseAbsoluteExpression(Tmp)) {
3479 return true;
3480 }
3481 Ret = static_cast<uint32_t>(Tmp);
3482 return false;
3483}
3484
Tom Stellard347ac792015-06-26 21:15:07 +00003485bool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major,
3486 uint32_t &Minor) {
Artem Tamazov25478d82016-12-29 15:41:52 +00003487 if (ParseAsAbsoluteExpression(Major))
Tom Stellard347ac792015-06-26 21:15:07 +00003488 return TokError("invalid major version");
3489
Tom Stellard347ac792015-06-26 21:15:07 +00003490 if (getLexer().isNot(AsmToken::Comma))
3491 return TokError("minor version number required, comma expected");
3492 Lex();
3493
Artem Tamazov25478d82016-12-29 15:41:52 +00003494 if (ParseAsAbsoluteExpression(Minor))
Tom Stellard347ac792015-06-26 21:15:07 +00003495 return TokError("invalid minor version");
3496
Tom Stellard347ac792015-06-26 21:15:07 +00003497 return false;
3498}
3499
Scott Linder1e8c2c72018-06-21 19:38:56 +00003500bool AMDGPUAsmParser::ParseDirectiveAMDGCNTarget() {
3501 if (getSTI().getTargetTriple().getArch() != Triple::amdgcn)
3502 return TokError("directive only supported for amdgcn architecture");
3503
3504 std::string Target;
3505
3506 SMLoc TargetStart = getTok().getLoc();
3507 if (getParser().parseEscapedString(Target))
3508 return true;
3509 SMRange TargetRange = SMRange(TargetStart, getTok().getLoc());
3510
3511 std::string ExpectedTarget;
3512 raw_string_ostream ExpectedTargetOS(ExpectedTarget);
3513 IsaInfo::streamIsaVersion(&getSTI(), ExpectedTargetOS);
3514
3515 if (Target != ExpectedTargetOS.str())
3516 return getParser().Error(TargetRange.Start, "target must match options",
3517 TargetRange);
3518
3519 getTargetStreamer().EmitDirectiveAMDGCNTarget(Target);
3520 return false;
3521}
3522
3523bool AMDGPUAsmParser::OutOfRangeError(SMRange Range) {
3524 return getParser().Error(Range.Start, "value out of range", Range);
3525}
3526
3527bool AMDGPUAsmParser::calculateGPRBlocks(
3528 const FeatureBitset &Features, bool VCCUsed, bool FlatScrUsed,
Stanislav Mekhanoshin8bcc9bb2019-06-13 19:18:29 +00003529 bool XNACKUsed, Optional<bool> EnableWavefrontSize32, unsigned NextFreeVGPR,
3530 SMRange VGPRRange, unsigned NextFreeSGPR, SMRange SGPRRange,
3531 unsigned &VGPRBlocks, unsigned &SGPRBlocks) {
Scott Linder1e8c2c72018-06-21 19:38:56 +00003532 // TODO(scott.linder): These calculations are duplicated from
3533 // AMDGPUAsmPrinter::getSIProgramInfo and could be unified.
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00003534 IsaVersion Version = getIsaVersion(getSTI().getCPU());
Scott Linder1e8c2c72018-06-21 19:38:56 +00003535
3536 unsigned NumVGPRs = NextFreeVGPR;
3537 unsigned NumSGPRs = NextFreeSGPR;
Scott Linder1e8c2c72018-06-21 19:38:56 +00003538
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00003539 if (Version.Major >= 10)
3540 NumSGPRs = 0;
3541 else {
3542 unsigned MaxAddressableNumSGPRs =
3543 IsaInfo::getAddressableNumSGPRs(&getSTI());
Scott Linder1e8c2c72018-06-21 19:38:56 +00003544
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00003545 if (Version.Major >= 8 && !Features.test(FeatureSGPRInitBug) &&
3546 NumSGPRs > MaxAddressableNumSGPRs)
3547 return OutOfRangeError(SGPRRange);
Scott Linder1e8c2c72018-06-21 19:38:56 +00003548
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00003549 NumSGPRs +=
3550 IsaInfo::getNumExtraSGPRs(&getSTI(), VCCUsed, FlatScrUsed, XNACKUsed);
Scott Linder1e8c2c72018-06-21 19:38:56 +00003551
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00003552 if ((Version.Major <= 7 || Features.test(FeatureSGPRInitBug)) &&
3553 NumSGPRs > MaxAddressableNumSGPRs)
3554 return OutOfRangeError(SGPRRange);
3555
3556 if (Features.test(FeatureSGPRInitBug))
3557 NumSGPRs = IsaInfo::FIXED_NUM_SGPRS_FOR_INIT_BUG;
3558 }
Scott Linder1e8c2c72018-06-21 19:38:56 +00003559
Stanislav Mekhanoshin8bcc9bb2019-06-13 19:18:29 +00003560 VGPRBlocks =
3561 IsaInfo::getNumVGPRBlocks(&getSTI(), NumVGPRs, EnableWavefrontSize32);
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00003562 SGPRBlocks = IsaInfo::getNumSGPRBlocks(&getSTI(), NumSGPRs);
Scott Linder1e8c2c72018-06-21 19:38:56 +00003563
3564 return false;
3565}
3566
3567bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() {
3568 if (getSTI().getTargetTriple().getArch() != Triple::amdgcn)
3569 return TokError("directive only supported for amdgcn architecture");
3570
3571 if (getSTI().getTargetTriple().getOS() != Triple::AMDHSA)
3572 return TokError("directive only supported for amdhsa OS");
3573
3574 StringRef KernelName;
3575 if (getParser().parseIdentifier(KernelName))
3576 return true;
3577
Stanislav Mekhanoshincee607e2019-04-24 17:03:15 +00003578 kernel_descriptor_t KD = getDefaultAmdhsaKernelDescriptor(&getSTI());
Scott Linder1e8c2c72018-06-21 19:38:56 +00003579
3580 StringSet<> Seen;
3581
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00003582 IsaVersion IVersion = getIsaVersion(getSTI().getCPU());
Scott Linder1e8c2c72018-06-21 19:38:56 +00003583
3584 SMRange VGPRRange;
3585 uint64_t NextFreeVGPR = 0;
3586 SMRange SGPRRange;
3587 uint64_t NextFreeSGPR = 0;
3588 unsigned UserSGPRCount = 0;
3589 bool ReserveVCC = true;
3590 bool ReserveFlatScr = true;
3591 bool ReserveXNACK = hasXNACK();
Stanislav Mekhanoshin8bcc9bb2019-06-13 19:18:29 +00003592 Optional<bool> EnableWavefrontSize32;
Scott Linder1e8c2c72018-06-21 19:38:56 +00003593
3594 while (true) {
3595 while (getLexer().is(AsmToken::EndOfStatement))
3596 Lex();
3597
3598 if (getLexer().isNot(AsmToken::Identifier))
3599 return TokError("expected .amdhsa_ directive or .end_amdhsa_kernel");
3600
3601 StringRef ID = getTok().getIdentifier();
3602 SMRange IDRange = getTok().getLocRange();
3603 Lex();
3604
3605 if (ID == ".end_amdhsa_kernel")
3606 break;
3607
3608 if (Seen.find(ID) != Seen.end())
3609 return TokError(".amdhsa_ directives cannot be repeated");
3610 Seen.insert(ID);
3611
3612 SMLoc ValStart = getTok().getLoc();
3613 int64_t IVal;
3614 if (getParser().parseAbsoluteExpression(IVal))
3615 return true;
3616 SMLoc ValEnd = getTok().getLoc();
3617 SMRange ValRange = SMRange(ValStart, ValEnd);
3618
3619 if (IVal < 0)
3620 return OutOfRangeError(ValRange);
3621
3622 uint64_t Val = IVal;
3623
3624#define PARSE_BITS_ENTRY(FIELD, ENTRY, VALUE, RANGE) \
3625 if (!isUInt<ENTRY##_WIDTH>(VALUE)) \
3626 return OutOfRangeError(RANGE); \
3627 AMDHSA_BITS_SET(FIELD, ENTRY, VALUE);
3628
3629 if (ID == ".amdhsa_group_segment_fixed_size") {
3630 if (!isUInt<sizeof(KD.group_segment_fixed_size) * CHAR_BIT>(Val))
3631 return OutOfRangeError(ValRange);
3632 KD.group_segment_fixed_size = Val;
3633 } else if (ID == ".amdhsa_private_segment_fixed_size") {
3634 if (!isUInt<sizeof(KD.private_segment_fixed_size) * CHAR_BIT>(Val))
3635 return OutOfRangeError(ValRange);
3636 KD.private_segment_fixed_size = Val;
3637 } else if (ID == ".amdhsa_user_sgpr_private_segment_buffer") {
3638 PARSE_BITS_ENTRY(KD.kernel_code_properties,
3639 KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER,
3640 Val, ValRange);
Scott Linder04f6f252019-08-28 19:38:15 +00003641 if (Val)
3642 UserSGPRCount += 4;
Scott Linder1e8c2c72018-06-21 19:38:56 +00003643 } else if (ID == ".amdhsa_user_sgpr_dispatch_ptr") {
3644 PARSE_BITS_ENTRY(KD.kernel_code_properties,
3645 KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR, Val,
3646 ValRange);
Scott Linder04f6f252019-08-28 19:38:15 +00003647 if (Val)
3648 UserSGPRCount += 2;
Scott Linder1e8c2c72018-06-21 19:38:56 +00003649 } else if (ID == ".amdhsa_user_sgpr_queue_ptr") {
3650 PARSE_BITS_ENTRY(KD.kernel_code_properties,
3651 KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR, Val,
3652 ValRange);
Scott Linder04f6f252019-08-28 19:38:15 +00003653 if (Val)
3654 UserSGPRCount += 2;
Scott Linder1e8c2c72018-06-21 19:38:56 +00003655 } else if (ID == ".amdhsa_user_sgpr_kernarg_segment_ptr") {
3656 PARSE_BITS_ENTRY(KD.kernel_code_properties,
3657 KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR,
3658 Val, ValRange);
Scott Linder04f6f252019-08-28 19:38:15 +00003659 if (Val)
3660 UserSGPRCount += 2;
Scott Linder1e8c2c72018-06-21 19:38:56 +00003661 } else if (ID == ".amdhsa_user_sgpr_dispatch_id") {
3662 PARSE_BITS_ENTRY(KD.kernel_code_properties,
3663 KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID, Val,
3664 ValRange);
Scott Linder04f6f252019-08-28 19:38:15 +00003665 if (Val)
3666 UserSGPRCount += 2;
Scott Linder1e8c2c72018-06-21 19:38:56 +00003667 } else if (ID == ".amdhsa_user_sgpr_flat_scratch_init") {
3668 PARSE_BITS_ENTRY(KD.kernel_code_properties,
3669 KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT, Val,
3670 ValRange);
Scott Linder04f6f252019-08-28 19:38:15 +00003671 if (Val)
3672 UserSGPRCount += 2;
Scott Linder1e8c2c72018-06-21 19:38:56 +00003673 } else if (ID == ".amdhsa_user_sgpr_private_segment_size") {
3674 PARSE_BITS_ENTRY(KD.kernel_code_properties,
3675 KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE,
3676 Val, ValRange);
Scott Linder04f6f252019-08-28 19:38:15 +00003677 if (Val)
3678 UserSGPRCount += 1;
Stanislav Mekhanoshin5d00c302019-06-17 16:48:56 +00003679 } else if (ID == ".amdhsa_wavefront_size32") {
3680 if (IVersion.Major < 10)
3681 return getParser().Error(IDRange.Start, "directive requires gfx10+",
3682 IDRange);
3683 EnableWavefrontSize32 = Val;
3684 PARSE_BITS_ENTRY(KD.kernel_code_properties,
3685 KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32,
3686 Val, ValRange);
Scott Linder1e8c2c72018-06-21 19:38:56 +00003687 } else if (ID == ".amdhsa_system_sgpr_private_segment_wavefront_offset") {
3688 PARSE_BITS_ENTRY(
3689 KD.compute_pgm_rsrc2,
3690 COMPUTE_PGM_RSRC2_ENABLE_SGPR_PRIVATE_SEGMENT_WAVEFRONT_OFFSET, Val,
3691 ValRange);
3692 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_x") {
3693 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3694 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X, Val,
3695 ValRange);
3696 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_y") {
3697 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3698 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y, Val,
3699 ValRange);
3700 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_z") {
3701 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3702 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z, Val,
3703 ValRange);
3704 } else if (ID == ".amdhsa_system_sgpr_workgroup_info") {
3705 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3706 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO, Val,
3707 ValRange);
3708 } else if (ID == ".amdhsa_system_vgpr_workitem_id") {
3709 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3710 COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID, Val,
3711 ValRange);
3712 } else if (ID == ".amdhsa_next_free_vgpr") {
3713 VGPRRange = ValRange;
3714 NextFreeVGPR = Val;
3715 } else if (ID == ".amdhsa_next_free_sgpr") {
3716 SGPRRange = ValRange;
3717 NextFreeSGPR = Val;
3718 } else if (ID == ".amdhsa_reserve_vcc") {
3719 if (!isUInt<1>(Val))
3720 return OutOfRangeError(ValRange);
3721 ReserveVCC = Val;
3722 } else if (ID == ".amdhsa_reserve_flat_scratch") {
3723 if (IVersion.Major < 7)
3724 return getParser().Error(IDRange.Start, "directive requires gfx7+",
3725 IDRange);
3726 if (!isUInt<1>(Val))
3727 return OutOfRangeError(ValRange);
3728 ReserveFlatScr = Val;
3729 } else if (ID == ".amdhsa_reserve_xnack_mask") {
3730 if (IVersion.Major < 8)
3731 return getParser().Error(IDRange.Start, "directive requires gfx8+",
3732 IDRange);
3733 if (!isUInt<1>(Val))
3734 return OutOfRangeError(ValRange);
3735 ReserveXNACK = Val;
3736 } else if (ID == ".amdhsa_float_round_mode_32") {
3737 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1,
3738 COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32, Val, ValRange);
3739 } else if (ID == ".amdhsa_float_round_mode_16_64") {
3740 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1,
3741 COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64, Val, ValRange);
3742 } else if (ID == ".amdhsa_float_denorm_mode_32") {
3743 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1,
3744 COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32, Val, ValRange);
3745 } else if (ID == ".amdhsa_float_denorm_mode_16_64") {
3746 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1,
3747 COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64, Val,
3748 ValRange);
3749 } else if (ID == ".amdhsa_dx10_clamp") {
3750 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1,
3751 COMPUTE_PGM_RSRC1_ENABLE_DX10_CLAMP, Val, ValRange);
3752 } else if (ID == ".amdhsa_ieee_mode") {
3753 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_ENABLE_IEEE_MODE,
3754 Val, ValRange);
3755 } else if (ID == ".amdhsa_fp16_overflow") {
3756 if (IVersion.Major < 9)
3757 return getParser().Error(IDRange.Start, "directive requires gfx9+",
3758 IDRange);
3759 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_FP16_OVFL, Val,
3760 ValRange);
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00003761 } else if (ID == ".amdhsa_workgroup_processor_mode") {
3762 if (IVersion.Major < 10)
3763 return getParser().Error(IDRange.Start, "directive requires gfx10+",
3764 IDRange);
3765 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_WGP_MODE, Val,
3766 ValRange);
3767 } else if (ID == ".amdhsa_memory_ordered") {
3768 if (IVersion.Major < 10)
3769 return getParser().Error(IDRange.Start, "directive requires gfx10+",
3770 IDRange);
3771 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_MEM_ORDERED, Val,
3772 ValRange);
3773 } else if (ID == ".amdhsa_forward_progress") {
3774 if (IVersion.Major < 10)
3775 return getParser().Error(IDRange.Start, "directive requires gfx10+",
3776 IDRange);
3777 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_FWD_PROGRESS, Val,
3778 ValRange);
Scott Linder1e8c2c72018-06-21 19:38:56 +00003779 } else if (ID == ".amdhsa_exception_fp_ieee_invalid_op") {
3780 PARSE_BITS_ENTRY(
3781 KD.compute_pgm_rsrc2,
3782 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION, Val,
3783 ValRange);
3784 } else if (ID == ".amdhsa_exception_fp_denorm_src") {
3785 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3786 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE,
3787 Val, ValRange);
3788 } else if (ID == ".amdhsa_exception_fp_ieee_div_zero") {
3789 PARSE_BITS_ENTRY(
3790 KD.compute_pgm_rsrc2,
3791 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO, Val,
3792 ValRange);
3793 } else if (ID == ".amdhsa_exception_fp_ieee_overflow") {
3794 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3795 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW,
3796 Val, ValRange);
3797 } else if (ID == ".amdhsa_exception_fp_ieee_underflow") {
3798 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3799 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW,
3800 Val, ValRange);
3801 } else if (ID == ".amdhsa_exception_fp_ieee_inexact") {
3802 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3803 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT,
3804 Val, ValRange);
3805 } else if (ID == ".amdhsa_exception_int_div_zero") {
3806 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3807 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO,
3808 Val, ValRange);
3809 } else {
3810 return getParser().Error(IDRange.Start,
3811 "unknown .amdhsa_kernel directive", IDRange);
3812 }
3813
3814#undef PARSE_BITS_ENTRY
3815 }
3816
3817 if (Seen.find(".amdhsa_next_free_vgpr") == Seen.end())
3818 return TokError(".amdhsa_next_free_vgpr directive is required");
3819
3820 if (Seen.find(".amdhsa_next_free_sgpr") == Seen.end())
3821 return TokError(".amdhsa_next_free_sgpr directive is required");
3822
3823 unsigned VGPRBlocks;
3824 unsigned SGPRBlocks;
3825 if (calculateGPRBlocks(getFeatureBits(), ReserveVCC, ReserveFlatScr,
Stanislav Mekhanoshin8bcc9bb2019-06-13 19:18:29 +00003826 ReserveXNACK, EnableWavefrontSize32, NextFreeVGPR,
3827 VGPRRange, NextFreeSGPR, SGPRRange, VGPRBlocks,
3828 SGPRBlocks))
Scott Linder1e8c2c72018-06-21 19:38:56 +00003829 return true;
3830
3831 if (!isUInt<COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT_WIDTH>(
3832 VGPRBlocks))
3833 return OutOfRangeError(VGPRRange);
3834 AMDHSA_BITS_SET(KD.compute_pgm_rsrc1,
3835 COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT, VGPRBlocks);
3836
3837 if (!isUInt<COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT_WIDTH>(
3838 SGPRBlocks))
3839 return OutOfRangeError(SGPRRange);
3840 AMDHSA_BITS_SET(KD.compute_pgm_rsrc1,
3841 COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT,
3842 SGPRBlocks);
3843
3844 if (!isUInt<COMPUTE_PGM_RSRC2_USER_SGPR_COUNT_WIDTH>(UserSGPRCount))
3845 return TokError("too many user SGPRs enabled");
3846 AMDHSA_BITS_SET(KD.compute_pgm_rsrc2, COMPUTE_PGM_RSRC2_USER_SGPR_COUNT,
3847 UserSGPRCount);
3848
3849 getTargetStreamer().EmitAmdhsaKernelDescriptor(
3850 getSTI(), KernelName, KD, NextFreeVGPR, NextFreeSGPR, ReserveVCC,
3851 ReserveFlatScr, ReserveXNACK);
3852 return false;
3853}
3854
Tom Stellard347ac792015-06-26 21:15:07 +00003855bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() {
Tom Stellard347ac792015-06-26 21:15:07 +00003856 uint32_t Major;
3857 uint32_t Minor;
3858
3859 if (ParseDirectiveMajorMinor(Major, Minor))
3860 return true;
3861
3862 getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor);
3863 return false;
3864}
3865
3866bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() {
Tom Stellard347ac792015-06-26 21:15:07 +00003867 uint32_t Major;
3868 uint32_t Minor;
3869 uint32_t Stepping;
3870 StringRef VendorName;
3871 StringRef ArchName;
3872
3873 // If this directive has no arguments, then use the ISA version for the
3874 // targeted GPU.
3875 if (getLexer().is(AsmToken::EndOfStatement)) {
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00003876 AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU());
Konstantin Zhuravlyov9f89ede2017-02-08 14:05:23 +00003877 getTargetStreamer().EmitDirectiveHSACodeObjectISA(ISA.Major, ISA.Minor,
3878 ISA.Stepping,
Tom Stellard347ac792015-06-26 21:15:07 +00003879 "AMD", "AMDGPU");
3880 return false;
3881 }
3882
Tom Stellard347ac792015-06-26 21:15:07 +00003883 if (ParseDirectiveMajorMinor(Major, Minor))
3884 return true;
3885
3886 if (getLexer().isNot(AsmToken::Comma))
3887 return TokError("stepping version number required, comma expected");
3888 Lex();
3889
Artem Tamazov25478d82016-12-29 15:41:52 +00003890 if (ParseAsAbsoluteExpression(Stepping))
Tom Stellard347ac792015-06-26 21:15:07 +00003891 return TokError("invalid stepping version");
3892
Tom Stellard347ac792015-06-26 21:15:07 +00003893 if (getLexer().isNot(AsmToken::Comma))
3894 return TokError("vendor name required, comma expected");
3895 Lex();
3896
3897 if (getLexer().isNot(AsmToken::String))
3898 return TokError("invalid vendor name");
3899
3900 VendorName = getLexer().getTok().getStringContents();
3901 Lex();
3902
3903 if (getLexer().isNot(AsmToken::Comma))
3904 return TokError("arch name required, comma expected");
3905 Lex();
3906
3907 if (getLexer().isNot(AsmToken::String))
3908 return TokError("invalid arch name");
3909
3910 ArchName = getLexer().getTok().getStringContents();
3911 Lex();
3912
3913 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping,
3914 VendorName, ArchName);
3915 return false;
3916}
3917
Tom Stellardff7416b2015-06-26 21:58:31 +00003918bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID,
3919 amd_kernel_code_t &Header) {
Konstantin Zhuravlyov61830652018-04-09 20:47:22 +00003920 // max_scratch_backing_memory_byte_size is deprecated. Ignore it while parsing
3921 // assembly for backwards compatibility.
3922 if (ID == "max_scratch_backing_memory_byte_size") {
3923 Parser.eatToEndOfStatement();
3924 return false;
3925 }
3926
Valery Pykhtindc110542016-03-06 20:25:36 +00003927 SmallString<40> ErrStr;
3928 raw_svector_ostream Err(ErrStr);
Valery Pykhtina852d692016-06-23 14:13:06 +00003929 if (!parseAmdKernelCodeField(ID, getParser(), Header, Err)) {
Valery Pykhtindc110542016-03-06 20:25:36 +00003930 return TokError(Err.str());
3931 }
Tom Stellardff7416b2015-06-26 21:58:31 +00003932 Lex();
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00003933
Stanislav Mekhanoshin5d00c302019-06-17 16:48:56 +00003934 if (ID == "enable_wavefront_size32") {
3935 if (Header.code_properties & AMD_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32) {
3936 if (!isGFX10())
3937 return TokError("enable_wavefront_size32=1 is only allowed on GFX10+");
3938 if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize32])
3939 return TokError("enable_wavefront_size32=1 requires +WavefrontSize32");
3940 } else {
3941 if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize64])
3942 return TokError("enable_wavefront_size32=0 requires +WavefrontSize64");
3943 }
3944 }
3945
3946 if (ID == "wavefront_size") {
3947 if (Header.wavefront_size == 5) {
3948 if (!isGFX10())
3949 return TokError("wavefront_size=5 is only allowed on GFX10+");
3950 if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize32])
3951 return TokError("wavefront_size=5 requires +WavefrontSize32");
3952 } else if (Header.wavefront_size == 6) {
3953 if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize64])
3954 return TokError("wavefront_size=6 requires +WavefrontSize64");
3955 }
3956 }
3957
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00003958 if (ID == "enable_wgp_mode") {
3959 if (G_00B848_WGP_MODE(Header.compute_pgm_resource_registers) && !isGFX10())
3960 return TokError("enable_wgp_mode=1 is only allowed on GFX10+");
3961 }
3962
3963 if (ID == "enable_mem_ordered") {
3964 if (G_00B848_MEM_ORDERED(Header.compute_pgm_resource_registers) && !isGFX10())
3965 return TokError("enable_mem_ordered=1 is only allowed on GFX10+");
3966 }
3967
3968 if (ID == "enable_fwd_progress") {
3969 if (G_00B848_FWD_PROGRESS(Header.compute_pgm_resource_registers) && !isGFX10())
3970 return TokError("enable_fwd_progress=1 is only allowed on GFX10+");
3971 }
3972
Tom Stellardff7416b2015-06-26 21:58:31 +00003973 return false;
3974}
3975
3976bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() {
Tom Stellardff7416b2015-06-26 21:58:31 +00003977 amd_kernel_code_t Header;
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00003978 AMDGPU::initDefaultAMDKernelCodeT(Header, &getSTI());
Tom Stellardff7416b2015-06-26 21:58:31 +00003979
3980 while (true) {
Tom Stellardff7416b2015-06-26 21:58:31 +00003981 // Lex EndOfStatement. This is in a while loop, because lexing a comment
3982 // will set the current token to EndOfStatement.
3983 while(getLexer().is(AsmToken::EndOfStatement))
3984 Lex();
3985
3986 if (getLexer().isNot(AsmToken::Identifier))
3987 return TokError("expected value identifier or .end_amd_kernel_code_t");
3988
3989 StringRef ID = getLexer().getTok().getIdentifier();
3990 Lex();
3991
3992 if (ID == ".end_amd_kernel_code_t")
3993 break;
3994
3995 if (ParseAMDKernelCodeTValue(ID, Header))
3996 return true;
3997 }
3998
3999 getTargetStreamer().EmitAMDKernelCodeT(Header);
4000
4001 return false;
4002}
4003
Tom Stellard1e1b05d2015-11-06 11:45:14 +00004004bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() {
4005 if (getLexer().isNot(AsmToken::Identifier))
4006 return TokError("expected symbol name");
4007
4008 StringRef KernelName = Parser.getTok().getString();
4009
4010 getTargetStreamer().EmitAMDGPUSymbolType(KernelName,
4011 ELF::STT_AMDGPU_HSA_KERNEL);
4012 Lex();
Scott Linder1e8c2c72018-06-21 19:38:56 +00004013 if (!AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI()))
4014 KernelScope.initialize(getContext());
Tom Stellard1e1b05d2015-11-06 11:45:14 +00004015 return false;
4016}
4017
Konstantin Zhuravlyov9c05b2b2017-10-14 15:40:33 +00004018bool AMDGPUAsmParser::ParseDirectiveISAVersion() {
Konstantin Zhuravlyov219066b2017-10-14 16:15:28 +00004019 if (getSTI().getTargetTriple().getArch() != Triple::amdgcn) {
4020 return Error(getParser().getTok().getLoc(),
4021 ".amd_amdgpu_isa directive is not available on non-amdgcn "
4022 "architectures");
4023 }
4024
Konstantin Zhuravlyov9c05b2b2017-10-14 15:40:33 +00004025 auto ISAVersionStringFromASM = getLexer().getTok().getStringContents();
4026
4027 std::string ISAVersionStringFromSTI;
4028 raw_string_ostream ISAVersionStreamFromSTI(ISAVersionStringFromSTI);
4029 IsaInfo::streamIsaVersion(&getSTI(), ISAVersionStreamFromSTI);
4030
4031 if (ISAVersionStringFromASM != ISAVersionStreamFromSTI.str()) {
4032 return Error(getParser().getTok().getLoc(),
4033 ".amd_amdgpu_isa directive does not match triple and/or mcpu "
4034 "arguments specified through the command line");
4035 }
4036
4037 getTargetStreamer().EmitISAVersion(ISAVersionStreamFromSTI.str());
4038 Lex();
4039
4040 return false;
4041}
4042
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +00004043bool AMDGPUAsmParser::ParseDirectiveHSAMetadata() {
Scott Linderf5b36e52018-12-12 19:39:27 +00004044 const char *AssemblerDirectiveBegin;
4045 const char *AssemblerDirectiveEnd;
4046 std::tie(AssemblerDirectiveBegin, AssemblerDirectiveEnd) =
4047 AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())
4048 ? std::make_tuple(HSAMD::V3::AssemblerDirectiveBegin,
4049 HSAMD::V3::AssemblerDirectiveEnd)
4050 : std::make_tuple(HSAMD::AssemblerDirectiveBegin,
4051 HSAMD::AssemblerDirectiveEnd);
4052
Konstantin Zhuravlyov219066b2017-10-14 16:15:28 +00004053 if (getSTI().getTargetTriple().getOS() != Triple::AMDHSA) {
4054 return Error(getParser().getTok().getLoc(),
Scott Linderf5b36e52018-12-12 19:39:27 +00004055 (Twine(AssemblerDirectiveBegin) + Twine(" directive is "
Konstantin Zhuravlyov219066b2017-10-14 16:15:28 +00004056 "not available on non-amdhsa OSes")).str());
4057 }
4058
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +00004059 std::string HSAMetadataString;
Tim Renoufe7bd52f2019-03-20 18:47:21 +00004060 if (ParseToEndDirective(AssemblerDirectiveBegin, AssemblerDirectiveEnd,
4061 HSAMetadataString))
4062 return true;
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +00004063
Scott Linderf5b36e52018-12-12 19:39:27 +00004064 if (IsaInfo::hasCodeObjectV3(&getSTI())) {
4065 if (!getTargetStreamer().EmitHSAMetadataV3(HSAMetadataString))
4066 return Error(getParser().getTok().getLoc(), "invalid HSA metadata");
4067 } else {
4068 if (!getTargetStreamer().EmitHSAMetadataV2(HSAMetadataString))
4069 return Error(getParser().getTok().getLoc(), "invalid HSA metadata");
4070 }
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +00004071
4072 return false;
4073}
4074
Tim Renoufe7bd52f2019-03-20 18:47:21 +00004075/// Common code to parse out a block of text (typically YAML) between start and
4076/// end directives.
4077bool AMDGPUAsmParser::ParseToEndDirective(const char *AssemblerDirectiveBegin,
4078 const char *AssemblerDirectiveEnd,
4079 std::string &CollectString) {
4080
4081 raw_string_ostream CollectStream(CollectString);
4082
4083 getLexer().setSkipSpace(false);
4084
4085 bool FoundEnd = false;
4086 while (!getLexer().is(AsmToken::Eof)) {
4087 while (getLexer().is(AsmToken::Space)) {
4088 CollectStream << getLexer().getTok().getString();
4089 Lex();
4090 }
4091
4092 if (getLexer().is(AsmToken::Identifier)) {
4093 StringRef ID = getLexer().getTok().getIdentifier();
4094 if (ID == AssemblerDirectiveEnd) {
4095 Lex();
4096 FoundEnd = true;
4097 break;
4098 }
4099 }
4100
4101 CollectStream << Parser.parseStringToEndOfStatement()
4102 << getContext().getAsmInfo()->getSeparatorString();
4103
4104 Parser.eatToEndOfStatement();
4105 }
4106
4107 getLexer().setSkipSpace(true);
4108
4109 if (getLexer().is(AsmToken::Eof) && !FoundEnd) {
4110 return TokError(Twine("expected directive ") +
4111 Twine(AssemblerDirectiveEnd) + Twine(" not found"));
4112 }
4113
4114 CollectStream.flush();
4115 return false;
4116}
4117
4118/// Parse the assembler directive for new MsgPack-format PAL metadata.
4119bool AMDGPUAsmParser::ParseDirectivePALMetadataBegin() {
4120 std::string String;
4121 if (ParseToEndDirective(AMDGPU::PALMD::AssemblerDirectiveBegin,
4122 AMDGPU::PALMD::AssemblerDirectiveEnd, String))
4123 return true;
4124
4125 auto PALMetadata = getTargetStreamer().getPALMetadata();
4126 if (!PALMetadata->setFromString(String))
4127 return Error(getParser().getTok().getLoc(), "invalid PAL metadata");
4128 return false;
4129}
4130
4131/// Parse the assembler directive for old linear-format PAL metadata.
Konstantin Zhuravlyovc3beb6a2017-10-11 22:41:09 +00004132bool AMDGPUAsmParser::ParseDirectivePALMetadata() {
Konstantin Zhuravlyov219066b2017-10-14 16:15:28 +00004133 if (getSTI().getTargetTriple().getOS() != Triple::AMDPAL) {
4134 return Error(getParser().getTok().getLoc(),
4135 (Twine(PALMD::AssemblerDirective) + Twine(" directive is "
4136 "not available on non-amdpal OSes")).str());
4137 }
4138
Tim Renoufd737b552019-03-20 17:42:00 +00004139 auto PALMetadata = getTargetStreamer().getPALMetadata();
Tim Renoufe7bd52f2019-03-20 18:47:21 +00004140 PALMetadata->setLegacy();
Tim Renouf72800f02017-10-03 19:03:52 +00004141 for (;;) {
Tim Renoufd737b552019-03-20 17:42:00 +00004142 uint32_t Key, Value;
4143 if (ParseAsAbsoluteExpression(Key)) {
4144 return TokError(Twine("invalid value in ") +
4145 Twine(PALMD::AssemblerDirective));
4146 }
4147 if (getLexer().isNot(AsmToken::Comma)) {
4148 return TokError(Twine("expected an even number of values in ") +
4149 Twine(PALMD::AssemblerDirective));
4150 }
4151 Lex();
Konstantin Zhuravlyovc3beb6a2017-10-11 22:41:09 +00004152 if (ParseAsAbsoluteExpression(Value)) {
4153 return TokError(Twine("invalid value in ") +
4154 Twine(PALMD::AssemblerDirective));
4155 }
Tim Renoufd737b552019-03-20 17:42:00 +00004156 PALMetadata->setRegister(Key, Value);
Tim Renouf72800f02017-10-03 19:03:52 +00004157 if (getLexer().isNot(AsmToken::Comma))
4158 break;
4159 Lex();
4160 }
Tim Renouf72800f02017-10-03 19:03:52 +00004161 return false;
4162}
4163
Nicolai Haehnle08e8cb52019-06-25 11:51:35 +00004164/// ParseDirectiveAMDGPULDS
4165/// ::= .amdgpu_lds identifier ',' size_expression [',' align_expression]
4166bool AMDGPUAsmParser::ParseDirectiveAMDGPULDS() {
4167 if (getParser().checkForValidSection())
4168 return true;
4169
4170 StringRef Name;
4171 SMLoc NameLoc = getLexer().getLoc();
4172 if (getParser().parseIdentifier(Name))
4173 return TokError("expected identifier in directive");
4174
4175 MCSymbol *Symbol = getContext().getOrCreateSymbol(Name);
4176 if (parseToken(AsmToken::Comma, "expected ','"))
4177 return true;
4178
4179 unsigned LocalMemorySize = AMDGPU::IsaInfo::getLocalMemorySize(&getSTI());
4180
4181 int64_t Size;
4182 SMLoc SizeLoc = getLexer().getLoc();
4183 if (getParser().parseAbsoluteExpression(Size))
4184 return true;
4185 if (Size < 0)
4186 return Error(SizeLoc, "size must be non-negative");
4187 if (Size > LocalMemorySize)
4188 return Error(SizeLoc, "size is too large");
4189
4190 int64_t Align = 4;
4191 if (getLexer().is(AsmToken::Comma)) {
4192 Lex();
4193 SMLoc AlignLoc = getLexer().getLoc();
4194 if (getParser().parseAbsoluteExpression(Align))
4195 return true;
4196 if (Align < 0 || !isPowerOf2_64(Align))
4197 return Error(AlignLoc, "alignment must be a power of two");
4198
4199 // Alignment larger than the size of LDS is possible in theory, as long
4200 // as the linker manages to place to symbol at address 0, but we do want
4201 // to make sure the alignment fits nicely into a 32-bit integer.
4202 if (Align >= 1u << 31)
4203 return Error(AlignLoc, "alignment is too large");
4204 }
4205
4206 if (parseToken(AsmToken::EndOfStatement,
4207 "unexpected token in '.amdgpu_lds' directive"))
4208 return true;
4209
4210 Symbol->redefineIfPossible();
4211 if (!Symbol->isUndefined())
4212 return Error(NameLoc, "invalid symbol redefinition");
4213
4214 getTargetStreamer().emitAMDGPULDS(Symbol, Size, Align);
4215 return false;
4216}
4217
Tom Stellard45bb48e2015-06-13 03:28:10 +00004218bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
Tom Stellard347ac792015-06-26 21:15:07 +00004219 StringRef IDVal = DirectiveID.getString();
4220
Scott Linder1e8c2c72018-06-21 19:38:56 +00004221 if (AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) {
4222 if (IDVal == ".amdgcn_target")
4223 return ParseDirectiveAMDGCNTarget();
Tom Stellard347ac792015-06-26 21:15:07 +00004224
Scott Linder1e8c2c72018-06-21 19:38:56 +00004225 if (IDVal == ".amdhsa_kernel")
4226 return ParseDirectiveAMDHSAKernel();
Scott Linderf5b36e52018-12-12 19:39:27 +00004227
4228 // TODO: Restructure/combine with PAL metadata directive.
4229 if (IDVal == AMDGPU::HSAMD::V3::AssemblerDirectiveBegin)
4230 return ParseDirectiveHSAMetadata();
Scott Linder1e8c2c72018-06-21 19:38:56 +00004231 } else {
4232 if (IDVal == ".hsa_code_object_version")
4233 return ParseDirectiveHSACodeObjectVersion();
Tom Stellard347ac792015-06-26 21:15:07 +00004234
Scott Linder1e8c2c72018-06-21 19:38:56 +00004235 if (IDVal == ".hsa_code_object_isa")
4236 return ParseDirectiveHSACodeObjectISA();
Tom Stellardff7416b2015-06-26 21:58:31 +00004237
Scott Linder1e8c2c72018-06-21 19:38:56 +00004238 if (IDVal == ".amd_kernel_code_t")
4239 return ParseDirectiveAMDKernelCodeT();
Tom Stellard1e1b05d2015-11-06 11:45:14 +00004240
Scott Linder1e8c2c72018-06-21 19:38:56 +00004241 if (IDVal == ".amdgpu_hsa_kernel")
4242 return ParseDirectiveAMDGPUHsaKernel();
4243
4244 if (IDVal == ".amd_amdgpu_isa")
4245 return ParseDirectiveISAVersion();
Konstantin Zhuravlyov9c05b2b2017-10-14 15:40:33 +00004246
Scott Linderf5b36e52018-12-12 19:39:27 +00004247 if (IDVal == AMDGPU::HSAMD::AssemblerDirectiveBegin)
4248 return ParseDirectiveHSAMetadata();
4249 }
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +00004250
Nicolai Haehnle08e8cb52019-06-25 11:51:35 +00004251 if (IDVal == ".amdgpu_lds")
4252 return ParseDirectiveAMDGPULDS();
4253
Tim Renoufe7bd52f2019-03-20 18:47:21 +00004254 if (IDVal == PALMD::AssemblerDirectiveBegin)
4255 return ParseDirectivePALMetadataBegin();
4256
Konstantin Zhuravlyovc3beb6a2017-10-11 22:41:09 +00004257 if (IDVal == PALMD::AssemblerDirective)
4258 return ParseDirectivePALMetadata();
Tim Renouf72800f02017-10-03 19:03:52 +00004259
Tom Stellard45bb48e2015-06-13 03:28:10 +00004260 return true;
4261}
4262
Matt Arsenault68802d32015-11-05 03:11:27 +00004263bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI,
4264 unsigned RegNo) const {
Dmitry Preobrazhenskyac2b0262017-12-11 15:23:20 +00004265
4266 for (MCRegAliasIterator R(AMDGPU::TTMP12_TTMP13_TTMP14_TTMP15, &MRI, true);
4267 R.isValid(); ++R) {
4268 if (*R == RegNo)
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00004269 return isGFX9() || isGFX10();
4270 }
4271
4272 // GFX10 has 2 more SGPRs 104 and 105.
4273 for (MCRegAliasIterator R(AMDGPU::SGPR104_SGPR105, &MRI, true);
4274 R.isValid(); ++R) {
4275 if (*R == RegNo)
4276 return hasSGPR104_SGPR105();
Dmitry Preobrazhenskyac2b0262017-12-11 15:23:20 +00004277 }
4278
4279 switch (RegNo) {
Dmitry Preobrazhensky9111f352019-06-03 13:51:24 +00004280 case AMDGPU::SRC_SHARED_BASE:
4281 case AMDGPU::SRC_SHARED_LIMIT:
4282 case AMDGPU::SRC_PRIVATE_BASE:
4283 case AMDGPU::SRC_PRIVATE_LIMIT:
4284 case AMDGPU::SRC_POPS_EXITING_WAVE_ID:
4285 return !isCI() && !isSI() && !isVI();
Dmitry Preobrazhenskyac2b0262017-12-11 15:23:20 +00004286 case AMDGPU::TBA:
4287 case AMDGPU::TBA_LO:
4288 case AMDGPU::TBA_HI:
4289 case AMDGPU::TMA:
4290 case AMDGPU::TMA_LO:
4291 case AMDGPU::TMA_HI:
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00004292 return !isGFX9() && !isGFX10();
Dmitry Preobrazhensky3afbd822018-01-10 14:22:19 +00004293 case AMDGPU::XNACK_MASK:
4294 case AMDGPU::XNACK_MASK_LO:
4295 case AMDGPU::XNACK_MASK_HI:
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00004296 return !isCI() && !isSI() && !isGFX10() && hasXNACK();
4297 case AMDGPU::SGPR_NULL:
4298 return isGFX10();
Dmitry Preobrazhenskyac2b0262017-12-11 15:23:20 +00004299 default:
4300 break;
4301 }
4302
Matt Arsenault3b159672015-12-01 20:31:08 +00004303 if (isCI())
Matt Arsenault68802d32015-11-05 03:11:27 +00004304 return true;
4305
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00004306 if (isSI() || isGFX10()) {
4307 // No flat_scr on SI.
4308 // On GFX10 flat scratch is not a valid register operand and can only be
4309 // accessed with s_setreg/s_getreg.
Matt Arsenault3b159672015-12-01 20:31:08 +00004310 switch (RegNo) {
4311 case AMDGPU::FLAT_SCR:
4312 case AMDGPU::FLAT_SCR_LO:
4313 case AMDGPU::FLAT_SCR_HI:
4314 return false;
4315 default:
4316 return true;
4317 }
4318 }
4319
Matt Arsenault68802d32015-11-05 03:11:27 +00004320 // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that
4321 // SI/CI have.
4322 for (MCRegAliasIterator R(AMDGPU::SGPR102_SGPR103, &MRI, true);
4323 R.isValid(); ++R) {
4324 if (*R == RegNo)
Stanislav Mekhanoshin33d806a2019-04-24 17:28:30 +00004325 return hasSGPR102_SGPR103();
Matt Arsenault68802d32015-11-05 03:11:27 +00004326 }
4327
4328 return true;
4329}
4330
Alex Bradbury58eba092016-11-01 16:32:05 +00004331OperandMatchResultTy
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00004332AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic,
4333 OperandMode Mode) {
Tom Stellard45bb48e2015-06-13 03:28:10 +00004334 // Try to parse with a custom parser
4335 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4336
4337 // If we successfully parsed the operand or if there as an error parsing,
4338 // we are done.
4339 //
4340 // If we are parsing after we reach EndOfStatement then this means we
4341 // are appending default values to the Operands list. This is only done
4342 // by custom parser, so we shouldn't continue on to the generic parsing.
Sam Kolton1bdcef72016-05-23 09:59:02 +00004343 if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail ||
Tom Stellard45bb48e2015-06-13 03:28:10 +00004344 getLexer().is(AsmToken::EndOfStatement))
4345 return ResTy;
4346
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00004347 if (Mode == OperandMode_NSA && getLexer().is(AsmToken::LBrac)) {
4348 unsigned Prefix = Operands.size();
4349 SMLoc LBraceLoc = getTok().getLoc();
4350 Parser.Lex(); // eat the '['
4351
4352 for (;;) {
4353 ResTy = parseReg(Operands);
4354 if (ResTy != MatchOperand_Success)
4355 return ResTy;
4356
4357 if (getLexer().is(AsmToken::RBrac))
4358 break;
4359
4360 if (getLexer().isNot(AsmToken::Comma))
4361 return MatchOperand_ParseFail;
4362 Parser.Lex();
4363 }
4364
4365 if (Operands.size() - Prefix > 1) {
4366 Operands.insert(Operands.begin() + Prefix,
4367 AMDGPUOperand::CreateToken(this, "[", LBraceLoc));
4368 Operands.push_back(AMDGPUOperand::CreateToken(this, "]",
4369 getTok().getLoc()));
4370 }
4371
4372 Parser.Lex(); // eat the ']'
4373 return MatchOperand_Success;
4374 }
4375
Dmitry Preobrazhensky43fcc792019-05-17 13:17:48 +00004376 return parseRegOrImm(Operands);
Tom Stellard45bb48e2015-06-13 03:28:10 +00004377}
4378
Sam Kolton05ef1c92016-06-03 10:27:37 +00004379StringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) {
4380 // Clear any forced encodings from the previous instruction.
4381 setForcedEncodingSize(0);
4382 setForcedDPP(false);
4383 setForcedSDWA(false);
4384
4385 if (Name.endswith("_e64")) {
4386 setForcedEncodingSize(64);
4387 return Name.substr(0, Name.size() - 4);
4388 } else if (Name.endswith("_e32")) {
4389 setForcedEncodingSize(32);
4390 return Name.substr(0, Name.size() - 4);
4391 } else if (Name.endswith("_dpp")) {
4392 setForcedDPP(true);
4393 return Name.substr(0, Name.size() - 4);
4394 } else if (Name.endswith("_sdwa")) {
4395 setForcedSDWA(true);
4396 return Name.substr(0, Name.size() - 5);
4397 }
4398 return Name;
4399}
4400
Tom Stellard45bb48e2015-06-13 03:28:10 +00004401bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info,
4402 StringRef Name,
4403 SMLoc NameLoc, OperandVector &Operands) {
Tom Stellard45bb48e2015-06-13 03:28:10 +00004404 // Add the instruction mnemonic
Sam Kolton05ef1c92016-06-03 10:27:37 +00004405 Name = parseMnemonicSuffix(Name);
Sam Kolton1eeb11b2016-09-09 14:44:04 +00004406 Operands.push_back(AMDGPUOperand::CreateToken(this, Name, NameLoc));
Matt Arsenault37fefd62016-06-10 02:18:02 +00004407
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00004408 bool IsMIMG = Name.startswith("image_");
4409
Tom Stellard45bb48e2015-06-13 03:28:10 +00004410 while (!getLexer().is(AsmToken::EndOfStatement)) {
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00004411 OperandMode Mode = OperandMode_Default;
4412 if (IsMIMG && isGFX10() && Operands.size() == 2)
4413 Mode = OperandMode_NSA;
4414 OperandMatchResultTy Res = parseOperand(Operands, Name, Mode);
Tom Stellard45bb48e2015-06-13 03:28:10 +00004415
4416 // Eat the comma or space if there is one.
4417 if (getLexer().is(AsmToken::Comma))
4418 Parser.Lex();
Matt Arsenault37fefd62016-06-10 02:18:02 +00004419
Tom Stellard45bb48e2015-06-13 03:28:10 +00004420 switch (Res) {
4421 case MatchOperand_Success: break;
Matt Arsenault37fefd62016-06-10 02:18:02 +00004422 case MatchOperand_ParseFail:
Dmitry Preobrazhensky7773fc42019-05-22 13:59:01 +00004423 // FIXME: use real operand location rather than the current location.
Sam Kolton1bdcef72016-05-23 09:59:02 +00004424 Error(getLexer().getLoc(), "failed parsing operand.");
4425 while (!getLexer().is(AsmToken::EndOfStatement)) {
4426 Parser.Lex();
4427 }
4428 return true;
Matt Arsenault37fefd62016-06-10 02:18:02 +00004429 case MatchOperand_NoMatch:
Dmitry Preobrazhensky7773fc42019-05-22 13:59:01 +00004430 // FIXME: use real operand location rather than the current location.
Sam Kolton1bdcef72016-05-23 09:59:02 +00004431 Error(getLexer().getLoc(), "not a valid operand.");
4432 while (!getLexer().is(AsmToken::EndOfStatement)) {
4433 Parser.Lex();
4434 }
4435 return true;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004436 }
4437 }
4438
Tom Stellard45bb48e2015-06-13 03:28:10 +00004439 return false;
4440}
4441
4442//===----------------------------------------------------------------------===//
4443// Utility functions
4444//===----------------------------------------------------------------------===//
4445
Alex Bradbury58eba092016-11-01 16:32:05 +00004446OperandMatchResultTy
Dmitry Preobrazhensky198611b2019-05-17 16:04:17 +00004447AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &IntVal) {
Tom Stellard45bb48e2015-06-13 03:28:10 +00004448
Dmitry Preobrazhensky198611b2019-05-17 16:04:17 +00004449 if (!trySkipId(Prefix, AsmToken::Colon))
4450 return MatchOperand_NoMatch;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004451
Dmitry Preobrazhensky198611b2019-05-17 16:04:17 +00004452 return parseExpr(IntVal) ? MatchOperand_Success : MatchOperand_ParseFail;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004453}
4454
Alex Bradbury58eba092016-11-01 16:32:05 +00004455OperandMatchResultTy
Tom Stellard45bb48e2015-06-13 03:28:10 +00004456AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
Matt Arsenaultf15da6c2017-02-03 20:49:51 +00004457 AMDGPUOperand::ImmTy ImmTy,
Nikolay Haustov4f672a32016-04-29 09:02:30 +00004458 bool (*ConvertResult)(int64_t&)) {
Dmitry Preobrazhensky198611b2019-05-17 16:04:17 +00004459 SMLoc S = getLoc();
Nikolay Haustov4f672a32016-04-29 09:02:30 +00004460 int64_t Value = 0;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004461
Alex Bradbury58eba092016-11-01 16:32:05 +00004462 OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Value);
Tom Stellard45bb48e2015-06-13 03:28:10 +00004463 if (Res != MatchOperand_Success)
4464 return Res;
4465
Nikolay Haustov4f672a32016-04-29 09:02:30 +00004466 if (ConvertResult && !ConvertResult(Value)) {
Dmitry Preobrazhensky198611b2019-05-17 16:04:17 +00004467 Error(S, "invalid " + StringRef(Prefix) + " value.");
Nikolay Haustov4f672a32016-04-29 09:02:30 +00004468 }
4469
Sam Kolton1eeb11b2016-09-09 14:44:04 +00004470 Operands.push_back(AMDGPUOperand::CreateImm(this, Value, S, ImmTy));
Tom Stellard45bb48e2015-06-13 03:28:10 +00004471 return MatchOperand_Success;
4472}
4473
Dmitry Preobrazhensky7773fc42019-05-22 13:59:01 +00004474OperandMatchResultTy
4475AMDGPUAsmParser::parseOperandArrayWithPrefix(const char *Prefix,
4476 OperandVector &Operands,
4477 AMDGPUOperand::ImmTy ImmTy,
4478 bool (*ConvertResult)(int64_t&)) {
4479 SMLoc S = getLoc();
4480 if (!trySkipId(Prefix, AsmToken::Colon))
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00004481 return MatchOperand_NoMatch;
4482
Dmitry Preobrazhensky7773fc42019-05-22 13:59:01 +00004483 if (!skipToken(AsmToken::LBrac, "expected a left square bracket"))
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00004484 return MatchOperand_ParseFail;
4485
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00004486 unsigned Val = 0;
Dmitry Preobrazhensky7773fc42019-05-22 13:59:01 +00004487 const unsigned MaxSize = 4;
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00004488
4489 // FIXME: How to verify the number of elements matches the number of src
4490 // operands?
Dmitry Preobrazhensky7773fc42019-05-22 13:59:01 +00004491 for (int I = 0; ; ++I) {
4492 int64_t Op;
4493 SMLoc Loc = getLoc();
4494 if (!parseExpr(Op))
4495 return MatchOperand_ParseFail;
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00004496
Dmitry Preobrazhensky7773fc42019-05-22 13:59:01 +00004497 if (Op != 0 && Op != 1) {
4498 Error(Loc, "invalid " + StringRef(Prefix) + " value.");
4499 return MatchOperand_ParseFail;
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00004500 }
4501
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00004502 Val |= (Op << I);
Dmitry Preobrazhensky7773fc42019-05-22 13:59:01 +00004503
4504 if (trySkipToken(AsmToken::RBrac))
4505 break;
4506
4507 if (I + 1 == MaxSize) {
4508 Error(getLoc(), "expected a closing square bracket");
4509 return MatchOperand_ParseFail;
4510 }
4511
4512 if (!skipToken(AsmToken::Comma, "expected a comma"))
4513 return MatchOperand_ParseFail;
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00004514 }
4515
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00004516 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S, ImmTy));
4517 return MatchOperand_Success;
4518}
4519
Alex Bradbury58eba092016-11-01 16:32:05 +00004520OperandMatchResultTy
Tom Stellard45bb48e2015-06-13 03:28:10 +00004521AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands,
Matt Arsenaultf15da6c2017-02-03 20:49:51 +00004522 AMDGPUOperand::ImmTy ImmTy) {
Tom Stellard45bb48e2015-06-13 03:28:10 +00004523 int64_t Bit = 0;
4524 SMLoc S = Parser.getTok().getLoc();
4525
4526 // We are at the end of the statement, and this is a default argument, so
4527 // use a default value.
4528 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4529 switch(getLexer().getKind()) {
4530 case AsmToken::Identifier: {
4531 StringRef Tok = Parser.getTok().getString();
4532 if (Tok == Name) {
Ryan Taylor1f334d02018-08-28 15:07:30 +00004533 if (Tok == "r128" && isGFX9())
4534 Error(S, "r128 modifier is not supported on this GPU");
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +00004535 if (Tok == "a16" && !isGFX9() && !isGFX10())
Ryan Taylor1f334d02018-08-28 15:07:30 +00004536 Error(S, "a16 modifier is not supported on this GPU");
Tom Stellard45bb48e2015-06-13 03:28:10 +00004537 Bit = 1;
4538 Parser.Lex();
4539 } else if (Tok.startswith("no") && Tok.endswith(Name)) {
4540 Bit = 0;
4541 Parser.Lex();
4542 } else {
Sam Kolton11de3702016-05-24 12:38:33 +00004543 return MatchOperand_NoMatch;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004544 }
4545 break;
4546 }
4547 default:
4548 return MatchOperand_NoMatch;
4549 }
4550 }
4551
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00004552 if (!isGFX10() && ImmTy == AMDGPUOperand::ImmTyDLC)
4553 return MatchOperand_ParseFail;
4554
Sam Kolton1eeb11b2016-09-09 14:44:04 +00004555 Operands.push_back(AMDGPUOperand::CreateImm(this, Bit, S, ImmTy));
Tom Stellard45bb48e2015-06-13 03:28:10 +00004556 return MatchOperand_Success;
4557}
4558
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00004559static void addOptionalImmOperand(
4560 MCInst& Inst, const OperandVector& Operands,
4561 AMDGPUAsmParser::OptionalImmIndexMap& OptionalIdx,
4562 AMDGPUOperand::ImmTy ImmT,
4563 int64_t Default = 0) {
Nikolay Haustov2e4c7292016-02-25 10:58:54 +00004564 auto i = OptionalIdx.find(ImmT);
4565 if (i != OptionalIdx.end()) {
4566 unsigned Idx = i->second;
4567 ((AMDGPUOperand &)*Operands[Idx]).addImmOperands(Inst, 1);
4568 } else {
Sam Koltondfa29f72016-03-09 12:29:31 +00004569 Inst.addOperand(MCOperand::createImm(Default));
Nikolay Haustov2e4c7292016-02-25 10:58:54 +00004570 }
4571}
4572
Alex Bradbury58eba092016-11-01 16:32:05 +00004573OperandMatchResultTy
Sam Kolton05ef1c92016-06-03 10:27:37 +00004574AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix, StringRef &Value) {
Sam Kolton3025e7f2016-04-26 13:33:56 +00004575 if (getLexer().isNot(AsmToken::Identifier)) {
4576 return MatchOperand_NoMatch;
4577 }
4578 StringRef Tok = Parser.getTok().getString();
4579 if (Tok != Prefix) {
4580 return MatchOperand_NoMatch;
4581 }
4582
4583 Parser.Lex();
4584 if (getLexer().isNot(AsmToken::Colon)) {
4585 return MatchOperand_ParseFail;
4586 }
Matt Arsenault37fefd62016-06-10 02:18:02 +00004587
Sam Kolton3025e7f2016-04-26 13:33:56 +00004588 Parser.Lex();
4589 if (getLexer().isNot(AsmToken::Identifier)) {
4590 return MatchOperand_ParseFail;
4591 }
4592
4593 Value = Parser.getTok().getString();
4594 return MatchOperand_Success;
4595}
4596
Tim Renouf35484c92018-08-21 11:06:05 +00004597// dfmt and nfmt (in a tbuffer instruction) are parsed as one to allow their
4598// values to live in a joint format operand in the MCInst encoding.
4599OperandMatchResultTy
4600AMDGPUAsmParser::parseDfmtNfmt(OperandVector &Operands) {
4601 SMLoc S = Parser.getTok().getLoc();
4602 int64_t Dfmt = 0, Nfmt = 0;
4603 // dfmt and nfmt can appear in either order, and each is optional.
4604 bool GotDfmt = false, GotNfmt = false;
4605 while (!GotDfmt || !GotNfmt) {
4606 if (!GotDfmt) {
4607 auto Res = parseIntWithPrefix("dfmt", Dfmt);
4608 if (Res != MatchOperand_NoMatch) {
4609 if (Res != MatchOperand_Success)
4610 return Res;
4611 if (Dfmt >= 16) {
4612 Error(Parser.getTok().getLoc(), "out of range dfmt");
4613 return MatchOperand_ParseFail;
4614 }
4615 GotDfmt = true;
4616 Parser.Lex();
4617 continue;
4618 }
4619 }
4620 if (!GotNfmt) {
4621 auto Res = parseIntWithPrefix("nfmt", Nfmt);
4622 if (Res != MatchOperand_NoMatch) {
4623 if (Res != MatchOperand_Success)
4624 return Res;
4625 if (Nfmt >= 8) {
4626 Error(Parser.getTok().getLoc(), "out of range nfmt");
4627 return MatchOperand_ParseFail;
4628 }
4629 GotNfmt = true;
4630 Parser.Lex();
4631 continue;
4632 }
4633 }
4634 break;
4635 }
4636 if (!GotDfmt && !GotNfmt)
4637 return MatchOperand_NoMatch;
4638 auto Format = Dfmt | Nfmt << 4;
4639 Operands.push_back(
4640 AMDGPUOperand::CreateImm(this, Format, S, AMDGPUOperand::ImmTyFORMAT));
4641 return MatchOperand_Success;
4642}
4643
Tom Stellard45bb48e2015-06-13 03:28:10 +00004644//===----------------------------------------------------------------------===//
4645// ds
4646//===----------------------------------------------------------------------===//
4647
Tom Stellard45bb48e2015-06-13 03:28:10 +00004648void AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst,
4649 const OperandVector &Operands) {
Nikolay Haustov2e4c7292016-02-25 10:58:54 +00004650 OptionalImmIndexMap OptionalIdx;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004651
4652 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
4653 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
4654
4655 // Add the register arguments
4656 if (Op.isReg()) {
4657 Op.addRegOperands(Inst, 1);
4658 continue;
4659 }
4660
4661 // Handle optional arguments
4662 OptionalIdx[Op.getImmTy()] = i;
4663 }
4664
Nikolay Haustov4f672a32016-04-29 09:02:30 +00004665 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset0);
4666 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset1);
Nikolay Haustov2e4c7292016-02-25 10:58:54 +00004667 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
Tom Stellard45bb48e2015-06-13 03:28:10 +00004668
Tom Stellard45bb48e2015-06-13 03:28:10 +00004669 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
4670}
4671
Matt Arsenaultf15da6c2017-02-03 20:49:51 +00004672void AMDGPUAsmParser::cvtDSImpl(MCInst &Inst, const OperandVector &Operands,
4673 bool IsGdsHardcoded) {
4674 OptionalImmIndexMap OptionalIdx;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004675
4676 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
4677 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
4678
4679 // Add the register arguments
4680 if (Op.isReg()) {
4681 Op.addRegOperands(Inst, 1);
4682 continue;
4683 }
4684
4685 if (Op.isToken() && Op.getToken() == "gds") {
Artem Tamazov43b61562017-02-03 12:47:30 +00004686 IsGdsHardcoded = true;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004687 continue;
4688 }
4689
4690 // Handle optional arguments
4691 OptionalIdx[Op.getImmTy()] = i;
4692 }
4693
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00004694 AMDGPUOperand::ImmTy OffsetType =
Stanislav Mekhanoshina224f682019-05-01 16:11:11 +00004695 (Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_gfx10 ||
4696 Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_gfx6_gfx7 ||
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00004697 Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_vi) ? AMDGPUOperand::ImmTySwizzle :
4698 AMDGPUOperand::ImmTyOffset;
4699
4700 addOptionalImmOperand(Inst, Operands, OptionalIdx, OffsetType);
4701
Artem Tamazov43b61562017-02-03 12:47:30 +00004702 if (!IsGdsHardcoded) {
Nikolay Haustov2e4c7292016-02-25 10:58:54 +00004703 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
Tom Stellard45bb48e2015-06-13 03:28:10 +00004704 }
4705 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
4706}
4707
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00004708void AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) {
4709 OptionalImmIndexMap OptionalIdx;
4710
Dmitry Preobrazhensky9321e8f2017-05-19 13:36:09 +00004711 unsigned OperandIdx[4];
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00004712 unsigned EnMask = 0;
4713 int SrcIdx = 0;
4714
4715 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
4716 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
4717
4718 // Add the register arguments
4719 if (Op.isReg()) {
Dmitry Preobrazhensky9321e8f2017-05-19 13:36:09 +00004720 assert(SrcIdx < 4);
4721 OperandIdx[SrcIdx] = Inst.size();
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00004722 Op.addRegOperands(Inst, 1);
4723 ++SrcIdx;
4724 continue;
4725 }
4726
4727 if (Op.isOff()) {
Dmitry Preobrazhensky9321e8f2017-05-19 13:36:09 +00004728 assert(SrcIdx < 4);
4729 OperandIdx[SrcIdx] = Inst.size();
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00004730 Inst.addOperand(MCOperand::createReg(AMDGPU::NoRegister));
Dmitry Preobrazhensky9321e8f2017-05-19 13:36:09 +00004731 ++SrcIdx;
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00004732 continue;
4733 }
4734
4735 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyExpTgt) {
4736 Op.addImmOperands(Inst, 1);
4737 continue;
4738 }
4739
4740 if (Op.isToken() && Op.getToken() == "done")
4741 continue;
4742
4743 // Handle optional arguments
4744 OptionalIdx[Op.getImmTy()] = i;
4745 }
4746
Dmitry Preobrazhensky9321e8f2017-05-19 13:36:09 +00004747 assert(SrcIdx == 4);
4748
4749 bool Compr = false;
4750 if (OptionalIdx.find(AMDGPUOperand::ImmTyExpCompr) != OptionalIdx.end()) {
4751 Compr = true;
4752 Inst.getOperand(OperandIdx[1]) = Inst.getOperand(OperandIdx[2]);
4753 Inst.getOperand(OperandIdx[2]).setReg(AMDGPU::NoRegister);
4754 Inst.getOperand(OperandIdx[3]).setReg(AMDGPU::NoRegister);
4755 }
4756
4757 for (auto i = 0; i < SrcIdx; ++i) {
4758 if (Inst.getOperand(OperandIdx[i]).getReg() != AMDGPU::NoRegister) {
4759 EnMask |= Compr? (0x3 << i * 2) : (0x1 << i);
4760 }
4761 }
4762
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00004763 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpVM);
4764 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpCompr);
4765
4766 Inst.addOperand(MCOperand::createImm(EnMask));
4767}
Tom Stellard45bb48e2015-06-13 03:28:10 +00004768
4769//===----------------------------------------------------------------------===//
4770// s_waitcnt
4771//===----------------------------------------------------------------------===//
4772
Dmitry Preobrazhensky43d297e2017-04-26 17:55:50 +00004773static bool
4774encodeCnt(
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00004775 const AMDGPU::IsaVersion ISA,
Dmitry Preobrazhensky43d297e2017-04-26 17:55:50 +00004776 int64_t &IntVal,
4777 int64_t CntVal,
4778 bool Saturate,
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00004779 unsigned (*encode)(const IsaVersion &Version, unsigned, unsigned),
4780 unsigned (*decode)(const IsaVersion &Version, unsigned))
Dmitry Preobrazhensky43d297e2017-04-26 17:55:50 +00004781{
4782 bool Failed = false;
4783
4784 IntVal = encode(ISA, IntVal, CntVal);
4785 if (CntVal != decode(ISA, IntVal)) {
4786 if (Saturate) {
4787 IntVal = encode(ISA, IntVal, -1);
4788 } else {
4789 Failed = true;
4790 }
4791 }
4792 return Failed;
4793}
4794
Tom Stellard45bb48e2015-06-13 03:28:10 +00004795bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
Dmitry Preobrazhenskyb79af792019-05-27 14:08:43 +00004796
4797 SMLoc CntLoc = getLoc();
4798 StringRef CntName = getTokenStr();
4799
4800 if (!skipToken(AsmToken::Identifier, "expected a counter name") ||
4801 !skipToken(AsmToken::LParen, "expected a left parenthesis"))
4802 return false;
4803
Tom Stellard45bb48e2015-06-13 03:28:10 +00004804 int64_t CntVal;
Dmitry Preobrazhenskyb79af792019-05-27 14:08:43 +00004805 SMLoc ValLoc = getLoc();
4806 if (!parseExpr(CntVal))
4807 return false;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004808
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00004809 AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU());
Tom Stellard45bb48e2015-06-13 03:28:10 +00004810
Dmitry Preobrazhensky43d297e2017-04-26 17:55:50 +00004811 bool Failed = true;
4812 bool Sat = CntName.endswith("_sat");
4813
4814 if (CntName == "vmcnt" || CntName == "vmcnt_sat") {
4815 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeVmcnt, decodeVmcnt);
4816 } else if (CntName == "expcnt" || CntName == "expcnt_sat") {
4817 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeExpcnt, decodeExpcnt);
4818 } else if (CntName == "lgkmcnt" || CntName == "lgkmcnt_sat") {
4819 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeLgkmcnt, decodeLgkmcnt);
Dmitry Preobrazhenskyb79af792019-05-27 14:08:43 +00004820 } else {
4821 Error(CntLoc, "invalid counter name " + CntName);
4822 return false;
Dmitry Preobrazhensky43d297e2017-04-26 17:55:50 +00004823 }
4824
Dmitry Preobrazhensky5a2f8812017-06-07 16:08:02 +00004825 if (Failed) {
4826 Error(ValLoc, "too large value for " + CntName);
Dmitry Preobrazhenskyb79af792019-05-27 14:08:43 +00004827 return false;
Dmitry Preobrazhensky5a2f8812017-06-07 16:08:02 +00004828 }
4829
Dmitry Preobrazhenskyb79af792019-05-27 14:08:43 +00004830 if (!skipToken(AsmToken::RParen, "expected a closing parenthesis"))
4831 return false;
Dmitry Preobrazhensky5a2f8812017-06-07 16:08:02 +00004832
Dmitry Preobrazhenskyb79af792019-05-27 14:08:43 +00004833 if (trySkipToken(AsmToken::Amp) || trySkipToken(AsmToken::Comma)) {
4834 if (isToken(AsmToken::EndOfStatement)) {
4835 Error(getLoc(), "expected a counter name");
4836 return false;
Dmitry Preobrazhensky43d297e2017-04-26 17:55:50 +00004837 }
4838 }
4839
Dmitry Preobrazhenskyb79af792019-05-27 14:08:43 +00004840 return true;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004841}
4842
Alex Bradbury58eba092016-11-01 16:32:05 +00004843OperandMatchResultTy
Tom Stellard45bb48e2015-06-13 03:28:10 +00004844AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) {
Konstantin Zhuravlyov71e43ee2018-09-12 18:50:47 +00004845 AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU());
Konstantin Zhuravlyov9f89ede2017-02-08 14:05:23 +00004846 int64_t Waitcnt = getWaitcntBitMask(ISA);
Dmitry Preobrazhenskyb79af792019-05-27 14:08:43 +00004847 SMLoc S = getLoc();
Tom Stellard45bb48e2015-06-13 03:28:10 +00004848
Dmitry Preobrazhenskyb79af792019-05-27 14:08:43 +00004849 // If parse failed, do not return error code
4850 // to avoid excessive error messages.
4851 if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) {
4852 while (parseCnt(Waitcnt) && !isToken(AsmToken::EndOfStatement));
4853 } else {
4854 parseExpr(Waitcnt);
Tom Stellard45bb48e2015-06-13 03:28:10 +00004855 }
Dmitry Preobrazhenskyb79af792019-05-27 14:08:43 +00004856
Konstantin Zhuravlyovcdd45472016-10-11 18:58:22 +00004857 Operands.push_back(AMDGPUOperand::CreateImm(this, Waitcnt, S));
Tom Stellard45bb48e2015-06-13 03:28:10 +00004858 return MatchOperand_Success;
4859}
4860
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004861bool
4862AMDGPUOperand::isSWaitCnt() const {
4863 return isImm();
4864}
4865
4866//===----------------------------------------------------------------------===//
4867// hwreg
4868//===----------------------------------------------------------------------===//
4869
4870bool
4871AMDGPUAsmParser::parseHwregBody(OperandInfoTy &HwReg,
4872 int64_t &Offset,
4873 int64_t &Width) {
Artem Tamazov6edc1352016-05-26 17:00:33 +00004874 using namespace llvm::AMDGPU::Hwreg;
4875
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004876 // The register may be specified by name or using a numeric code
4877 if (isToken(AsmToken::Identifier) &&
4878 (HwReg.Id = getHwregId(getTokenStr())) >= 0) {
Artem Tamazov6edc1352016-05-26 17:00:33 +00004879 HwReg.IsSymbolic = true;
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004880 lex(); // skip message name
4881 } else if (!parseExpr(HwReg.Id)) {
Artem Tamazovd6468662016-04-25 14:13:51 +00004882 return false;
4883 }
4884
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004885 if (trySkipToken(AsmToken::RParen))
Artem Tamazovd6468662016-04-25 14:13:51 +00004886 return true;
4887
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004888 // parse optional params
4889 return
4890 skipToken(AsmToken::Comma, "expected a comma or a closing parenthesis") &&
4891 parseExpr(Offset) &&
4892 skipToken(AsmToken::Comma, "expected a comma") &&
4893 parseExpr(Width) &&
4894 skipToken(AsmToken::RParen, "expected a closing parenthesis");
Artem Tamazovd6468662016-04-25 14:13:51 +00004895}
4896
Dmitry Preobrazhensky2eff0312019-07-08 14:27:37 +00004897bool
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004898AMDGPUAsmParser::validateHwreg(const OperandInfoTy &HwReg,
4899 const int64_t Offset,
4900 const int64_t Width,
4901 const SMLoc Loc) {
4902
Artem Tamazov6edc1352016-05-26 17:00:33 +00004903 using namespace llvm::AMDGPU::Hwreg;
4904
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004905 if (HwReg.IsSymbolic && !isValidHwreg(HwReg.Id, getSTI())) {
4906 Error(Loc, "specified hardware register is not supported on this GPU");
Dmitry Preobrazhensky2eff0312019-07-08 14:27:37 +00004907 return false;
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004908 } else if (!isValidHwreg(HwReg.Id)) {
4909 Error(Loc, "invalid code of hardware register: only 6-bit values are legal");
Dmitry Preobrazhensky2eff0312019-07-08 14:27:37 +00004910 return false;
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004911 } else if (!isValidHwregOffset(Offset)) {
4912 Error(Loc, "invalid bit offset: only 5-bit values are legal");
Dmitry Preobrazhensky2eff0312019-07-08 14:27:37 +00004913 return false;
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004914 } else if (!isValidHwregWidth(Width)) {
4915 Error(Loc, "invalid bitfield width: only values from 1 to 32 are legal");
Dmitry Preobrazhensky2eff0312019-07-08 14:27:37 +00004916 return false;
Artem Tamazovd6468662016-04-25 14:13:51 +00004917 }
Dmitry Preobrazhensky2eff0312019-07-08 14:27:37 +00004918 return true;
Artem Tamazovd6468662016-04-25 14:13:51 +00004919}
4920
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004921OperandMatchResultTy
4922AMDGPUAsmParser::parseHwreg(OperandVector &Operands) {
4923 using namespace llvm::AMDGPU::Hwreg;
4924
4925 int64_t ImmVal = 0;
4926 SMLoc Loc = getLoc();
4927
4928 // If parse failed, do not return error code
4929 // to avoid excessive error messages.
4930 if (trySkipId("hwreg", AsmToken::LParen)) {
4931 OperandInfoTy HwReg(ID_UNKNOWN_);
4932 int64_t Offset = OFFSET_DEFAULT_;
4933 int64_t Width = WIDTH_DEFAULT_;
Dmitry Preobrazhensky2eff0312019-07-08 14:27:37 +00004934 if (parseHwregBody(HwReg, Offset, Width) &&
4935 validateHwreg(HwReg, Offset, Width, Loc)) {
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004936 ImmVal = encodeHwreg(HwReg.Id, Offset, Width);
4937 }
4938 } else if (parseExpr(ImmVal)) {
4939 if (ImmVal < 0 || !isUInt<16>(ImmVal))
4940 Error(Loc, "invalid immediate: only 16-bit values are legal");
4941 }
4942
4943 Operands.push_back(AMDGPUOperand::CreateImm(this, ImmVal, Loc, AMDGPUOperand::ImmTyHwreg));
4944 return MatchOperand_Success;
Tom Stellard45bb48e2015-06-13 03:28:10 +00004945}
4946
Artem Tamazovd6468662016-04-25 14:13:51 +00004947bool AMDGPUOperand::isHwreg() const {
4948 return isImmTy(ImmTyHwreg);
4949}
4950
Dmitry Preobrazhensky1fca3b12019-06-13 12:46:37 +00004951//===----------------------------------------------------------------------===//
4952// sendmsg
4953//===----------------------------------------------------------------------===//
4954
Dmitry Preobrazhensky1d572ce2019-06-28 14:14:02 +00004955bool
4956AMDGPUAsmParser::parseSendMsgBody(OperandInfoTy &Msg,
4957 OperandInfoTy &Op,
4958 OperandInfoTy &Stream) {
Artem Tamazovebe71ce2016-05-06 17:48:48 +00004959 using namespace llvm::AMDGPU::SendMsg;
4960
Dmitry Preobrazhensky1d572ce2019-06-28 14:14:02 +00004961 if (isToken(AsmToken::Identifier) && (Msg.Id = getMsgId(getTokenStr())) >= 0) {
Artem Tamazovebe71ce2016-05-06 17:48:48 +00004962 Msg.IsSymbolic = true;
Dmitry Preobrazhensky1d572ce2019-06-28 14:14:02 +00004963 lex(); // skip message name
4964 } else if (!parseExpr(Msg.Id)) {
Artem Tamazovebe71ce2016-05-06 17:48:48 +00004965 return false;
4966 }
4967
Dmitry Preobrazhensky1d572ce2019-06-28 14:14:02 +00004968 if (trySkipToken(AsmToken::Comma)) {
4969 Op.IsDefined = true;
4970 if (isToken(AsmToken::Identifier) &&
4971 (Op.Id = getMsgOpId(Msg.Id, getTokenStr())) >= 0) {
4972 lex(); // skip operation name
4973 } else if (!parseExpr(Op.Id)) {
Artem Tamazovebe71ce2016-05-06 17:48:48 +00004974 return false;
4975 }
4976
Dmitry Preobrazhensky1d572ce2019-06-28 14:14:02 +00004977 if (trySkipToken(AsmToken::Comma)) {
4978 Stream.IsDefined = true;
4979 if (!parseExpr(Stream.Id))
4980 return false;
4981 }
Artem Tamazovebe71ce2016-05-06 17:48:48 +00004982 }
4983
Dmitry Preobrazhensky1d572ce2019-06-28 14:14:02 +00004984 return skipToken(AsmToken::RParen, "expected a closing parenthesis");
Artem Tamazovebe71ce2016-05-06 17:48:48 +00004985}
4986
Dmitry Preobrazhenskyd12966c2019-06-28 15:22:47 +00004987bool
Dmitry Preobrazhensky1d572ce2019-06-28 14:14:02 +00004988AMDGPUAsmParser::validateSendMsg(const OperandInfoTy &Msg,
4989 const OperandInfoTy &Op,
4990 const OperandInfoTy &Stream,
4991 const SMLoc S) {
4992 using namespace llvm::AMDGPU::SendMsg;
4993
4994 // Validation strictness depends on whether message is specified
4995 // in a symbolc or in a numeric form. In the latter case
4996 // only encoding possibility is checked.
4997 bool Strict = Msg.IsSymbolic;
4998
4999 if (!isValidMsgId(Msg.Id, getSTI(), Strict)) {
5000 Error(S, "invalid message id");
Dmitry Preobrazhenskyd12966c2019-06-28 15:22:47 +00005001 return false;
Dmitry Preobrazhensky1d572ce2019-06-28 14:14:02 +00005002 } else if (Strict && (msgRequiresOp(Msg.Id) != Op.IsDefined)) {
5003 Error(S, Op.IsDefined ?
5004 "message does not support operations" :
5005 "missing message operation");
Dmitry Preobrazhenskyd12966c2019-06-28 15:22:47 +00005006 return false;
Dmitry Preobrazhensky1d572ce2019-06-28 14:14:02 +00005007 } else if (!isValidMsgOp(Msg.Id, Op.Id, Strict)) {
5008 Error(S, "invalid operation id");
Dmitry Preobrazhenskyd12966c2019-06-28 15:22:47 +00005009 return false;
Dmitry Preobrazhensky1d572ce2019-06-28 14:14:02 +00005010 } else if (Strict && !msgSupportsStream(Msg.Id, Op.Id) && Stream.IsDefined) {
5011 Error(S, "message operation does not support streams");
Dmitry Preobrazhenskyd12966c2019-06-28 15:22:47 +00005012 return false;
Dmitry Preobrazhensky1d572ce2019-06-28 14:14:02 +00005013 } else if (!isValidMsgStream(Msg.Id, Op.Id, Stream.Id, Strict)) {
5014 Error(S, "invalid message stream id");
Dmitry Preobrazhenskyd12966c2019-06-28 15:22:47 +00005015 return false;
Dmitry Preobrazhensky1d572ce2019-06-28 14:14:02 +00005016 }
Dmitry Preobrazhenskyd12966c2019-06-28 15:22:47 +00005017 return true;
Dmitry Preobrazhensky1d572ce2019-06-28 14:14:02 +00005018}
5019
5020OperandMatchResultTy
5021AMDGPUAsmParser::parseSendMsgOp(OperandVector &Operands) {
5022 using namespace llvm::AMDGPU::SendMsg;
5023
5024 int64_t ImmVal = 0;
5025 SMLoc Loc = getLoc();
5026
5027 // If parse failed, do not return error code
5028 // to avoid excessive error messages.
5029 if (trySkipId("sendmsg", AsmToken::LParen)) {
5030 OperandInfoTy Msg(ID_UNKNOWN_);
5031 OperandInfoTy Op(OP_NONE_);
5032 OperandInfoTy Stream(STREAM_ID_NONE_);
Dmitry Preobrazhenskyd12966c2019-06-28 15:22:47 +00005033 if (parseSendMsgBody(Msg, Op, Stream) &&
5034 validateSendMsg(Msg, Op, Stream, Loc)) {
Dmitry Preobrazhensky1d572ce2019-06-28 14:14:02 +00005035 ImmVal = encodeMsg(Msg.Id, Op.Id, Stream.Id);
5036 }
5037 } else if (parseExpr(ImmVal)) {
5038 if (ImmVal < 0 || !isUInt<16>(ImmVal))
5039 Error(Loc, "invalid immediate: only 16-bit values are legal");
5040 }
5041
5042 Operands.push_back(AMDGPUOperand::CreateImm(this, ImmVal, Loc, AMDGPUOperand::ImmTySendMsg));
5043 return MatchOperand_Success;
5044}
5045
5046bool AMDGPUOperand::isSendMsg() const {
5047 return isImmTy(ImmTySendMsg);
5048}
5049
5050//===----------------------------------------------------------------------===//
5051// v_interp
5052//===----------------------------------------------------------------------===//
5053
Matt Arsenault0e8a2992016-12-15 20:40:20 +00005054OperandMatchResultTy AMDGPUAsmParser::parseInterpSlot(OperandVector &Operands) {
5055 if (getLexer().getKind() != AsmToken::Identifier)
5056 return MatchOperand_NoMatch;
5057
5058 StringRef Str = Parser.getTok().getString();
5059 int Slot = StringSwitch<int>(Str)
5060 .Case("p10", 0)
5061 .Case("p20", 1)
5062 .Case("p0", 2)
5063 .Default(-1);
5064
5065 SMLoc S = Parser.getTok().getLoc();
5066 if (Slot == -1)
5067 return MatchOperand_ParseFail;
5068
5069 Parser.Lex();
5070 Operands.push_back(AMDGPUOperand::CreateImm(this, Slot, S,
5071 AMDGPUOperand::ImmTyInterpSlot));
5072 return MatchOperand_Success;
5073}
5074
5075OperandMatchResultTy AMDGPUAsmParser::parseInterpAttr(OperandVector &Operands) {
5076 if (getLexer().getKind() != AsmToken::Identifier)
5077 return MatchOperand_NoMatch;
5078
5079 StringRef Str = Parser.getTok().getString();
5080 if (!Str.startswith("attr"))
5081 return MatchOperand_NoMatch;
5082
5083 StringRef Chan = Str.take_back(2);
5084 int AttrChan = StringSwitch<int>(Chan)
5085 .Case(".x", 0)
5086 .Case(".y", 1)
5087 .Case(".z", 2)
5088 .Case(".w", 3)
5089 .Default(-1);
5090 if (AttrChan == -1)
5091 return MatchOperand_ParseFail;
5092
5093 Str = Str.drop_back(2).drop_front(4);
5094
5095 uint8_t Attr;
5096 if (Str.getAsInteger(10, Attr))
5097 return MatchOperand_ParseFail;
5098
5099 SMLoc S = Parser.getTok().getLoc();
5100 Parser.Lex();
5101 if (Attr > 63) {
5102 Error(S, "out of bounds attr");
5103 return MatchOperand_Success;
5104 }
5105
5106 SMLoc SChan = SMLoc::getFromPointer(Chan.data());
5107
5108 Operands.push_back(AMDGPUOperand::CreateImm(this, Attr, S,
5109 AMDGPUOperand::ImmTyInterpAttr));
5110 Operands.push_back(AMDGPUOperand::CreateImm(this, AttrChan, SChan,
5111 AMDGPUOperand::ImmTyAttrChan));
5112 return MatchOperand_Success;
5113}
5114
Dmitry Preobrazhensky1d572ce2019-06-28 14:14:02 +00005115//===----------------------------------------------------------------------===//
5116// exp
5117//===----------------------------------------------------------------------===//
5118
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00005119void AMDGPUAsmParser::errorExpTgt() {
5120 Error(Parser.getTok().getLoc(), "invalid exp target");
5121}
5122
5123OperandMatchResultTy AMDGPUAsmParser::parseExpTgtImpl(StringRef Str,
5124 uint8_t &Val) {
5125 if (Str == "null") {
5126 Val = 9;
5127 return MatchOperand_Success;
5128 }
5129
5130 if (Str.startswith("mrt")) {
5131 Str = Str.drop_front(3);
5132 if (Str == "z") { // == mrtz
5133 Val = 8;
5134 return MatchOperand_Success;
5135 }
5136
5137 if (Str.getAsInteger(10, Val))
5138 return MatchOperand_ParseFail;
5139
5140 if (Val > 7)
5141 errorExpTgt();
5142
5143 return MatchOperand_Success;
5144 }
5145
5146 if (Str.startswith("pos")) {
5147 Str = Str.drop_front(3);
5148 if (Str.getAsInteger(10, Val))
5149 return MatchOperand_ParseFail;
5150
Stanislav Mekhanoshin1dbf7212019-05-08 21:23:37 +00005151 if (Val > 4 || (Val == 4 && !isGFX10()))
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00005152 errorExpTgt();
5153
5154 Val += 12;
5155 return MatchOperand_Success;
5156 }
5157
Stanislav Mekhanoshin1dbf7212019-05-08 21:23:37 +00005158 if (isGFX10() && Str == "prim") {
5159 Val = 20;
5160 return MatchOperand_Success;
5161 }
5162
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00005163 if (Str.startswith("param")) {
5164 Str = Str.drop_front(5);
5165 if (Str.getAsInteger(10, Val))
5166 return MatchOperand_ParseFail;
5167
5168 if (Val >= 32)
5169 errorExpTgt();
5170
5171 Val += 32;
5172 return MatchOperand_Success;
5173 }
5174
5175 if (Str.startswith("invalid_target_")) {
5176 Str = Str.drop_front(15);
5177 if (Str.getAsInteger(10, Val))
5178 return MatchOperand_ParseFail;
5179
5180 errorExpTgt();
5181 return MatchOperand_Success;
5182 }
5183
5184 return MatchOperand_NoMatch;
5185}
5186
5187OperandMatchResultTy AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) {
5188 uint8_t Val;
5189 StringRef Str = Parser.getTok().getString();
5190
5191 auto Res = parseExpTgtImpl(Str, Val);
5192 if (Res != MatchOperand_Success)
5193 return Res;
5194
5195 SMLoc S = Parser.getTok().getLoc();
5196 Parser.Lex();
5197
5198 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S,
5199 AMDGPUOperand::ImmTyExpTgt));
5200 return MatchOperand_Success;
5201}
5202
Tom Stellard45bb48e2015-06-13 03:28:10 +00005203//===----------------------------------------------------------------------===//
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00005204// parser helpers
5205//===----------------------------------------------------------------------===//
5206
5207bool
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00005208AMDGPUAsmParser::isId(const AsmToken &Token, const StringRef Id) const {
5209 return Token.is(AsmToken::Identifier) && Token.getString() == Id;
5210}
5211
5212bool
5213AMDGPUAsmParser::isId(const StringRef Id) const {
5214 return isId(getToken(), Id);
5215}
5216
5217bool
5218AMDGPUAsmParser::isToken(const AsmToken::TokenKind Kind) const {
5219 return getTokenKind() == Kind;
5220}
5221
5222bool
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00005223AMDGPUAsmParser::trySkipId(const StringRef Id) {
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00005224 if (isId(Id)) {
5225 lex();
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00005226 return true;
5227 }
5228 return false;
5229}
5230
5231bool
Dmitry Preobrazhensky198611b2019-05-17 16:04:17 +00005232AMDGPUAsmParser::trySkipId(const StringRef Id, const AsmToken::TokenKind Kind) {
5233 if (isId(Id) && peekToken().is(Kind)) {
5234 lex();
5235 lex();
5236 return true;
5237 }
5238 return false;
5239}
5240
5241bool
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00005242AMDGPUAsmParser::trySkipToken(const AsmToken::TokenKind Kind) {
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00005243 if (isToken(Kind)) {
5244 lex();
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00005245 return true;
5246 }
5247 return false;
5248}
5249
5250bool
5251AMDGPUAsmParser::skipToken(const AsmToken::TokenKind Kind,
5252 const StringRef ErrMsg) {
5253 if (!trySkipToken(Kind)) {
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00005254 Error(getLoc(), ErrMsg);
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00005255 return false;
5256 }
5257 return true;
5258}
5259
5260bool
5261AMDGPUAsmParser::parseExpr(int64_t &Imm) {
5262 return !getParser().parseAbsoluteExpression(Imm);
5263}
5264
5265bool
Dmitry Preobrazhensky4ccb7f82019-07-19 13:12:47 +00005266AMDGPUAsmParser::parseExpr(OperandVector &Operands) {
5267 SMLoc S = getLoc();
5268
5269 const MCExpr *Expr;
5270 if (Parser.parseExpression(Expr))
5271 return false;
5272
5273 int64_t IntVal;
5274 if (Expr->evaluateAsAbsolute(IntVal)) {
5275 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S));
5276 } else {
5277 Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S));
5278 }
5279 return true;
5280}
5281
5282bool
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00005283AMDGPUAsmParser::parseString(StringRef &Val, const StringRef ErrMsg) {
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00005284 if (isToken(AsmToken::String)) {
5285 Val = getToken().getStringContents();
5286 lex();
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00005287 return true;
5288 } else {
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00005289 Error(getLoc(), ErrMsg);
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00005290 return false;
5291 }
5292}
5293
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00005294AsmToken
5295AMDGPUAsmParser::getToken() const {
5296 return Parser.getTok();
5297}
5298
5299AsmToken
5300AMDGPUAsmParser::peekToken() {
5301 return getLexer().peekTok();
5302}
5303
Dmitry Preobrazhenskye2707f52019-04-22 14:35:47 +00005304void
5305AMDGPUAsmParser::peekTokens(MutableArrayRef<AsmToken> Tokens) {
5306 auto TokCount = getLexer().peekTokens(Tokens);
5307
5308 for (auto Idx = TokCount; Idx < Tokens.size(); ++Idx)
5309 Tokens[Idx] = AsmToken(AsmToken::Error, "");
5310}
5311
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00005312AsmToken::TokenKind
5313AMDGPUAsmParser::getTokenKind() const {
5314 return getLexer().getKind();
5315}
5316
5317SMLoc
5318AMDGPUAsmParser::getLoc() const {
5319 return getToken().getLoc();
5320}
5321
Dmitry Preobrazhensky394d0a12019-04-17 16:56:34 +00005322StringRef
5323AMDGPUAsmParser::getTokenStr() const {
5324 return getToken().getString();
5325}
5326
Dmitry Preobrazhensky20d52e32019-04-17 14:44:01 +00005327void
5328AMDGPUAsmParser::lex() {
5329 Parser.Lex();
5330}
5331
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00005332//===----------------------------------------------------------------------===//
5333// swizzle
5334//===----------------------------------------------------------------------===//
5335
5336LLVM_READNONE
5337static unsigned
5338encodeBitmaskPerm(const unsigned AndMask,
5339 const unsigned OrMask,
5340 const unsigned XorMask) {
5341 using namespace llvm::AMDGPU::Swizzle;
5342
5343 return BITMASK_PERM_ENC |
5344 (AndMask << BITMASK_AND_SHIFT) |
5345 (OrMask << BITMASK_OR_SHIFT) |
5346 (XorMask << BITMASK_XOR_SHIFT);
5347}
5348
5349bool
5350AMDGPUAsmParser::parseSwizzleOperands(const unsigned OpNum, int64_t* Op,
5351 const unsigned MinVal,
5352 const unsigned MaxVal,
5353 const StringRef ErrMsg) {
5354 for (unsigned i = 0; i < OpNum; ++i) {
5355 if (!skipToken(AsmToken::Comma, "expected a comma")){
5356 return false;
5357 }
5358 SMLoc ExprLoc = Parser.getTok().getLoc();
5359 if (!parseExpr(Op[i])) {
5360 return false;
5361 }
5362 if (Op[i] < MinVal || Op[i] > MaxVal) {
5363 Error(ExprLoc, ErrMsg);
5364 return false;
5365 }
5366 }
5367
5368 return true;
5369}
5370
5371bool
5372AMDGPUAsmParser::parseSwizzleQuadPerm(int64_t &Imm) {
5373 using namespace llvm::AMDGPU::Swizzle;
5374
5375 int64_t Lane[LANE_NUM];
5376 if (parseSwizzleOperands(LANE_NUM, Lane, 0, LANE_MAX,
5377 "expected a 2-bit lane id")) {
5378 Imm = QUAD_PERM_ENC;
Stanislav Mekhanoshin266f1572019-03-11 16:49:32 +00005379 for (unsigned I = 0; I < LANE_NUM; ++I) {
5380 Imm |= Lane[I] << (LANE_SHIFT * I);
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00005381 }
5382 return true;
5383 }
5384 return false;
5385}
5386
5387bool
5388AMDGPUAsmParser::parseSwizzleBroadcast(int64_t &Imm) {
5389 using namespace llvm::AMDGPU::Swizzle;
5390
5391 SMLoc S = Parser.getTok().getLoc();
5392 int64_t GroupSize;
5393 int64_t LaneIdx;
5394
5395 if (!parseSwizzleOperands(1, &GroupSize,
5396 2, 32,
5397 "group size must be in the interval [2,32]")) {
5398 return false;
5399 }
5400 if (!isPowerOf2_64(GroupSize)) {
5401 Error(S, "group size must be a power of two");
5402 return false;
5403 }
5404 if (parseSwizzleOperands(1, &LaneIdx,
5405 0, GroupSize - 1,
5406 "lane id must be in the interval [0,group size - 1]")) {
5407 Imm = encodeBitmaskPerm(BITMASK_MAX - GroupSize + 1, LaneIdx, 0);
5408 return true;
5409 }
5410 return false;
5411}
5412
5413bool
5414AMDGPUAsmParser::parseSwizzleReverse(int64_t &Imm) {
5415 using namespace llvm::AMDGPU::Swizzle;
5416
5417 SMLoc S = Parser.getTok().getLoc();
5418 int64_t GroupSize;
5419
5420 if (!parseSwizzleOperands(1, &GroupSize,
5421 2, 32, "group size must be in the interval [2,32]")) {
5422 return false;
5423 }
5424 if (!isPowerOf2_64(GroupSize)) {
5425 Error(S, "group size must be a power of two");
5426 return false;
5427 }
5428
5429 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize - 1);
5430 return true;
5431}
5432
5433bool
5434AMDGPUAsmParser::parseSwizzleSwap(int64_t &Imm) {
5435 using namespace llvm::AMDGPU::Swizzle;
5436
5437 SMLoc S = Parser.getTok().getLoc();
5438 int64_t GroupSize;
5439
5440 if (!parseSwizzleOperands(1, &GroupSize,
5441 1, 16, "group size must be in the interval [1,16]")) {
5442 return false;
5443 }
5444 if (!isPowerOf2_64(GroupSize)) {
5445 Error(S, "group size must be a power of two");
5446 return false;
5447 }
5448
5449 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize);
5450 return true;
5451}
5452
5453bool
5454AMDGPUAsmParser::parseSwizzleBitmaskPerm(int64_t &Imm) {
5455 using namespace llvm::AMDGPU::Swizzle;
5456
5457 if (!skipToken(AsmToken::Comma, "expected a comma")) {
5458 return false;
5459 }
5460
5461 StringRef Ctl;
5462 SMLoc StrLoc = Parser.getTok().getLoc();
5463 if (!parseString(Ctl)) {
5464 return false;
5465 }
5466 if (Ctl.size() != BITMASK_WIDTH) {
5467 Error(StrLoc, "expected a 5-character mask");
5468 return false;
5469 }
5470
5471 unsigned AndMask = 0;
5472 unsigned OrMask = 0;
5473 unsigned XorMask = 0;
5474
5475 for (size_t i = 0; i < Ctl.size(); ++i) {
5476 unsigned Mask = 1 << (BITMASK_WIDTH - 1 - i);
5477 switch(Ctl[i]) {
5478 default:
5479 Error(StrLoc, "invalid mask");
5480 return false;
5481 case '0':
5482 break;
5483 case '1':
5484 OrMask |= Mask;
5485 break;
5486 case 'p':
5487 AndMask |= Mask;
5488 break;
5489 case 'i':
5490 AndMask |= Mask;
5491 XorMask |= Mask;
5492 break;
5493 }
5494 }
5495
5496 Imm = encodeBitmaskPerm(AndMask, OrMask, XorMask);
5497 return true;
5498}
5499
5500bool
5501AMDGPUAsmParser::parseSwizzleOffset(int64_t &Imm) {
5502
5503 SMLoc OffsetLoc = Parser.getTok().getLoc();
5504
5505 if (!parseExpr(Imm)) {
5506 return false;
5507 }
5508 if (!isUInt<16>(Imm)) {
5509 Error(OffsetLoc, "expected a 16-bit offset");
5510 return false;
5511 }
5512 return true;
5513}
5514
5515bool
5516AMDGPUAsmParser::parseSwizzleMacro(int64_t &Imm) {
5517 using namespace llvm::AMDGPU::Swizzle;
5518
5519 if (skipToken(AsmToken::LParen, "expected a left parentheses")) {
5520
5521 SMLoc ModeLoc = Parser.getTok().getLoc();
5522 bool Ok = false;
5523
5524 if (trySkipId(IdSymbolic[ID_QUAD_PERM])) {
5525 Ok = parseSwizzleQuadPerm(Imm);
5526 } else if (trySkipId(IdSymbolic[ID_BITMASK_PERM])) {
5527 Ok = parseSwizzleBitmaskPerm(Imm);
5528 } else if (trySkipId(IdSymbolic[ID_BROADCAST])) {
5529 Ok = parseSwizzleBroadcast(Imm);
5530 } else if (trySkipId(IdSymbolic[ID_SWAP])) {
5531 Ok = parseSwizzleSwap(Imm);
5532 } else if (trySkipId(IdSymbolic[ID_REVERSE])) {
5533 Ok = parseSwizzleReverse(Imm);
5534 } else {
5535 Error(ModeLoc, "expected a swizzle mode");
5536 }
5537
5538 return Ok && skipToken(AsmToken::RParen, "expected a closing parentheses");
5539 }
5540
5541 return false;
5542}
5543
5544OperandMatchResultTy
5545AMDGPUAsmParser::parseSwizzleOp(OperandVector &Operands) {
5546 SMLoc S = Parser.getTok().getLoc();
5547 int64_t Imm = 0;
5548
5549 if (trySkipId("offset")) {
5550
5551 bool Ok = false;
5552 if (skipToken(AsmToken::Colon, "expected a colon")) {
5553 if (trySkipId("swizzle")) {
5554 Ok = parseSwizzleMacro(Imm);
5555 } else {
5556 Ok = parseSwizzleOffset(Imm);
5557 }
5558 }
5559
5560 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTySwizzle));
5561
5562 return Ok? MatchOperand_Success : MatchOperand_ParseFail;
5563 } else {
Dmitry Preobrazhenskyc5b0c172017-12-22 17:13:28 +00005564 // Swizzle "offset" operand is optional.
5565 // If it is omitted, try parsing other optional operands.
Dmitry Preobrazhensky414e0532017-12-29 13:55:11 +00005566 return parseOptionalOpr(Operands);
Dmitry Preobrazhensky793c5922017-05-31 16:26:47 +00005567 }
5568}
5569
5570bool
5571AMDGPUOperand::isSwizzle() const {
5572 return isImmTy(ImmTySwizzle);
5573}
5574
5575//===----------------------------------------------------------------------===//
Dmitry Preobrazhenskyef920352019-02-27 13:12:12 +00005576// VGPR Index Mode
5577//===----------------------------------------------------------------------===//
5578
5579int64_t AMDGPUAsmParser::parseGPRIdxMacro() {
5580
5581 using namespace llvm::AMDGPU::VGPRIndexMode;
5582
5583 if (trySkipToken(AsmToken::RParen)) {
5584 return OFF;
5585 }
5586
5587 int64_t Imm = 0;
5588
5589 while (true) {
5590 unsigned Mode = 0;
5591 SMLoc S = Parser.getTok().getLoc();
5592
5593 for (unsigned ModeId = ID_MIN; ModeId <= ID_MAX; ++ModeId) {
5594 if (trySkipId(IdSymbolic[ModeId])) {
5595 Mode = 1 << ModeId;
5596 break;
5597 }
5598 }
5599
5600 if (Mode == 0) {
5601 Error(S, (Imm == 0)?
5602 "expected a VGPR index mode or a closing parenthesis" :
5603 "expected a VGPR index mode");
5604 break;
5605 }
5606
5607 if (Imm & Mode) {
5608 Error(S, "duplicate VGPR index mode");
5609 break;
5610 }
5611 Imm |= Mode;
5612
5613 if (trySkipToken(AsmToken::RParen))
5614 break;
5615 if (!skipToken(AsmToken::Comma,
5616 "expected a comma or a closing parenthesis"))
5617 break;
5618 }
5619
5620 return Imm;
5621}
5622
5623OperandMatchResultTy
5624AMDGPUAsmParser::parseGPRIdxMode(OperandVector &Operands) {
5625
5626 int64_t Imm = 0;
5627 SMLoc S = Parser.getTok().getLoc();
5628
5629 if (getLexer().getKind() == AsmToken::Identifier &&
5630 Parser.getTok().getString() == "gpr_idx" &&
5631 getLexer().peekTok().is(AsmToken::LParen)) {
5632
5633 Parser.Lex();
5634 Parser.Lex();
5635
5636 // If parse failed, trigger an error but do not return error code
5637 // to avoid excessive error messages.
5638 Imm = parseGPRIdxMacro();
5639
5640 } else {
5641 if (getParser().parseAbsoluteExpression(Imm))
5642 return MatchOperand_NoMatch;
5643 if (Imm < 0 || !isUInt<4>(Imm)) {
5644 Error(S, "invalid immediate: only 4-bit values are legal");
5645 }
5646 }
5647
5648 Operands.push_back(
5649 AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTyGprIdxMode));
5650 return MatchOperand_Success;
5651}
5652
5653bool AMDGPUOperand::isGPRIdxMode() const {
5654 return isImmTy(ImmTyGprIdxMode);
5655}
5656
5657//===----------------------------------------------------------------------===//
Tom Stellard45bb48e2015-06-13 03:28:10 +00005658// sopp branch targets
5659//===----------------------------------------------------------------------===//
5660
Alex Bradbury58eba092016-11-01 16:32:05 +00005661OperandMatchResultTy
Tom Stellard45bb48e2015-06-13 03:28:10 +00005662AMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) {
Tom Stellard45bb48e2015-06-13 03:28:10 +00005663
Dmitry Preobrazhensky4ccb7f82019-07-19 13:12:47 +00005664 // Make sure we are not parsing something
5665 // that looks like a label or an expression but is not.
5666 // This will improve error messages.
5667 if (isRegister() || isModifier())
5668 return MatchOperand_NoMatch;
5669
5670 if (parseExpr(Operands)) {
5671
5672 AMDGPUOperand &Opr = ((AMDGPUOperand &)*Operands[Operands.size() - 1]);
5673 assert(Opr.isImm() || Opr.isExpr());
5674 SMLoc Loc = Opr.getStartLoc();
5675
5676 // Currently we do not support arbitrary expressions as branch targets.
5677 // Only labels and absolute expressions are accepted.
5678 if (Opr.isExpr() && !Opr.isSymbolRefExpr()) {
5679 Error(Loc, "expected an absolute expression or a label");
5680 } else if (Opr.isImm() && !Opr.isS16Imm()) {
5681 Error(Loc, "expected a 16-bit signed jump offset");
Tom Stellard45bb48e2015-06-13 03:28:10 +00005682 }
Tom Stellard45bb48e2015-06-13 03:28:10 +00005683 }
Dmitry Preobrazhensky4ccb7f82019-07-19 13:12:47 +00005684
5685 return MatchOperand_Success; // avoid excessive error messages
Tom Stellard45bb48e2015-06-13 03:28:10 +00005686}
5687
5688//===----------------------------------------------------------------------===//
Stanislav Mekhanoshin8bcc9bb2019-06-13 19:18:29 +00005689// Boolean holding registers
5690//===----------------------------------------------------------------------===//
5691
5692OperandMatchResultTy
5693AMDGPUAsmParser::parseBoolReg(OperandVector &Operands) {
5694 return parseReg(Operands);
5695}
5696
5697//===----------------------------------------------------------------------===//
Tom Stellard45bb48e2015-06-13 03:28:10 +00005698// mubuf
5699//===----------------------------------------------------------------------===//
5700
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00005701AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDLC() const {
5702 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDLC);
5703}
5704
Sam Kolton5f10a132016-05-06 11:31:17 +00005705AMDGPUOperand::Ptr AMDGPUAsmParser::defaultGLC() const {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00005706 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyGLC);
Sam Kolton5f10a132016-05-06 11:31:17 +00005707}
5708
5709AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSLC() const {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00005710 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTySLC);
Sam Kolton5f10a132016-05-06 11:31:17 +00005711}
5712
Artem Tamazov8ce1f712016-05-19 12:22:39 +00005713void AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst,
5714 const OperandVector &Operands,
Dmitry Preobrazhenskyd98c97b2018-03-12 17:29:24 +00005715 bool IsAtomic,
5716 bool IsAtomicReturn,
5717 bool IsLds) {
5718 bool IsLdsOpcode = IsLds;
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +00005719 bool HasLdsModifier = false;
Nikolay Haustov2e4c7292016-02-25 10:58:54 +00005720 OptionalImmIndexMap OptionalIdx;
Artem Tamazov8ce1f712016-05-19 12:22:39 +00005721 assert(IsAtomicReturn ? IsAtomic : true);
Dmitry Preobrazhensky7f335742019-03-29 12:16:04 +00005722 unsigned FirstOperandIdx = 1;
Tom Stellard45bb48e2015-06-13 03:28:10 +00005723
Dmitry Preobrazhensky7f335742019-03-29 12:16:04 +00005724 for (unsigned i = FirstOperandIdx, e = Operands.size(); i != e; ++i) {
Tom Stellard45bb48e2015-06-13 03:28:10 +00005725 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
5726
5727 // Add the register arguments
5728 if (Op.isReg()) {
5729 Op.addRegOperands(Inst, 1);
Dmitry Preobrazhensky7f335742019-03-29 12:16:04 +00005730 // Insert a tied src for atomic return dst.
5731 // This cannot be postponed as subsequent calls to
5732 // addImmOperands rely on correct number of MC operands.
5733 if (IsAtomicReturn && i == FirstOperandIdx)
5734 Op.addRegOperands(Inst, 1);
Tom Stellard45bb48e2015-06-13 03:28:10 +00005735 continue;
5736 }
5737
5738 // Handle the case where soffset is an immediate
5739 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
5740 Op.addImmOperands(Inst, 1);
5741 continue;
5742 }
5743
Stanislav Mekhanoshina224f682019-05-01 16:11:11 +00005744 HasLdsModifier |= Op.isLDS();
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +00005745
Tom Stellard45bb48e2015-06-13 03:28:10 +00005746 // Handle tokens like 'offen' which are sometimes hard-coded into the
5747 // asm string. There are no MCInst operands for these.
5748 if (Op.isToken()) {
5749 continue;
5750 }
5751 assert(Op.isImm());
5752
5753 // Handle optional arguments
5754 OptionalIdx[Op.getImmTy()] = i;
5755 }
5756
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +00005757 // This is a workaround for an llvm quirk which may result in an
5758 // incorrect instruction selection. Lds and non-lds versions of
5759 // MUBUF instructions are identical except that lds versions
5760 // have mandatory 'lds' modifier. However this modifier follows
5761 // optional modifiers and llvm asm matcher regards this 'lds'
5762 // modifier as an optional one. As a result, an lds version
5763 // of opcode may be selected even if it has no 'lds' modifier.
Dmitry Preobrazhenskyd98c97b2018-03-12 17:29:24 +00005764 if (IsLdsOpcode && !HasLdsModifier) {
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +00005765 int NoLdsOpcode = AMDGPU::getMUBUFNoLdsInst(Inst.getOpcode());
5766 if (NoLdsOpcode != -1) { // Got lds version - correct it.
5767 Inst.setOpcode(NoLdsOpcode);
Dmitry Preobrazhenskyd98c97b2018-03-12 17:29:24 +00005768 IsLdsOpcode = false;
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +00005769 }
5770 }
5771
Nikolay Haustov2e4c7292016-02-25 10:58:54 +00005772 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
Artem Tamazov8ce1f712016-05-19 12:22:39 +00005773 if (!IsAtomic) { // glc is hard-coded.
5774 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
5775 }
Nikolay Haustov2e4c7292016-02-25 10:58:54 +00005776 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +00005777
Dmitry Preobrazhenskyd98c97b2018-03-12 17:29:24 +00005778 if (!IsLdsOpcode) { // tfe is not legal with lds opcodes
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +00005779 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
5780 }
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00005781
5782 if (isGFX10())
5783 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDLC);
Tom Stellard45bb48e2015-06-13 03:28:10 +00005784}
5785
David Stuttard70e8bc12017-06-22 16:29:22 +00005786void AMDGPUAsmParser::cvtMtbuf(MCInst &Inst, const OperandVector &Operands) {
5787 OptionalImmIndexMap OptionalIdx;
5788
5789 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
5790 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
5791
5792 // Add the register arguments
5793 if (Op.isReg()) {
5794 Op.addRegOperands(Inst, 1);
5795 continue;
5796 }
5797
5798 // Handle the case where soffset is an immediate
5799 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
5800 Op.addImmOperands(Inst, 1);
5801 continue;
5802 }
5803
5804 // Handle tokens like 'offen' which are sometimes hard-coded into the
5805 // asm string. There are no MCInst operands for these.
5806 if (Op.isToken()) {
5807 continue;
5808 }
5809 assert(Op.isImm());
5810
5811 // Handle optional arguments
5812 OptionalIdx[Op.getImmTy()] = i;
5813 }
5814
5815 addOptionalImmOperand(Inst, Operands, OptionalIdx,
5816 AMDGPUOperand::ImmTyOffset);
Tim Renouf35484c92018-08-21 11:06:05 +00005817 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyFORMAT);
David Stuttard70e8bc12017-06-22 16:29:22 +00005818 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
5819 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
5820 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00005821
5822 if (isGFX10())
5823 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDLC);
David Stuttard70e8bc12017-06-22 16:29:22 +00005824}
5825
Tom Stellard45bb48e2015-06-13 03:28:10 +00005826//===----------------------------------------------------------------------===//
5827// mimg
5828//===----------------------------------------------------------------------===//
5829
Sam Kolton10ac2fd2017-07-07 15:21:52 +00005830void AMDGPUAsmParser::cvtMIMG(MCInst &Inst, const OperandVector &Operands,
5831 bool IsAtomic) {
Sam Kolton1bdcef72016-05-23 09:59:02 +00005832 unsigned I = 1;
5833 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
5834 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
5835 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
5836 }
5837
Sam Kolton10ac2fd2017-07-07 15:21:52 +00005838 if (IsAtomic) {
5839 // Add src, same as dst
Dmitry Preobrazhensky0e074e32018-01-19 13:49:53 +00005840 assert(Desc.getNumDefs() == 1);
5841 ((AMDGPUOperand &)*Operands[I - 1]).addRegOperands(Inst, 1);
Sam Kolton10ac2fd2017-07-07 15:21:52 +00005842 }
5843
Sam Kolton1bdcef72016-05-23 09:59:02 +00005844 OptionalImmIndexMap OptionalIdx;
5845
5846 for (unsigned E = Operands.size(); I != E; ++I) {
5847 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
5848
5849 // Add the register arguments
Dmitry Preobrazhensky0e074e32018-01-19 13:49:53 +00005850 if (Op.isReg()) {
5851 Op.addRegOperands(Inst, 1);
Sam Kolton1bdcef72016-05-23 09:59:02 +00005852 } else if (Op.isImmModifier()) {
5853 OptionalIdx[Op.getImmTy()] = I;
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00005854 } else if (!Op.isToken()) {
Matt Arsenault92b355b2016-11-15 19:34:37 +00005855 llvm_unreachable("unexpected operand type");
Sam Kolton1bdcef72016-05-23 09:59:02 +00005856 }
5857 }
5858
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00005859 bool IsGFX10 = isGFX10();
5860
Sam Kolton1bdcef72016-05-23 09:59:02 +00005861 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00005862 if (IsGFX10)
5863 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDim, -1);
Sam Kolton1bdcef72016-05-23 09:59:02 +00005864 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00005865 if (IsGFX10)
5866 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDLC);
Sam Kolton1bdcef72016-05-23 09:59:02 +00005867 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
Dmitry Preobrazhensky0e074e32018-01-19 13:49:53 +00005868 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
Ryan Taylor1f334d02018-08-28 15:07:30 +00005869 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128A16);
Sam Kolton1bdcef72016-05-23 09:59:02 +00005870 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
5871 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00005872 if (!IsGFX10)
5873 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
Nicolai Haehnlef2674312018-06-21 13:36:01 +00005874 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyD16);
Sam Kolton1bdcef72016-05-23 09:59:02 +00005875}
5876
5877void AMDGPUAsmParser::cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands) {
Sam Kolton10ac2fd2017-07-07 15:21:52 +00005878 cvtMIMG(Inst, Operands, true);
Sam Kolton1bdcef72016-05-23 09:59:02 +00005879}
5880
Tom Stellard45bb48e2015-06-13 03:28:10 +00005881//===----------------------------------------------------------------------===//
Tom Stellard217361c2015-08-06 19:28:38 +00005882// smrd
5883//===----------------------------------------------------------------------===//
5884
Artem Tamazov54bfd542016-10-31 16:07:39 +00005885bool AMDGPUOperand::isSMRDOffset8() const {
Tom Stellard217361c2015-08-06 19:28:38 +00005886 return isImm() && isUInt<8>(getImm());
5887}
5888
Artem Tamazov54bfd542016-10-31 16:07:39 +00005889bool AMDGPUOperand::isSMRDOffset20() const {
5890 return isImm() && isUInt<20>(getImm());
5891}
5892
Tom Stellard217361c2015-08-06 19:28:38 +00005893bool AMDGPUOperand::isSMRDLiteralOffset() const {
5894 // 32-bit literals are only supported on CI and we only want to use them
5895 // when the offset is > 8-bits.
5896 return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm());
5897}
5898
Artem Tamazov54bfd542016-10-31 16:07:39 +00005899AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset8() const {
5900 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
5901}
5902
5903AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset20() const {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00005904 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
Sam Kolton5f10a132016-05-06 11:31:17 +00005905}
5906
5907AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDLiteralOffset() const {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00005908 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
Sam Kolton5f10a132016-05-06 11:31:17 +00005909}
5910
Dmitry Preobrazhensky2eff0312019-07-08 14:27:37 +00005911AMDGPUOperand::Ptr AMDGPUAsmParser::defaultFlatOffset() const {
Matt Arsenault9698f1c2017-06-20 19:54:14 +00005912 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
5913}
5914
Tom Stellard217361c2015-08-06 19:28:38 +00005915//===----------------------------------------------------------------------===//
Tom Stellard45bb48e2015-06-13 03:28:10 +00005916// vop3
5917//===----------------------------------------------------------------------===//
5918
5919static bool ConvertOmodMul(int64_t &Mul) {
5920 if (Mul != 1 && Mul != 2 && Mul != 4)
5921 return false;
5922
5923 Mul >>= 1;
5924 return true;
5925}
5926
5927static bool ConvertOmodDiv(int64_t &Div) {
5928 if (Div == 1) {
5929 Div = 0;
5930 return true;
5931 }
5932
5933 if (Div == 2) {
5934 Div = 3;
5935 return true;
5936 }
5937
5938 return false;
5939}
5940
Nikolay Haustov4f672a32016-04-29 09:02:30 +00005941static bool ConvertBoundCtrl(int64_t &BoundCtrl) {
5942 if (BoundCtrl == 0) {
5943 BoundCtrl = 1;
Tom Stellard45bb48e2015-06-13 03:28:10 +00005944 return true;
Matt Arsenault12c53892016-11-15 19:58:54 +00005945 }
5946
5947 if (BoundCtrl == -1) {
Nikolay Haustov4f672a32016-04-29 09:02:30 +00005948 BoundCtrl = 0;
Tom Stellard45bb48e2015-06-13 03:28:10 +00005949 return true;
Tom Stellard45bb48e2015-06-13 03:28:10 +00005950 }
Matt Arsenault12c53892016-11-15 19:58:54 +00005951
Tom Stellard45bb48e2015-06-13 03:28:10 +00005952 return false;
5953}
5954
Nikolay Haustov4f672a32016-04-29 09:02:30 +00005955// Note: the order in this table matches the order of operands in AsmString.
Sam Kolton11de3702016-05-24 12:38:33 +00005956static const OptionalOperand AMDGPUOptionalOperandTable[] = {
5957 {"offen", AMDGPUOperand::ImmTyOffen, true, nullptr},
5958 {"idxen", AMDGPUOperand::ImmTyIdxen, true, nullptr},
5959 {"addr64", AMDGPUOperand::ImmTyAddr64, true, nullptr},
5960 {"offset0", AMDGPUOperand::ImmTyOffset0, false, nullptr},
5961 {"offset1", AMDGPUOperand::ImmTyOffset1, false, nullptr},
5962 {"gds", AMDGPUOperand::ImmTyGDS, true, nullptr},
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +00005963 {"lds", AMDGPUOperand::ImmTyLDS, true, nullptr},
Sam Kolton11de3702016-05-24 12:38:33 +00005964 {"offset", AMDGPUOperand::ImmTyOffset, false, nullptr},
Dmitry Preobrazhenskydd2f1c92017-11-24 13:22:38 +00005965 {"inst_offset", AMDGPUOperand::ImmTyInstOffset, false, nullptr},
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00005966 {"dlc", AMDGPUOperand::ImmTyDLC, true, nullptr},
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00005967 {"format", AMDGPUOperand::ImmTyFORMAT, false, nullptr},
Sam Kolton11de3702016-05-24 12:38:33 +00005968 {"glc", AMDGPUOperand::ImmTyGLC, true, nullptr},
5969 {"slc", AMDGPUOperand::ImmTySLC, true, nullptr},
5970 {"tfe", AMDGPUOperand::ImmTyTFE, true, nullptr},
Dmitry Preobrazhensky4f321ae2018-01-29 14:20:42 +00005971 {"d16", AMDGPUOperand::ImmTyD16, true, nullptr},
Dmitry Preobrazhensky50805a02017-08-07 13:14:12 +00005972 {"high", AMDGPUOperand::ImmTyHigh, true, nullptr},
Sam Kolton11de3702016-05-24 12:38:33 +00005973 {"clamp", AMDGPUOperand::ImmTyClampSI, true, nullptr},
5974 {"omod", AMDGPUOperand::ImmTyOModSI, false, ConvertOmodMul},
5975 {"unorm", AMDGPUOperand::ImmTyUNorm, true, nullptr},
5976 {"da", AMDGPUOperand::ImmTyDA, true, nullptr},
Ryan Taylor1f334d02018-08-28 15:07:30 +00005977 {"r128", AMDGPUOperand::ImmTyR128A16, true, nullptr},
5978 {"a16", AMDGPUOperand::ImmTyR128A16, true, nullptr},
Sam Kolton11de3702016-05-24 12:38:33 +00005979 {"lwe", AMDGPUOperand::ImmTyLWE, true, nullptr},
Nicolai Haehnlef2674312018-06-21 13:36:01 +00005980 {"d16", AMDGPUOperand::ImmTyD16, true, nullptr},
Sam Kolton11de3702016-05-24 12:38:33 +00005981 {"dmask", AMDGPUOperand::ImmTyDMask, false, nullptr},
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00005982 {"dim", AMDGPUOperand::ImmTyDim, false, nullptr},
Sam Kolton11de3702016-05-24 12:38:33 +00005983 {"row_mask", AMDGPUOperand::ImmTyDppRowMask, false, nullptr},
5984 {"bank_mask", AMDGPUOperand::ImmTyDppBankMask, false, nullptr},
5985 {"bound_ctrl", AMDGPUOperand::ImmTyDppBoundCtrl, false, ConvertBoundCtrl},
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00005986 {"fi", AMDGPUOperand::ImmTyDppFi, false, nullptr},
Sam Kolton05ef1c92016-06-03 10:27:37 +00005987 {"dst_sel", AMDGPUOperand::ImmTySdwaDstSel, false, nullptr},
5988 {"src0_sel", AMDGPUOperand::ImmTySdwaSrc0Sel, false, nullptr},
5989 {"src1_sel", AMDGPUOperand::ImmTySdwaSrc1Sel, false, nullptr},
Sam Kolton11de3702016-05-24 12:38:33 +00005990 {"dst_unused", AMDGPUOperand::ImmTySdwaDstUnused, false, nullptr},
Dmitry Preobrazhensky9321e8f2017-05-19 13:36:09 +00005991 {"compr", AMDGPUOperand::ImmTyExpCompr, true, nullptr },
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00005992 {"vm", AMDGPUOperand::ImmTyExpVM, true, nullptr},
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00005993 {"op_sel", AMDGPUOperand::ImmTyOpSel, false, nullptr},
5994 {"op_sel_hi", AMDGPUOperand::ImmTyOpSelHi, false, nullptr},
5995 {"neg_lo", AMDGPUOperand::ImmTyNegLo, false, nullptr},
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +00005996 {"neg_hi", AMDGPUOperand::ImmTyNegHi, false, nullptr},
5997 {"blgp", AMDGPUOperand::ImmTyBLGP, false, nullptr},
5998 {"cbsz", AMDGPUOperand::ImmTyCBSZ, false, nullptr},
5999 {"abid", AMDGPUOperand::ImmTyABID, false, nullptr}
Nikolay Haustov4f672a32016-04-29 09:02:30 +00006000};
Tom Stellard45bb48e2015-06-13 03:28:10 +00006001
Alex Bradbury58eba092016-11-01 16:32:05 +00006002OperandMatchResultTy AMDGPUAsmParser::parseOptionalOperand(OperandVector &Operands) {
Dmitry Preobrazhensky414e0532017-12-29 13:55:11 +00006003 unsigned size = Operands.size();
6004 assert(size > 0);
6005
6006 OperandMatchResultTy res = parseOptionalOpr(Operands);
6007
6008 // This is a hack to enable hardcoded mandatory operands which follow
6009 // optional operands.
6010 //
6011 // Current design assumes that all operands after the first optional operand
6012 // are also optional. However implementation of some instructions violates
6013 // this rule (see e.g. flat/global atomic which have hardcoded 'glc' operands).
6014 //
6015 // To alleviate this problem, we have to (implicitly) parse extra operands
6016 // to make sure autogenerated parser of custom operands never hit hardcoded
6017 // mandatory operands.
6018
6019 if (size == 1 || ((AMDGPUOperand &)*Operands[size - 1]).isRegKind()) {
6020
6021 // We have parsed the first optional operand.
6022 // Parse as many operands as necessary to skip all mandatory operands.
6023
6024 for (unsigned i = 0; i < MAX_OPR_LOOKAHEAD; ++i) {
6025 if (res != MatchOperand_Success ||
6026 getLexer().is(AsmToken::EndOfStatement)) break;
6027 if (getLexer().is(AsmToken::Comma)) Parser.Lex();
6028 res = parseOptionalOpr(Operands);
6029 }
6030 }
6031
6032 return res;
6033}
6034
6035OperandMatchResultTy AMDGPUAsmParser::parseOptionalOpr(OperandVector &Operands) {
Sam Kolton11de3702016-05-24 12:38:33 +00006036 OperandMatchResultTy res;
6037 for (const OptionalOperand &Op : AMDGPUOptionalOperandTable) {
6038 // try to parse any optional operand here
6039 if (Op.IsBit) {
6040 res = parseNamedBit(Op.Name, Operands, Op.Type);
6041 } else if (Op.Type == AMDGPUOperand::ImmTyOModSI) {
6042 res = parseOModOperand(Operands);
Sam Kolton05ef1c92016-06-03 10:27:37 +00006043 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstSel ||
6044 Op.Type == AMDGPUOperand::ImmTySdwaSrc0Sel ||
6045 Op.Type == AMDGPUOperand::ImmTySdwaSrc1Sel) {
6046 res = parseSDWASel(Operands, Op.Name, Op.Type);
Sam Kolton11de3702016-05-24 12:38:33 +00006047 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstUnused) {
6048 res = parseSDWADstUnused(Operands);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00006049 } else if (Op.Type == AMDGPUOperand::ImmTyOpSel ||
6050 Op.Type == AMDGPUOperand::ImmTyOpSelHi ||
6051 Op.Type == AMDGPUOperand::ImmTyNegLo ||
6052 Op.Type == AMDGPUOperand::ImmTyNegHi) {
6053 res = parseOperandArrayWithPrefix(Op.Name, Operands, Op.Type,
6054 Op.ConvertResult);
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00006055 } else if (Op.Type == AMDGPUOperand::ImmTyDim) {
6056 res = parseDim(Operands);
6057 } else if (Op.Type == AMDGPUOperand::ImmTyFORMAT && !isGFX10()) {
Tim Renouf35484c92018-08-21 11:06:05 +00006058 res = parseDfmtNfmt(Operands);
Sam Kolton11de3702016-05-24 12:38:33 +00006059 } else {
6060 res = parseIntWithPrefix(Op.Name, Operands, Op.Type, Op.ConvertResult);
6061 }
6062 if (res != MatchOperand_NoMatch) {
6063 return res;
Tom Stellard45bb48e2015-06-13 03:28:10 +00006064 }
Tom Stellard45bb48e2015-06-13 03:28:10 +00006065 }
6066 return MatchOperand_NoMatch;
6067}
6068
Matt Arsenault12c53892016-11-15 19:58:54 +00006069OperandMatchResultTy AMDGPUAsmParser::parseOModOperand(OperandVector &Operands) {
Nikolay Haustov4f672a32016-04-29 09:02:30 +00006070 StringRef Name = Parser.getTok().getString();
6071 if (Name == "mul") {
Matt Arsenault12c53892016-11-15 19:58:54 +00006072 return parseIntWithPrefix("mul", Operands,
6073 AMDGPUOperand::ImmTyOModSI, ConvertOmodMul);
Nikolay Haustov4f672a32016-04-29 09:02:30 +00006074 }
Matt Arsenault12c53892016-11-15 19:58:54 +00006075
6076 if (Name == "div") {
6077 return parseIntWithPrefix("div", Operands,
6078 AMDGPUOperand::ImmTyOModSI, ConvertOmodDiv);
6079 }
6080
6081 return MatchOperand_NoMatch;
Nikolay Haustov4f672a32016-04-29 09:02:30 +00006082}
6083
Dmitry Preobrazhenskyabf28392017-07-21 13:54:11 +00006084void AMDGPUAsmParser::cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands) {
6085 cvtVOP3P(Inst, Operands);
6086
6087 int Opc = Inst.getOpcode();
6088
6089 int SrcNum;
6090 const int Ops[] = { AMDGPU::OpName::src0,
6091 AMDGPU::OpName::src1,
6092 AMDGPU::OpName::src2 };
6093 for (SrcNum = 0;
6094 SrcNum < 3 && AMDGPU::getNamedOperandIdx(Opc, Ops[SrcNum]) != -1;
6095 ++SrcNum);
6096 assert(SrcNum > 0);
6097
6098 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
6099 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
6100
6101 if ((OpSel & (1 << SrcNum)) != 0) {
6102 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers);
6103 uint32_t ModVal = Inst.getOperand(ModIdx).getImm();
6104 Inst.getOperand(ModIdx).setImm(ModVal | SISrcMods::DST_OP_SEL);
6105 }
6106}
6107
Sam Koltona3ec5c12016-10-07 14:46:06 +00006108static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum) {
6109 // 1. This operand is input modifiers
6110 return Desc.OpInfo[OpNum].OperandType == AMDGPU::OPERAND_INPUT_MODS
6111 // 2. This is not last operand
6112 && Desc.NumOperands > (OpNum + 1)
6113 // 3. Next operand is register class
6114 && Desc.OpInfo[OpNum + 1].RegClass != -1
6115 // 4. Next register is not tied to any other operand
6116 && Desc.getOperandConstraint(OpNum + 1, MCOI::OperandConstraint::TIED_TO) == -1;
6117}
6118
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00006119void AMDGPUAsmParser::cvtVOP3Interp(MCInst &Inst, const OperandVector &Operands)
6120{
Dmitry Preobrazhensky50805a02017-08-07 13:14:12 +00006121 OptionalImmIndexMap OptionalIdx;
6122 unsigned Opc = Inst.getOpcode();
6123
6124 unsigned I = 1;
6125 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
6126 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
6127 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
6128 }
6129
6130 for (unsigned E = Operands.size(); I != E; ++I) {
6131 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
6132 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
6133 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
6134 } else if (Op.isInterpSlot() ||
6135 Op.isInterpAttr() ||
6136 Op.isAttrChan()) {
Dmitry Preobrazhensky47621d72019-04-24 14:06:15 +00006137 Inst.addOperand(MCOperand::createImm(Op.getImm()));
Dmitry Preobrazhensky50805a02017-08-07 13:14:12 +00006138 } else if (Op.isImmModifier()) {
6139 OptionalIdx[Op.getImmTy()] = I;
6140 } else {
6141 llvm_unreachable("unhandled operand type");
6142 }
6143 }
6144
6145 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::high) != -1) {
6146 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyHigh);
6147 }
6148
6149 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1) {
6150 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
6151 }
6152
6153 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod) != -1) {
6154 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
6155 }
6156}
6157
Sam Kolton10ac2fd2017-07-07 15:21:52 +00006158void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands,
6159 OptionalImmIndexMap &OptionalIdx) {
6160 unsigned Opc = Inst.getOpcode();
6161
Tom Stellarda90b9522016-02-11 03:28:15 +00006162 unsigned I = 1;
6163 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
Tom Stellarde9934512016-02-11 18:25:26 +00006164 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
Tom Stellarda90b9522016-02-11 03:28:15 +00006165 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
Tom Stellard88e0b252015-10-06 15:57:53 +00006166 }
Tom Stellard45bb48e2015-06-13 03:28:10 +00006167
Sam Kolton10ac2fd2017-07-07 15:21:52 +00006168 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers) != -1) {
6169 // This instruction has src modifiers
6170 for (unsigned E = Operands.size(); I != E; ++I) {
6171 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
6172 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
6173 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
6174 } else if (Op.isImmModifier()) {
6175 OptionalIdx[Op.getImmTy()] = I;
6176 } else if (Op.isRegOrImm()) {
6177 Op.addRegOrImmOperands(Inst, 1);
6178 } else {
6179 llvm_unreachable("unhandled operand type");
6180 }
6181 }
6182 } else {
6183 // No src modifiers
6184 for (unsigned E = Operands.size(); I != E; ++I) {
6185 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
6186 if (Op.isMod()) {
6187 OptionalIdx[Op.getImmTy()] = I;
6188 } else {
6189 Op.addRegOrImmOperands(Inst, 1);
6190 }
Tom Stellard45bb48e2015-06-13 03:28:10 +00006191 }
Tom Stellarda90b9522016-02-11 03:28:15 +00006192 }
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00006193
Sam Kolton10ac2fd2017-07-07 15:21:52 +00006194 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1) {
6195 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
6196 }
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00006197
Sam Kolton10ac2fd2017-07-07 15:21:52 +00006198 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod) != -1) {
6199 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
6200 }
Sam Koltona3ec5c12016-10-07 14:46:06 +00006201
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00006202 // Special case v_mac_{f16, f32} and v_fmac_{f16, f32} (gfx906/gfx10+):
Sam Koltona3ec5c12016-10-07 14:46:06 +00006203 // it has src2 register operand that is tied to dst operand
6204 // we don't allow modifiers for this operand in assembler so src2_modifiers
Matt Arsenault0084adc2018-04-30 19:08:16 +00006205 // should be 0.
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00006206 if (Opc == AMDGPU::V_MAC_F32_e64_gfx6_gfx7 ||
6207 Opc == AMDGPU::V_MAC_F32_e64_gfx10 ||
Matt Arsenault0084adc2018-04-30 19:08:16 +00006208 Opc == AMDGPU::V_MAC_F32_e64_vi ||
6209 Opc == AMDGPU::V_MAC_F16_e64_vi ||
Stanislav Mekhanoshin8f3da702019-04-26 16:37:51 +00006210 Opc == AMDGPU::V_FMAC_F32_e64_gfx10 ||
6211 Opc == AMDGPU::V_FMAC_F32_e64_vi ||
6212 Opc == AMDGPU::V_FMAC_F16_e64_gfx10) {
Sam Koltona3ec5c12016-10-07 14:46:06 +00006213 auto it = Inst.begin();
Sam Kolton10ac2fd2017-07-07 15:21:52 +00006214 std::advance(it, AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2_modifiers));
Sam Koltona3ec5c12016-10-07 14:46:06 +00006215 it = Inst.insert(it, MCOperand::createImm(0)); // no modifiers for src2
6216 ++it;
6217 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
6218 }
Tom Stellard45bb48e2015-06-13 03:28:10 +00006219}
6220
Sam Kolton10ac2fd2017-07-07 15:21:52 +00006221void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) {
Dmitry Preobrazhenskyc512d442017-03-27 15:57:17 +00006222 OptionalImmIndexMap OptionalIdx;
Sam Kolton10ac2fd2017-07-07 15:21:52 +00006223 cvtVOP3(Inst, Operands, OptionalIdx);
Dmitry Preobrazhenskyc512d442017-03-27 15:57:17 +00006224}
6225
Dmitry Preobrazhensky682a6542017-11-17 15:15:40 +00006226void AMDGPUAsmParser::cvtVOP3P(MCInst &Inst,
6227 const OperandVector &Operands) {
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00006228 OptionalImmIndexMap OptIdx;
Dmitry Preobrazhensky682a6542017-11-17 15:15:40 +00006229 const int Opc = Inst.getOpcode();
6230 const MCInstrDesc &Desc = MII.get(Opc);
6231
6232 const bool IsPacked = (Desc.TSFlags & SIInstrFlags::IsPacked) != 0;
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00006233
Sam Kolton10ac2fd2017-07-07 15:21:52 +00006234 cvtVOP3(Inst, Operands, OptIdx);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00006235
Matt Arsenaulte135c4c2017-09-20 20:53:49 +00006236 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in) != -1) {
6237 assert(!IsPacked);
6238 Inst.addOperand(Inst.getOperand(0));
6239 }
6240
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00006241 // FIXME: This is messy. Parse the modifiers as if it was a normal VOP3
6242 // instruction, and then figure out where to actually put the modifiers
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00006243
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00006244 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSel);
Dmitry Preobrazhenskyabf28392017-07-21 13:54:11 +00006245
6246 int OpSelHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel_hi);
6247 if (OpSelHiIdx != -1) {
Matt Arsenaultc8f8cda2017-08-30 22:18:40 +00006248 int DefaultVal = IsPacked ? -1 : 0;
6249 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSelHi,
6250 DefaultVal);
Dmitry Preobrazhenskyabf28392017-07-21 13:54:11 +00006251 }
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00006252
6253 int NegLoIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_lo);
6254 if (NegLoIdx != -1) {
Matt Arsenaultc8f8cda2017-08-30 22:18:40 +00006255 assert(IsPacked);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00006256 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegLo);
6257 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegHi);
6258 }
6259
6260 const int Ops[] = { AMDGPU::OpName::src0,
6261 AMDGPU::OpName::src1,
6262 AMDGPU::OpName::src2 };
6263 const int ModOps[] = { AMDGPU::OpName::src0_modifiers,
6264 AMDGPU::OpName::src1_modifiers,
6265 AMDGPU::OpName::src2_modifiers };
6266
6267 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00006268
6269 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
Dmitry Preobrazhenskyabf28392017-07-21 13:54:11 +00006270 unsigned OpSelHi = 0;
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00006271 unsigned NegLo = 0;
6272 unsigned NegHi = 0;
6273
Dmitry Preobrazhenskyabf28392017-07-21 13:54:11 +00006274 if (OpSelHiIdx != -1) {
6275 OpSelHi = Inst.getOperand(OpSelHiIdx).getImm();
6276 }
6277
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00006278 if (NegLoIdx != -1) {
6279 int NegHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_hi);
6280 NegLo = Inst.getOperand(NegLoIdx).getImm();
6281 NegHi = Inst.getOperand(NegHiIdx).getImm();
6282 }
6283
6284 for (int J = 0; J < 3; ++J) {
6285 int OpIdx = AMDGPU::getNamedOperandIdx(Opc, Ops[J]);
6286 if (OpIdx == -1)
6287 break;
6288
6289 uint32_t ModVal = 0;
6290
6291 if ((OpSel & (1 << J)) != 0)
6292 ModVal |= SISrcMods::OP_SEL_0;
6293
6294 if ((OpSelHi & (1 << J)) != 0)
6295 ModVal |= SISrcMods::OP_SEL_1;
6296
6297 if ((NegLo & (1 << J)) != 0)
6298 ModVal |= SISrcMods::NEG;
6299
6300 if ((NegHi & (1 << J)) != 0)
6301 ModVal |= SISrcMods::NEG_HI;
6302
6303 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
6304
Dmitry Preobrazhenskyb2d24e22017-07-07 14:29:06 +00006305 Inst.getOperand(ModIdx).setImm(Inst.getOperand(ModIdx).getImm() | ModVal);
Matt Arsenault9be7b0d2017-02-27 18:49:11 +00006306 }
6307}
6308
Sam Koltondfa29f72016-03-09 12:29:31 +00006309//===----------------------------------------------------------------------===//
6310// dpp
6311//===----------------------------------------------------------------------===//
6312
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006313bool AMDGPUOperand::isDPP8() const {
6314 return isImmTy(ImmTyDPP8);
6315}
6316
Sam Koltondfa29f72016-03-09 12:29:31 +00006317bool AMDGPUOperand::isDPPCtrl() const {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006318 using namespace AMDGPU::DPP;
6319
Sam Koltondfa29f72016-03-09 12:29:31 +00006320 bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm());
6321 if (result) {
6322 int64_t Imm = getImm();
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006323 return (Imm >= DppCtrl::QUAD_PERM_FIRST && Imm <= DppCtrl::QUAD_PERM_LAST) ||
6324 (Imm >= DppCtrl::ROW_SHL_FIRST && Imm <= DppCtrl::ROW_SHL_LAST) ||
6325 (Imm >= DppCtrl::ROW_SHR_FIRST && Imm <= DppCtrl::ROW_SHR_LAST) ||
6326 (Imm >= DppCtrl::ROW_ROR_FIRST && Imm <= DppCtrl::ROW_ROR_LAST) ||
6327 (Imm == DppCtrl::WAVE_SHL1) ||
6328 (Imm == DppCtrl::WAVE_ROL1) ||
6329 (Imm == DppCtrl::WAVE_SHR1) ||
6330 (Imm == DppCtrl::WAVE_ROR1) ||
6331 (Imm == DppCtrl::ROW_MIRROR) ||
6332 (Imm == DppCtrl::ROW_HALF_MIRROR) ||
6333 (Imm == DppCtrl::BCAST15) ||
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006334 (Imm == DppCtrl::BCAST31) ||
6335 (Imm >= DppCtrl::ROW_SHARE_FIRST && Imm <= DppCtrl::ROW_SHARE_LAST) ||
6336 (Imm >= DppCtrl::ROW_XMASK_FIRST && Imm <= DppCtrl::ROW_XMASK_LAST);
Sam Koltondfa29f72016-03-09 12:29:31 +00006337 }
6338 return false;
6339}
6340
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +00006341//===----------------------------------------------------------------------===//
6342// mAI
6343//===----------------------------------------------------------------------===//
6344
6345bool AMDGPUOperand::isBLGP() const {
6346 return isImm() && getImmTy() == ImmTyBLGP && isUInt<3>(getImm());
6347}
6348
6349bool AMDGPUOperand::isCBSZ() const {
6350 return isImm() && getImmTy() == ImmTyCBSZ && isUInt<3>(getImm());
6351}
6352
6353bool AMDGPUOperand::isABID() const {
6354 return isImm() && getImmTy() == ImmTyABID && isUInt<4>(getImm());
6355}
6356
Dmitry Preobrazhenskyc7d35a02017-04-26 15:34:19 +00006357bool AMDGPUOperand::isS16Imm() const {
6358 return isImm() && (isInt<16>(getImm()) || isUInt<16>(getImm()));
6359}
6360
6361bool AMDGPUOperand::isU16Imm() const {
6362 return isImm() && isUInt<16>(getImm());
6363}
6364
Stanislav Mekhanoshin692560d2019-05-01 16:32:58 +00006365OperandMatchResultTy AMDGPUAsmParser::parseDim(OperandVector &Operands) {
6366 if (!isGFX10())
6367 return MatchOperand_NoMatch;
6368
6369 SMLoc S = Parser.getTok().getLoc();
6370
6371 if (getLexer().isNot(AsmToken::Identifier))
6372 return MatchOperand_NoMatch;
6373 if (getLexer().getTok().getString() != "dim")
6374 return MatchOperand_NoMatch;
6375
6376 Parser.Lex();
6377 if (getLexer().isNot(AsmToken::Colon))
6378 return MatchOperand_ParseFail;
6379
6380 Parser.Lex();
6381
6382 // We want to allow "dim:1D" etc., but the initial 1 is tokenized as an
6383 // integer.
6384 std::string Token;
6385 if (getLexer().is(AsmToken::Integer)) {
6386 SMLoc Loc = getLexer().getTok().getEndLoc();
6387 Token = getLexer().getTok().getString();
6388 Parser.Lex();
6389 if (getLexer().getTok().getLoc() != Loc)
6390 return MatchOperand_ParseFail;
6391 }
6392 if (getLexer().isNot(AsmToken::Identifier))
6393 return MatchOperand_ParseFail;
6394 Token += getLexer().getTok().getString();
6395
6396 StringRef DimId = Token;
6397 if (DimId.startswith("SQ_RSRC_IMG_"))
6398 DimId = DimId.substr(12);
6399
6400 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByAsmSuffix(DimId);
6401 if (!DimInfo)
6402 return MatchOperand_ParseFail;
6403
6404 Parser.Lex();
6405
6406 Operands.push_back(AMDGPUOperand::CreateImm(this, DimInfo->Encoding, S,
6407 AMDGPUOperand::ImmTyDim));
6408 return MatchOperand_Success;
6409}
6410
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006411OperandMatchResultTy AMDGPUAsmParser::parseDPP8(OperandVector &Operands) {
6412 SMLoc S = Parser.getTok().getLoc();
6413 StringRef Prefix;
6414
6415 if (getLexer().getKind() == AsmToken::Identifier) {
6416 Prefix = Parser.getTok().getString();
6417 } else {
6418 return MatchOperand_NoMatch;
6419 }
6420
6421 if (Prefix != "dpp8")
6422 return parseDPPCtrl(Operands);
6423 if (!isGFX10())
6424 return MatchOperand_NoMatch;
6425
6426 // dpp8:[%d,%d,%d,%d,%d,%d,%d,%d]
6427
6428 int64_t Sels[8];
6429
6430 Parser.Lex();
6431 if (getLexer().isNot(AsmToken::Colon))
6432 return MatchOperand_ParseFail;
6433
6434 Parser.Lex();
6435 if (getLexer().isNot(AsmToken::LBrac))
6436 return MatchOperand_ParseFail;
6437
6438 Parser.Lex();
6439 if (getParser().parseAbsoluteExpression(Sels[0]))
6440 return MatchOperand_ParseFail;
6441 if (0 > Sels[0] || 7 < Sels[0])
6442 return MatchOperand_ParseFail;
6443
6444 for (size_t i = 1; i < 8; ++i) {
6445 if (getLexer().isNot(AsmToken::Comma))
6446 return MatchOperand_ParseFail;
6447
6448 Parser.Lex();
6449 if (getParser().parseAbsoluteExpression(Sels[i]))
6450 return MatchOperand_ParseFail;
6451 if (0 > Sels[i] || 7 < Sels[i])
6452 return MatchOperand_ParseFail;
6453 }
6454
6455 if (getLexer().isNot(AsmToken::RBrac))
6456 return MatchOperand_ParseFail;
6457 Parser.Lex();
6458
6459 unsigned DPP8 = 0;
6460 for (size_t i = 0; i < 8; ++i)
6461 DPP8 |= (Sels[i] << (i * 3));
6462
6463 Operands.push_back(AMDGPUOperand::CreateImm(this, DPP8, S, AMDGPUOperand::ImmTyDPP8));
6464 return MatchOperand_Success;
6465}
6466
Alex Bradbury58eba092016-11-01 16:32:05 +00006467OperandMatchResultTy
Sam Kolton11de3702016-05-24 12:38:33 +00006468AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006469 using namespace AMDGPU::DPP;
6470
Sam Koltondfa29f72016-03-09 12:29:31 +00006471 SMLoc S = Parser.getTok().getLoc();
6472 StringRef Prefix;
6473 int64_t Int;
Sam Koltondfa29f72016-03-09 12:29:31 +00006474
Sam Koltona74cd522016-03-18 15:35:51 +00006475 if (getLexer().getKind() == AsmToken::Identifier) {
6476 Prefix = Parser.getTok().getString();
6477 } else {
6478 return MatchOperand_NoMatch;
6479 }
6480
6481 if (Prefix == "row_mirror") {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006482 Int = DppCtrl::ROW_MIRROR;
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006483 Parser.Lex();
Sam Koltona74cd522016-03-18 15:35:51 +00006484 } else if (Prefix == "row_half_mirror") {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006485 Int = DppCtrl::ROW_HALF_MIRROR;
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006486 Parser.Lex();
Sam Koltona74cd522016-03-18 15:35:51 +00006487 } else {
Sam Kolton201398e2016-04-21 13:14:24 +00006488 // Check to prevent parseDPPCtrlOps from eating invalid tokens
6489 if (Prefix != "quad_perm"
6490 && Prefix != "row_shl"
6491 && Prefix != "row_shr"
6492 && Prefix != "row_ror"
6493 && Prefix != "wave_shl"
6494 && Prefix != "wave_rol"
6495 && Prefix != "wave_shr"
6496 && Prefix != "wave_ror"
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006497 && Prefix != "row_bcast"
6498 && Prefix != "row_share"
6499 && Prefix != "row_xmask") {
Sam Kolton11de3702016-05-24 12:38:33 +00006500 return MatchOperand_NoMatch;
Sam Kolton201398e2016-04-21 13:14:24 +00006501 }
6502
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006503 if (!isGFX10() && (Prefix == "row_share" || Prefix == "row_xmask"))
6504 return MatchOperand_NoMatch;
6505
6506 if (!isVI() && !isGFX9() &&
6507 (Prefix == "wave_shl" || Prefix == "wave_shr" ||
6508 Prefix == "wave_rol" || Prefix == "wave_ror" ||
6509 Prefix == "row_bcast"))
6510 return MatchOperand_NoMatch;
6511
Sam Koltona74cd522016-03-18 15:35:51 +00006512 Parser.Lex();
6513 if (getLexer().isNot(AsmToken::Colon))
6514 return MatchOperand_ParseFail;
6515
6516 if (Prefix == "quad_perm") {
6517 // quad_perm:[%d,%d,%d,%d]
Sam Koltondfa29f72016-03-09 12:29:31 +00006518 Parser.Lex();
Sam Koltona74cd522016-03-18 15:35:51 +00006519 if (getLexer().isNot(AsmToken::LBrac))
Sam Koltondfa29f72016-03-09 12:29:31 +00006520 return MatchOperand_ParseFail;
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006521 Parser.Lex();
Sam Koltondfa29f72016-03-09 12:29:31 +00006522
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006523 if (getParser().parseAbsoluteExpression(Int) || !(0 <= Int && Int <=3))
Sam Koltondfa29f72016-03-09 12:29:31 +00006524 return MatchOperand_ParseFail;
6525
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006526 for (int i = 0; i < 3; ++i) {
6527 if (getLexer().isNot(AsmToken::Comma))
6528 return MatchOperand_ParseFail;
6529 Parser.Lex();
Sam Koltondfa29f72016-03-09 12:29:31 +00006530
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006531 int64_t Temp;
6532 if (getParser().parseAbsoluteExpression(Temp) || !(0 <= Temp && Temp <=3))
6533 return MatchOperand_ParseFail;
6534 const int shift = i*2 + 2;
6535 Int += (Temp << shift);
6536 }
Sam Koltona74cd522016-03-18 15:35:51 +00006537
Sam Koltona74cd522016-03-18 15:35:51 +00006538 if (getLexer().isNot(AsmToken::RBrac))
6539 return MatchOperand_ParseFail;
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006540 Parser.Lex();
Sam Koltona74cd522016-03-18 15:35:51 +00006541 } else {
6542 // sel:%d
6543 Parser.Lex();
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006544 if (getParser().parseAbsoluteExpression(Int))
Sam Koltona74cd522016-03-18 15:35:51 +00006545 return MatchOperand_ParseFail;
Sam Koltona74cd522016-03-18 15:35:51 +00006546
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006547 if (Prefix == "row_shl" && 1 <= Int && Int <= 15) {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006548 Int |= DppCtrl::ROW_SHL0;
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006549 } else if (Prefix == "row_shr" && 1 <= Int && Int <= 15) {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006550 Int |= DppCtrl::ROW_SHR0;
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006551 } else if (Prefix == "row_ror" && 1 <= Int && Int <= 15) {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006552 Int |= DppCtrl::ROW_ROR0;
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006553 } else if (Prefix == "wave_shl" && 1 == Int) {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006554 Int = DppCtrl::WAVE_SHL1;
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006555 } else if (Prefix == "wave_rol" && 1 == Int) {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006556 Int = DppCtrl::WAVE_ROL1;
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006557 } else if (Prefix == "wave_shr" && 1 == Int) {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006558 Int = DppCtrl::WAVE_SHR1;
Artem Tamazov2146a0a2016-09-22 11:47:21 +00006559 } else if (Prefix == "wave_ror" && 1 == Int) {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006560 Int = DppCtrl::WAVE_ROR1;
Sam Koltona74cd522016-03-18 15:35:51 +00006561 } else if (Prefix == "row_bcast") {
6562 if (Int == 15) {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006563 Int = DppCtrl::BCAST15;
Sam Koltona74cd522016-03-18 15:35:51 +00006564 } else if (Int == 31) {
Stanislav Mekhanoshin43293612018-05-08 16:53:02 +00006565 Int = DppCtrl::BCAST31;
Sam Kolton7a2a3232016-07-14 14:50:35 +00006566 } else {
6567 return MatchOperand_ParseFail;
Sam Koltona74cd522016-03-18 15:35:51 +00006568 }
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006569 } else if (Prefix == "row_share" && 0 <= Int && Int <= 15) {
6570 Int |= DppCtrl::ROW_SHARE_FIRST;
6571 } else if (Prefix == "row_xmask" && 0 <= Int && Int <= 15) {
6572 Int |= DppCtrl::ROW_XMASK_FIRST;
Sam Koltona74cd522016-03-18 15:35:51 +00006573 } else {
Sam Kolton201398e2016-04-21 13:14:24 +00006574 return MatchOperand_ParseFail;
Sam Koltona74cd522016-03-18 15:35:51 +00006575 }
Sam Koltondfa29f72016-03-09 12:29:31 +00006576 }
Sam Koltondfa29f72016-03-09 12:29:31 +00006577 }
Sam Koltona74cd522016-03-18 15:35:51 +00006578
Sam Kolton1eeb11b2016-09-09 14:44:04 +00006579 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTyDppCtrl));
Sam Koltondfa29f72016-03-09 12:29:31 +00006580 return MatchOperand_Success;
6581}
6582
Sam Kolton5f10a132016-05-06 11:31:17 +00006583AMDGPUOperand::Ptr AMDGPUAsmParser::defaultRowMask() const {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00006584 return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppRowMask);
Sam Koltondfa29f72016-03-09 12:29:31 +00006585}
6586
David Stuttard20ea21c2019-03-12 09:52:58 +00006587AMDGPUOperand::Ptr AMDGPUAsmParser::defaultEndpgmImmOperands() const {
6588 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyEndpgm);
6589}
6590
Sam Kolton5f10a132016-05-06 11:31:17 +00006591AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBankMask() const {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00006592 return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppBankMask);
Sam Koltondfa29f72016-03-09 12:29:31 +00006593}
6594
Sam Kolton5f10a132016-05-06 11:31:17 +00006595AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBoundCtrl() const {
Sam Kolton1eeb11b2016-09-09 14:44:04 +00006596 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDppBoundCtrl);
Sam Kolton5f10a132016-05-06 11:31:17 +00006597}
6598
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006599AMDGPUOperand::Ptr AMDGPUAsmParser::defaultFI() const {
6600 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDppFi);
6601}
6602
6603void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands, bool IsDPP8) {
Sam Koltondfa29f72016-03-09 12:29:31 +00006604 OptionalImmIndexMap OptionalIdx;
6605
6606 unsigned I = 1;
6607 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
6608 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
6609 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
6610 }
6611
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006612 int Fi = 0;
Sam Koltondfa29f72016-03-09 12:29:31 +00006613 for (unsigned E = Operands.size(); I != E; ++I) {
Valery Pykhtin3d9afa22018-11-30 14:21:56 +00006614 auto TiedTo = Desc.getOperandConstraint(Inst.getNumOperands(),
6615 MCOI::TIED_TO);
6616 if (TiedTo != -1) {
6617 assert((unsigned)TiedTo < Inst.getNumOperands());
6618 // handle tied old or src2 for MAC instructions
6619 Inst.addOperand(Inst.getOperand(TiedTo));
6620 }
Sam Koltondfa29f72016-03-09 12:29:31 +00006621 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
6622 // Add the register arguments
Stanislav Mekhanoshin8bcc9bb2019-06-13 19:18:29 +00006623 if (Op.isReg() && validateVccOperand(Op.getReg())) {
Sam Kolton07dbde22017-01-20 10:01:25 +00006624 // VOP2b (v_add_u32, v_sub_u32 ...) dpp use "vcc" token.
Sam Koltone66365e2016-12-27 10:06:42 +00006625 // Skip it.
6626 continue;
Simon Pilgrim6f349d82019-04-29 17:34:26 +00006627 }
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006628
6629 if (IsDPP8) {
6630 if (Op.isDPP8()) {
6631 Op.addImmOperands(Inst, 1);
6632 } else if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
6633 Op.addRegWithFPInputModsOperands(Inst, 2);
6634 } else if (Op.isFI()) {
6635 Fi = Op.getImm();
6636 } else if (Op.isReg()) {
6637 Op.addRegOperands(Inst, 1);
6638 } else {
6639 llvm_unreachable("Invalid operand type");
6640 }
Sam Koltondfa29f72016-03-09 12:29:31 +00006641 } else {
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006642 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
6643 Op.addRegWithFPInputModsOperands(Inst, 2);
6644 } else if (Op.isDPPCtrl()) {
6645 Op.addImmOperands(Inst, 1);
6646 } else if (Op.isImm()) {
6647 // Handle optional arguments
6648 OptionalIdx[Op.getImmTy()] = I;
6649 } else {
6650 llvm_unreachable("Invalid operand type");
6651 }
Sam Koltondfa29f72016-03-09 12:29:31 +00006652 }
6653 }
6654
Stanislav Mekhanoshin245b5ba2019-06-12 18:02:41 +00006655 if (IsDPP8) {
6656 using namespace llvm::AMDGPU::DPP;
6657 Inst.addOperand(MCOperand::createImm(Fi? DPP8_FI_1 : DPP8_FI_0));
6658 } else {
6659 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf);
6660 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf);
6661 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl);
6662 if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::fi) != -1) {
6663 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppFi);
6664 }
6665 }
Sam Koltondfa29f72016-03-09 12:29:31 +00006666}
Nikolay Haustov5bf46ac12016-03-04 10:39:50 +00006667
Sam Kolton3025e7f2016-04-26 13:33:56 +00006668//===----------------------------------------------------------------------===//
6669// sdwa
6670//===----------------------------------------------------------------------===//
6671
Alex Bradbury58eba092016-11-01 16:32:05 +00006672OperandMatchResultTy
Sam Kolton05ef1c92016-06-03 10:27:37 +00006673AMDGPUAsmParser::parseSDWASel(OperandVector &Operands, StringRef Prefix,
6674 AMDGPUOperand::ImmTy Type) {
Sam Koltona3ec5c12016-10-07 14:46:06 +00006675 using namespace llvm::AMDGPU::SDWA;
6676
Sam Kolton3025e7f2016-04-26 13:33:56 +00006677 SMLoc S = Parser.getTok().getLoc();
6678 StringRef Value;
Alex Bradbury58eba092016-11-01 16:32:05 +00006679 OperandMatchResultTy res;
Matt Arsenault37fefd62016-06-10 02:18:02 +00006680
Sam Kolton05ef1c92016-06-03 10:27:37 +00006681 res = parseStringWithPrefix(Prefix, Value);
6682 if (res != MatchOperand_Success) {
6683 return res;
Sam Kolton3025e7f2016-04-26 13:33:56 +00006684 }
Matt Arsenault37fefd62016-06-10 02:18:02 +00006685
Sam Kolton3025e7f2016-04-26 13:33:56 +00006686 int64_t Int;
6687 Int = StringSwitch<int64_t>(Value)
Sam Koltona3ec5c12016-10-07 14:46:06 +00006688 .Case("BYTE_0", SdwaSel::BYTE_0)
6689 .Case("BYTE_1", SdwaSel::BYTE_1)
6690 .Case("BYTE_2", SdwaSel::BYTE_2)
6691 .Case("BYTE_3", SdwaSel::BYTE_3)
6692 .Case("WORD_0", SdwaSel::WORD_0)
6693 .Case("WORD_1", SdwaSel::WORD_1)
6694 .Case("DWORD", SdwaSel::DWORD)
Sam Kolton3025e7f2016-04-26 13:33:56 +00006695 .Default(0xffffffff);
6696 Parser.Lex(); // eat last token
6697
6698 if (Int == 0xffffffff) {
6699 return MatchOperand_ParseFail;
6700 }
6701
Sam Kolton1eeb11b2016-09-09 14:44:04 +00006702 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, Type));
Sam Kolton3025e7f2016-04-26 13:33:56 +00006703 return MatchOperand_Success;
6704}
6705
Alex Bradbury58eba092016-11-01 16:32:05 +00006706OperandMatchResultTy
Sam Kolton3025e7f2016-04-26 13:33:56 +00006707AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) {
Sam Koltona3ec5c12016-10-07 14:46:06 +00006708 using namespace llvm::AMDGPU::SDWA;
6709
Sam Kolton3025e7f2016-04-26 13:33:56 +00006710 SMLoc S = Parser.getTok().getLoc();
6711 StringRef Value;
Alex Bradbury58eba092016-11-01 16:32:05 +00006712 OperandMatchResultTy res;
Sam Kolton3025e7f2016-04-26 13:33:56 +00006713
6714 res = parseStringWithPrefix("dst_unused", Value);
6715 if (res != MatchOperand_Success) {
6716 return res;
6717 }
6718
6719 int64_t Int;
6720 Int = StringSwitch<int64_t>(Value)
Sam Koltona3ec5c12016-10-07 14:46:06 +00006721 .Case("UNUSED_PAD", DstUnused::UNUSED_PAD)
6722 .Case("UNUSED_SEXT", DstUnused::UNUSED_SEXT)
6723 .Case("UNUSED_PRESERVE", DstUnused::UNUSED_PRESERVE)
Sam Kolton3025e7f2016-04-26 13:33:56 +00006724 .Default(0xffffffff);
6725 Parser.Lex(); // eat last token
6726
6727 if (Int == 0xffffffff) {
6728 return MatchOperand_ParseFail;
6729 }
6730
Sam Kolton1eeb11b2016-09-09 14:44:04 +00006731 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTySdwaDstUnused));
Sam Kolton3025e7f2016-04-26 13:33:56 +00006732 return MatchOperand_Success;
6733}
6734
Sam Kolton945231a2016-06-10 09:57:59 +00006735void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) {
Sam Kolton5196b882016-07-01 09:59:21 +00006736 cvtSDWA(Inst, Operands, SIInstrFlags::VOP1);
Sam Kolton05ef1c92016-06-03 10:27:37 +00006737}
6738
Sam Kolton945231a2016-06-10 09:57:59 +00006739void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) {
Sam Kolton5196b882016-07-01 09:59:21 +00006740 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2);
6741}
6742
Sam Koltonf7659d712017-05-23 10:08:55 +00006743void AMDGPUAsmParser::cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands) {
6744 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2, true);
6745}
6746
Sam Kolton5196b882016-07-01 09:59:21 +00006747void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) {
Sam Koltonf7659d712017-05-23 10:08:55 +00006748 cvtSDWA(Inst, Operands, SIInstrFlags::VOPC, isVI());
Sam Kolton05ef1c92016-06-03 10:27:37 +00006749}
6750
6751void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands,
Sam Koltonf7659d712017-05-23 10:08:55 +00006752 uint64_t BasicInstType, bool skipVcc) {
Sam Kolton9dffada2017-01-17 15:26:02 +00006753 using namespace llvm::AMDGPU::SDWA;
Eugene Zelenkoc8fbf6f2017-08-10 00:46:15 +00006754
Sam Kolton05ef1c92016-06-03 10:27:37 +00006755 OptionalImmIndexMap OptionalIdx;
Sam Koltonf7659d712017-05-23 10:08:55 +00006756 bool skippedVcc = false;
Sam Kolton05ef1c92016-06-03 10:27:37 +00006757
6758 unsigned I = 1;
6759 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
6760 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
6761 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
6762 }
6763
6764 for (unsigned E = Operands.size(); I != E; ++I) {
6765 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
Stanislav Mekhanoshin8bcc9bb2019-06-13 19:18:29 +00006766 if (skipVcc && !skippedVcc && Op.isReg() &&
6767 (Op.getReg() == AMDGPU::VCC || Op.getReg() == AMDGPU::VCC_LO)) {
Sam Koltonf7659d712017-05-23 10:08:55 +00006768 // VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst.
6769 // Skip it if it's 2nd (e.g. v_add_i32_sdwa v1, vcc, v2, v3)
6770 // or 4th (v_addc_u32_sdwa v1, vcc, v2, v3, vcc) operand.
6771 // Skip VCC only if we didn't skip it on previous iteration.
6772 if (BasicInstType == SIInstrFlags::VOP2 &&
6773 (Inst.getNumOperands() == 1 || Inst.getNumOperands() == 5)) {
6774 skippedVcc = true;
6775 continue;
6776 } else if (BasicInstType == SIInstrFlags::VOPC &&
6777 Inst.getNumOperands() == 0) {
6778 skippedVcc = true;
6779 continue;
6780 }
6781 }
6782 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
Dmitry Preobrazhensky6b65f7c2018-01-17 14:00:48 +00006783 Op.addRegOrImmWithInputModsOperands(Inst, 2);
Sam Kolton05ef1c92016-06-03 10:27:37 +00006784 } else if (Op.isImm()) {
6785 // Handle optional arguments
6786 OptionalIdx[Op.getImmTy()] = I;
6787 } else {
6788 llvm_unreachable("Invalid operand type");
6789 }
Sam Koltonf7659d712017-05-23 10:08:55 +00006790 skippedVcc = false;
Sam Kolton05ef1c92016-06-03 10:27:37 +00006791 }
6792
Stanislav Mekhanoshin4f331cb2019-04-26 23:16:16 +00006793 if (Inst.getOpcode() != AMDGPU::V_NOP_sdwa_gfx10 &&
6794 Inst.getOpcode() != AMDGPU::V_NOP_sdwa_gfx9 &&
Sam Koltonf7659d712017-05-23 10:08:55 +00006795 Inst.getOpcode() != AMDGPU::V_NOP_sdwa_vi) {
Sam Kolton549c89d2017-06-21 08:53:38 +00006796 // v_nop_sdwa_sdwa_vi/gfx9 has no optional sdwa arguments
Sam Koltona3ec5c12016-10-07 14:46:06 +00006797 switch (BasicInstType) {
Eugene Zelenko2bc2f332016-12-09 22:06:55 +00006798 case SIInstrFlags::VOP1:
Sam Koltonf7659d712017-05-23 10:08:55 +00006799 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
Sam Kolton549c89d2017-06-21 08:53:38 +00006800 if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) {
Sam Koltonf7659d712017-05-23 10:08:55 +00006801 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0);
6802 }
Sam Kolton9dffada2017-01-17 15:26:02 +00006803 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD);
6804 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE);
6805 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
Sam Koltona3ec5c12016-10-07 14:46:06 +00006806 break;
Eugene Zelenko2bc2f332016-12-09 22:06:55 +00006807
6808 case SIInstrFlags::VOP2:
Sam Koltonf7659d712017-05-23 10:08:55 +00006809 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
Sam Kolton549c89d2017-06-21 08:53:38 +00006810 if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) {
Sam Koltonf7659d712017-05-23 10:08:55 +00006811 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0);
6812 }
Sam Kolton9dffada2017-01-17 15:26:02 +00006813 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD);
6814 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE);
6815 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
6816 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD);
Sam Koltona3ec5c12016-10-07 14:46:06 +00006817 break;
Eugene Zelenko2bc2f332016-12-09 22:06:55 +00006818
6819 case SIInstrFlags::VOPC:
Stanislav Mekhanoshina6322942019-04-30 22:08:23 +00006820 if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::clamp) != -1)
6821 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
Sam Kolton9dffada2017-01-17 15:26:02 +00006822 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
6823 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD);
Sam Koltona3ec5c12016-10-07 14:46:06 +00006824 break;
Eugene Zelenko2bc2f332016-12-09 22:06:55 +00006825
Sam Koltona3ec5c12016-10-07 14:46:06 +00006826 default:
6827 llvm_unreachable("Invalid instruction type. Only VOP1, VOP2 and VOPC allowed");
6828 }
Sam Kolton05ef1c92016-06-03 10:27:37 +00006829 }
Matt Arsenaultf3dd8632016-11-01 00:55:14 +00006830
Konstantin Zhuravlyovf86e4b72016-11-13 07:01:11 +00006831 // special case v_mac_{f16, f32}:
Sam Koltona3ec5c12016-10-07 14:46:06 +00006832 // it has src2 register operand that is tied to dst operand
Sam Koltona568e3d2016-12-22 12:57:41 +00006833 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
6834 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
Sam Koltona3ec5c12016-10-07 14:46:06 +00006835 auto it = Inst.begin();
Konstantin Zhuravlyovf86e4b72016-11-13 07:01:11 +00006836 std::advance(
Sam Koltonf7659d712017-05-23 10:08:55 +00006837 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
Sam Koltona3ec5c12016-10-07 14:46:06 +00006838 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
Sam Kolton5196b882016-07-01 09:59:21 +00006839 }
Sam Kolton05ef1c92016-06-03 10:27:37 +00006840}
Nikolay Haustov2f684f12016-02-26 09:51:05 +00006841
Stanislav Mekhanoshin9e77d0c2019-07-09 19:41:51 +00006842//===----------------------------------------------------------------------===//
6843// mAI
6844//===----------------------------------------------------------------------===//
6845
6846AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBLGP() const {
6847 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyBLGP);
6848}
6849
6850AMDGPUOperand::Ptr AMDGPUAsmParser::defaultCBSZ() const {
6851 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyCBSZ);
6852}
6853
6854AMDGPUOperand::Ptr AMDGPUAsmParser::defaultABID() const {
6855 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyABID);
6856}
6857
Tom Stellard45bb48e2015-06-13 03:28:10 +00006858/// Force static initialization.
Tom Stellard4b0b2612019-06-11 03:21:13 +00006859extern "C" void LLVMInitializeAMDGPUAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00006860 RegisterMCAsmParser<AMDGPUAsmParser> A(getTheAMDGPUTarget());
6861 RegisterMCAsmParser<AMDGPUAsmParser> B(getTheGCNTarget());
Tom Stellard45bb48e2015-06-13 03:28:10 +00006862}
6863
6864#define GET_REGISTER_MATCHER
6865#define GET_MATCHER_IMPLEMENTATION
Matt Arsenaultf7f59b52017-12-20 18:52:57 +00006866#define GET_MNEMONIC_SPELL_CHECKER
Tom Stellard45bb48e2015-06-13 03:28:10 +00006867#include "AMDGPUGenAsmMatcher.inc"
Sam Kolton11de3702016-05-24 12:38:33 +00006868
Sam Kolton11de3702016-05-24 12:38:33 +00006869// This fuction should be defined after auto-generated include so that we have
6870// MatchClassKind enum defined
6871unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
6872 unsigned Kind) {
6873 // Tokens like "glc" would be parsed as immediate operands in ParseOperand().
Matt Arsenault37fefd62016-06-10 02:18:02 +00006874 // But MatchInstructionImpl() expects to meet token and fails to validate
Sam Kolton11de3702016-05-24 12:38:33 +00006875 // operand. This method checks if we are given immediate operand but expect to
6876 // get corresponding token.
6877 AMDGPUOperand &Operand = (AMDGPUOperand&)Op;
6878 switch (Kind) {
6879 case MCK_addr64:
6880 return Operand.isAddr64() ? Match_Success : Match_InvalidOperand;
6881 case MCK_gds:
6882 return Operand.isGDS() ? Match_Success : Match_InvalidOperand;
Dmitry Preobrazhenskyd6e1a942018-02-21 13:13:48 +00006883 case MCK_lds:
6884 return Operand.isLDS() ? Match_Success : Match_InvalidOperand;
Sam Kolton11de3702016-05-24 12:38:33 +00006885 case MCK_glc:
6886 return Operand.isGLC() ? Match_Success : Match_InvalidOperand;
6887 case MCK_idxen:
6888 return Operand.isIdxen() ? Match_Success : Match_InvalidOperand;
6889 case MCK_offen:
6890 return Operand.isOffen() ? Match_Success : Match_InvalidOperand;
Sam Kolton1eeb11b2016-09-09 14:44:04 +00006891 case MCK_SSrcB32:
Tom Stellard89049702016-06-15 02:54:14 +00006892 // When operands have expression values, they will return true for isToken,
6893 // because it is not possible to distinguish between a token and an
6894 // expression at parse time. MatchInstructionImpl() will always try to
6895 // match an operand as a token, when isToken returns true, and when the
6896 // name of the expression is not a valid token, the match will fail,
6897 // so we need to handle it here.
Sam Kolton1eeb11b2016-09-09 14:44:04 +00006898 return Operand.isSSrcB32() ? Match_Success : Match_InvalidOperand;
6899 case MCK_SSrcF32:
6900 return Operand.isSSrcF32() ? Match_Success : Match_InvalidOperand;
Artem Tamazov53c9de02016-07-11 12:07:18 +00006901 case MCK_SoppBrTarget:
6902 return Operand.isSoppBrTarget() ? Match_Success : Match_InvalidOperand;
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00006903 case MCK_VReg32OrOff:
6904 return Operand.isVReg32OrOff() ? Match_Success : Match_InvalidOperand;
Matt Arsenault0e8a2992016-12-15 20:40:20 +00006905 case MCK_InterpSlot:
6906 return Operand.isInterpSlot() ? Match_Success : Match_InvalidOperand;
6907 case MCK_Attr:
6908 return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand;
6909 case MCK_AttrChan:
6910 return Operand.isAttrChan() ? Match_Success : Match_InvalidOperand;
Matt Arsenaultbf6bdac2016-12-05 20:42:41 +00006911 default:
6912 return Match_InvalidOperand;
Sam Kolton11de3702016-05-24 12:38:33 +00006913 }
6914}
David Stuttard20ea21c2019-03-12 09:52:58 +00006915
6916//===----------------------------------------------------------------------===//
6917// endpgm
6918//===----------------------------------------------------------------------===//
6919
6920OperandMatchResultTy AMDGPUAsmParser::parseEndpgmOp(OperandVector &Operands) {
6921 SMLoc S = Parser.getTok().getLoc();
6922 int64_t Imm = 0;
6923
6924 if (!parseExpr(Imm)) {
6925 // The operand is optional, if not present default to 0
6926 Imm = 0;
6927 }
6928
6929 if (!isUInt<16>(Imm)) {
6930 Error(S, "expected a 16-bit value");
6931 return MatchOperand_ParseFail;
6932 }
6933
6934 Operands.push_back(
6935 AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTyEndpgm));
6936 return MatchOperand_Success;
6937}
6938
6939bool AMDGPUOperand::isEndpgm() const { return isImmTy(ImmTyEndpgm); }