source: CLRX/CLRadeonExtender/trunk/amdasm/GCNAsmInternals.h @ 4998

Last change on this file since 4998 was 4998, checked in by matszpk, 11 months ago

CLRadeonExtender: GCNASM: Preliminary support for SMRD 32-bit immediate literal if arch==GCN1.1.

File size: 18.1 KB
Line 
1/*
2 *  CLRadeonExtender - Unofficial OpenCL Radeon Extensions Library
3 *  Copyright (C) 2014-2018 Mateusz Szpakowski
4 *
5 *  This library is free software; you can redistribute it and/or
6 *  modify it under the terms of the GNU Lesser General Public
7 *  License as published by the Free Software Foundation; either
8 *  version 2.1 of the License, or (at your option) any later version.
9 *
10 *  This library is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 *  Lesser General Public License for more details.
14 *
15 *  You should have received a copy of the GNU Lesser General Public
16 *  License along with this library; if not, write to the Free Software
17 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19
20#ifndef __CLRX_GCNASMINTERNALS_H__
21#define __CLRX_GCNASMINTERNALS_H__
22
23#include <CLRX/Config.h>
24#include <cstdint>
25#include <string>
26#include <memory>
27#include <utility>
28#include <CLRX/utils/Utilities.h>
29#include <CLRX/amdasm/Assembler.h>
30#include <CLRX/utils/GPUId.h>
31#include "AsmInternals.h"
32#include "GCNInternals.h"
33
34namespace CLRX
35{
36
37enum : Flags {
38    INSTROP_SREGS = 1,
39    INSTROP_SSOURCE = 2,
40    INSTROP_VREGS = 4,
41    INSTROP_LDS = 8,
42    INSTROP_VOP3MODS = 0x10,
43    // used internally by parseGCNOperand to continuing parsing with modifiers
44    INSTROP_PARSEWITHNEG = 0x20,
45    INSTROP_VOP3NEG = 0x40,
46   
47    INSTROP_ONLYINLINECONSTS = 0x80, /// accepts only inline constants
48    INSTROP_NOLITERALERROR = 0x100, /// accepts only inline constants
49    INSTROP_NOLITERALERRORMUBUF = 0x200, /// accepts only inline constants
50   
51    INSTROP_TYPE_MASK = 0x3000,
52    INSTROP_INT = 0x000,    // integer literal
53    INSTROP_FLOAT = 0x1000, // floating point literal
54    INSTROP_F16 = 0x2000,   // half floating point literal
55    INSTROP_V64BIT = 0x3000, // 64-bit value (specific for vector instructions)
56    INSTROP_UNALIGNED = 0xc000, // not aligned, use by parseRegisterRange
57    INSTROP_ALIGNED = 0x0000,
58    INSTROP_SGPR_UNALIGNED = 0x4000,
59   
60    INSTROP_READ = 0x10000,
61    INSTROP_WRITE = 0x20000,
62    INSTROP_ACCESS_MASK = 0x30000,
63    INSTROP_NOSEXT = 0x40000,
64    INSTROP_VOP3P = 0x80000, // VOP3P encoding
65   
66    // for parseSRregRange/parseVRegRange
67    INSTROP_SYMREGRANGE = 1
68};
69
70// standard VOP operand modifers
71enum: cxbyte {
72    VOPOP_ABS = 1,
73    VOPOP_NEG = 2,
74    VOPOP_SEXT = 4
75};
76
77// VOP3 modifiers
78enum: cxbyte {
79    VOP3_MUL2 = 1,
80    VOP3_MUL4 = 2,
81    VOP3_DIV2 = 3,
82    VOP3_CLAMP = 16,
83    VOP3_VOP3 = 32,
84    VOP3_BOUNDCTRL = 64
85};
86
87// represent register range with regvar
88struct CLRX_INTERNAL RegRange
89{
90    uint16_t start, end;
91    const AsmRegVar* regVar;
92   
93    RegRange(): start(0), end(0), regVar(nullptr)
94    { }
95    template<typename U1, typename U2>
96    RegRange(U1 t1, U2 t2 = 0, const AsmRegVar* rv = nullptr)
97            : start(t1), end(t2), regVar(rv)
98    { }
99   
100    bool operator!() const
101    { return start==0 && end==0; }
102    operator bool() const
103    { return start!=0 || end!=0; }
104    // return start register or zero if regvar (start is not specified)
105    uint16_t bstart() const
106    { return (regVar==nullptr) ? start : 0; }
107   
108    bool isRegVar() const
109    { return regVar!=nullptr; }
110    // return if start register is reg
111    bool isVal(uint16_t reg) const
112    { return (regVar==nullptr && start==reg); }
113   
114    bool isSGPR() const
115    { return (regVar==nullptr && start<108) || (regVar!=nullptr &&
116                regVar->type==REGTYPE_SGPR); }
117    bool isNonVGPR() const
118    { return (regVar==nullptr && start<256) || (regVar!=nullptr &&
119                regVar->type==REGTYPE_SGPR); }
120    bool isVGPR() const
121    { return (regVar==nullptr && start>=256) || (regVar!=nullptr &&
122                regVar->type==REGTYPE_VGPR); }
123};
124
125// GCN operand (can be regrange or value) with VOP modifiers
126struct CLRX_INTERNAL GCNOperand
127{
128    RegRange range;
129    uint32_t value;
130    cxbyte vopMods;
131   
132    bool operator!() const
133    { return !range; }
134    operator bool() const
135    { return range; }
136};
137
138// VOP extra modifiers
139struct CLRX_INTERNAL VOPExtraModifiers
140{
141    cxbyte dstSel;
142    cxbyte dstUnused;
143    cxbyte src0Sel;
144    cxbyte src1Sel;
145    cxbyte bankMask;
146    cxbyte rowMask;
147    uint16_t dppCtrl;
148    bool needSDWA;
149    bool needDPP;
150    bool fi; // DPP GFX10
151    bool needDPP8;
152    uint32_t dpp8Value;
153};
154
155// VOP operand modifiers (booleans)
156struct CLRX_INTERNAL VOPOpModifiers
157{
158    cxbyte absMod;
159    cxbyte negMod; // lo (low 4-bits) and hi (high 4-bits)
160    cxbyte sextMod;
161    cxbyte opselMod; // lo (low 4-bits) and hi (high 4-bits)
162};
163
164// GCN encoding sizes
165enum class GCNEncSize
166{
167    UNKNOWN,
168    BIT32,
169    BIT64
170};
171
172enum class GCNVOPEnc
173{
174    NORMAL,
175    DPP,
176    SDWA
177};
178
179// flags for parse VOP modifiers (specifies what will be parsed)
180enum {
181    PARSEVOP_WITHCLAMP = 1,
182    PARSEVOP_WITHSEXT = 2,
183    PARSEVOP_WITHOPSEL = 4,
184    PARSEVOP_VOP3P = 8, // VOP3P modifiers
185    // do not parse dst_unused and dst_sel (for GCN1.4 SDWAB encoding)
186    PARSEVOP_NODSTMODS = 16
187};
188
189struct CLRX_INTERNAL GCNAsmUtils: AsmParseUtils
190{
191    // helper that print error that specified regrange expected
192    static bool printRegisterRangeExpected(Assembler& asmr, const char* linePtr,
193               const char* regPoolName, cxuint regsNum, bool required);
194    // helper that print error that specified regrange required
195    static void printXRegistersRequired(Assembler& asmr, const char* linePtr,
196               const char* regPoolName, cxuint requiredRegsNum);
197   
198    // parse register variable range
199    static bool parseRegVarRange(Assembler& asmr, const char*& linePtr,
200                 RegRange& regPair, GPUArchMask arch, cxuint regsNum, AsmRegField regField,
201                 Flags flags, bool required = true);
202    // parse symbol register range
203    static bool parseSymRegRange(Assembler& asmr, const char*& linePtr, RegRange& regPair,
204                 GPUArchMask arch, cxuint regsNum, AsmRegField regField, Flags flags,
205                 bool required = true);
206    /* return true if no error */
207    static bool parseVRegRange(Assembler& asmr, const char*& linePtr, RegRange& regPair,
208                   cxuint regsNum, AsmRegField regField, bool required = true,
209                   Flags flags = INSTROP_SYMREGRANGE);
210    /* return true if no error */
211    static bool parseVRegRangesLimited(Assembler& asmr, const char*& linePtr,
212                   cxuint vgprsLimit, std::vector<RegRange>& regPairs,
213                   AsmRegField regField, Flags flags = INSTROP_SYMREGRANGE);
214    /* return true if no error */
215    static bool parseSRegRange(Assembler& asmr, const char*& linePtr, RegRange& regPair,
216                   GPUArchMask arch, cxuint regsNum, AsmRegField regField,
217                   bool required = true, Flags flags = INSTROP_SYMREGRANGE);
218   
219    // bits=UINT_MAX - no range checking
220    /* return true if no error */
221    static bool parseImmInt(Assembler& asmr, const char*& linePtr, uint32_t& value,
222            std::unique_ptr<AsmExpression>* outTargetExpr, cxuint bits = 0,
223            cxbyte signess = WS_BOTH);
224    static bool parseSMRDImm(Assembler& asmr, const char*& linePtr, uint32_t& value,
225            std::unique_ptr<AsmExpression>* outTargetExpr, bool &litimm);
226   
227    // parse immediate value (for field) with specified bits (can be signed)
228    template<typename T>
229    static bool parseImm(Assembler& asmr, const char*& linePtr, T& value,
230            std::unique_ptr<AsmExpression>* outTargetExpr, cxuint bits = 0,
231            cxbyte signess = WS_BOTH)
232    {
233        uint32_t v32;
234        bool ret = parseImmInt(asmr, linePtr, v32, outTargetExpr,
235               (bits!=0?bits:(sizeof(T)<<3)), signess);
236        if ((outTargetExpr==nullptr || *outTargetExpr==nullptr) && ret)
237            value = v32;
238        return ret;
239    }
240   
241    // parse array of booleans
242    static bool parseImmWithBoolArray(Assembler& asmr, const char*& linePtr,
243            uint32_t& value, cxuint bits = 0, cxbyte signess = WS_BOTH);
244   
245    static bool parseLiteralImm(Assembler& asmr, const char*& linePtr, uint32_t& value,
246            std::unique_ptr<AsmExpression>* outTargetExpr, Flags instropMask = 0);
247   
248    static bool parseSingleOMODCLAMP(Assembler& asmr, const char*& linePtr,
249                const char* modPlace, const char* mod, GPUArchMask arch, cxbyte& mods,
250                VOPOpModifiers& opMods, cxuint modOperands, cxuint flags,
251                bool& haveAbs, bool& haveNeg, bool& alreadyDefined, bool& good);
252   
253    /* withSDWAOperands - number operand that will be handled by SDWA modifer parser,
254     * modOperands - number of operands for abs,neg,sext
255     * (includes destination at begin) */
256    static bool parseVOPModifiers(Assembler& asmr, const char*& linePtr, GPUArchMask arch,
257                       cxbyte& mods, VOPOpModifiers& opMods, cxuint modOperands,
258                       VOPExtraModifiers* extraMods = nullptr,
259                       cxuint flags = PARSEVOP_WITHCLAMP|PARSEVOP_WITHSEXT,
260                       cxuint withSDWAOperands = 3);
261   
262    static bool parseOperand(Assembler& asmr, const char*& linePtr, GCNOperand& operand,
263               std::unique_ptr<AsmExpression>* outTargetExpr, GPUArchMask arch,
264               cxuint regsNum, Flags instrOpMask, AsmRegField regField);
265   
266    template<typename T>
267    static bool parseModImm(Assembler& asmr, const char*& linePtr, T& value,
268            std::unique_ptr<AsmExpression>* outTargetExpr, const char* modName,
269            cxuint bits = 0, cxbyte signess = WS_BOTH)
270    {
271        if (outTargetExpr!=nullptr)
272            outTargetExpr->reset();
273        const char* end = asmr.line+asmr.lineSize;
274        skipSpacesToEnd(linePtr, end);
275        if (linePtr!=end && *linePtr==':')
276        {
277            skipCharAndSpacesToEnd(linePtr, end);
278            return parseImm(asmr, linePtr, value, outTargetExpr, bits, signess);
279        }
280        asmr.printError(linePtr, (std::string("Expected ':' before ")+modName).c_str());
281        return false;
282    }
283   
284    // parse modifier parameter (to enable or disable modifier: mod:[0:1])
285    static bool parseModEnable(Assembler& asmr, const char*& linePtr, bool& value,
286            const char* modName)
287    {
288        uint64_t val = 0;
289        const char* end = asmr.line+asmr.lineSize;
290        skipSpacesToEnd(linePtr, end);
291        if (linePtr==end || *linePtr!=':')
292        {
293            // by default is enabled
294            value = true;
295            return true;
296        }
297        // OldModParam choice between old parametrization rules and new rules
298        // in old rules (accepts only 0 or 1), in new can any value
299        bool ret = parseModImm(asmr, linePtr, val, nullptr, modName,
300                        asmr.isOldModParam() ? 1 : UINT_MAX, WS_UNSIGNED);
301        value = val!=0;
302        return ret;
303    }
304   
305    static bool parseVINTRP0P10P20(Assembler& asmr, const char*& linePtr, RegRange& reg);
306    static bool parseVINTRPAttr(Assembler& asmr, const char*& linePtr, cxbyte& attr);
307   
308    static bool getMUBUFFmtNameArg(Assembler& asmr, size_t maxOutStrSize, char* outStr,
309               const char*& linePtr, const char* objName);
310   
311    // checking whether encoding size is match
312    static bool checkGCNEncodingSize(Assembler& asmr, const char* insnPtr,
313                     GCNEncSize gcnEncSize, uint32_t wordsNum);
314    // checking whether VOP encoding is match
315    static bool checkGCNVOPEncoding(Assembler& asmr, GPUArchMask arch, const char* insnPtr,
316            GCNVOPEnc vopEnc, GCNInsnMode insnMode, const VOPExtraModifiers* modifiers);
317    // checking whether VOP extra modifiers match
318    static bool checkGCNVOPExtraModifers(Assembler& asmr, GPUArchMask arch,
319                 bool needImm, bool sextFlags, bool vop3, GCNVOPEnc gcnVOPEnc,
320                 const GCNOperand& src0Op, VOPExtraModifiers& extraMods,
321                 bool absNegFlags, const char* instrPlace);
322   
323    // routines to parse GCN encodings
324    static bool parseSOP2Encoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
325                      const char* instrPlace, const char* linePtr, GPUArchMask arch,
326                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
327                      GCNEncSize gcnEncSize);
328    static bool parseSOP1Encoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
329                      const char* instrPlace, const char* linePtr, GPUArchMask arch,
330                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
331                      GCNEncSize gcnEncSize);
332    static bool parseSOPKEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
333                      const char* instrPlace, const char* linePtr, GPUArchMask arch,
334                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
335                      GCNEncSize gcnEncSize);
336    static bool parseSOPCEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
337                      const char* instrPlace, const char* linePtr, GPUArchMask arch,
338                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
339                      GCNEncSize gcnEncSize);
340    static bool parseSOPPEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
341                      const char* instrPlace, const char* linePtr, GPUArchMask arch,
342                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
343                      GCNEncSize gcnEncSize);
344   
345    static bool parseSMRDEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
346                      const char* instrPlace, const char* linePtr, GPUArchMask arch,
347                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
348                      GCNEncSize gcnEncSize);
349    static bool parseSMEMEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
350                      const char* instrPlace, const char* linePtr, GPUArchMask arch,
351                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
352                      GCNEncSize gcnEncSize);
353   
354    static bool parseVOP2Encoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
355                      const char* instrPlace, const char* linePtr, GPUArchMask arch,
356                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
357                      GCNEncSize gcnEncSize, GCNVOPEnc gcnVOPEnc);
358    static bool parseVOP1Encoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
359                      const char* instrPlace, const char* linePtr, GPUArchMask arch,
360                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
361                      GCNEncSize gcnEncSize, GCNVOPEnc gcnVOPEnc);
362    static bool parseVOPCEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
363                      const char* instrPlace, const char* linePtr, GPUArchMask arch,
364                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
365                      GCNEncSize gcnEncSize, GCNVOPEnc gcnVOPEnc);
366    static bool parseVOP3Encoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
367                      const char* instrPlace, const char* linePtr, GPUArchMask arch,
368                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
369                      GCNEncSize gcnEncSize, GCNVOPEnc gcnVOPEnc);
370    static bool parseVINTRPEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
371                      const char* instrPlace, const char* linePtr, GPUArchMask arch,
372                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
373                      GCNEncSize gcnEncSize, GCNVOPEnc gcnVOPEnc);
374    static bool parseDSEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
375                      const char* instrPlace, const char* linePtr, GPUArchMask arch,
376                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
377                      GCNEncSize gcnEncSize);
378    static bool parseMUBUFEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
379                      const char* instrPlace, const char* linePtr, GPUArchMask arch,
380                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
381                      GCNEncSize gcnEncSize);
382    static bool parseMIMGEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
383                      const char* instrPlace, const char* linePtr, GPUArchMask arch,
384                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
385                      GCNEncSize gcnEncSize);
386    static bool parseEXPEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
387                      const char* instrPlace, const char* linePtr, GPUArchMask arch,
388                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
389                      GCNEncSize gcnEncSize);
390    static bool parseFLATEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
391                      const char* instrPlace, const char* linePtr, GPUArchMask arch,
392                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
393                      GCNEncSize gcnEncSize);
394   
395    static void prepareRVUAndWait(GCNAssembler* gcnAsm, GPUArchMask arch, bool vdataToRead,
396            bool vdataToWrite, bool haveLds, bool haveTfe, std::vector<cxbyte>& output,
397            const GCNAsmInstruction& gcnInsn);
398};
399
400static inline bool isXRegRange(RegRange pair, cxuint regsNum = 1)
401{
402    // second==0 - we assume that first is inline constant, otherwise we check range
403    return (pair.end==0) || cxuint(pair.end-pair.start)==regsNum;
404}
405
406static inline void updateVGPRsNum(cxuint& vgprsNum, cxuint vgpr)
407{
408    vgprsNum = std::min(std::max(vgprsNum, vgpr+1), 256U);
409}
410
411static inline void updateSGPRsNum(cxuint& sgprsNum, cxuint sgpr, GPUArchMask arch)
412{
413    cxuint maxSGPRsNum = getGPUMaxRegsNumByArchMask(arch, REGTYPE_SGPR);
414    if (sgpr < maxSGPRsNum) /* sgpr=-1 does not change sgprsNum */
415        sgprsNum = std::min(std::max(sgprsNum, sgpr+1), maxSGPRsNum-2);
416}
417
418static inline void updateRegFlags(Flags& regFlags, cxuint reg, GPUArchMask arch)
419{
420    reg &= ~1;
421    if (reg==106)
422        regFlags |= GCN_VCC;
423    else if (((arch&ARCH_GCN_1_2_4)!=0 && reg==102) ||
424            ((arch&ARCH_GCN_1_2_4)==0 && reg==104))
425        regFlags |= GCN_FLAT;
426    else if ((arch&ARCH_GCN_1_2_4)!=0 && reg==104)
427        regFlags |= GCN_XNACK;
428}
429
430};
431
432#endif
Note: See TracBrowser for help on using the repository browser.