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

Last change on this file since 3096 was 3096, checked in by matszpk, 2 years ago

CLRadeonExtender: GCNAsm: Add parametrizable modifers: abs, neg, sext.

File size: 15.0 KB
Line 
1/*
2 *  CLRadeonExtender - Unofficial OpenCL Radeon Extensions Library
3 *  Copyright (C) 2014-2017 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 "AsmInternals.h"
31#include "GCNInternals.h"
32
33namespace CLRX
34{
35
36enum : Flags {
37    INSTROP_SREGS = 1,
38    INSTROP_SSOURCE = 2,
39    INSTROP_VREGS = 4,
40    INSTROP_LDS = 8,
41    INSTROP_VOP3MODS = 0x10,
42    // used internally by parseGCNOperand to continuing parsing with modifiers
43    INSTROP_PARSEWITHNEG = 0x20,
44    INSTROP_VOP3NEG = 0x40,
45   
46    INSTROP_ONLYINLINECONSTS = 0x80, /// accepts only inline constants
47    INSTROP_NOLITERALERROR = 0x100, /// accepts only inline constants
48    INSTROP_NOLITERALERRORMUBUF = 0x200, /// accepts only inline constants
49   
50    INSTROP_TYPE_MASK = 0x3000,
51    INSTROP_INT = 0x000,    // integer literal
52    INSTROP_FLOAT = 0x1000, // floating point literal
53    INSTROP_F16 = 0x2000,   // half floating point literal
54    INSTROP_V64BIT = 0x3000, // 64-bit value (specific for vector instructions)
55    INSTROP_UNALIGNED = 0x8000, // not aligned, use by parseRegisterRange
56   
57    INSTROP_READ = 0x10000,
58    INSTROP_WRITE = 0x20000,
59    INSTROP_ACCESS_MASK = 0x30000,
60   
61    // for parseSRregRange/parseVRegRange
62    INSTROP_SYMREGRANGE = 1
63};
64
65enum: cxbyte {
66    VOPOP_ABS = 1,
67    VOPOP_NEG = 2,
68    VOPOP_SEXT = 4
69};
70
71enum: cxbyte {
72    VOP3_MUL2 = 1,
73    VOP3_MUL4 = 2,
74    VOP3_DIV2 = 3,
75    VOP3_CLAMP = 16,
76    VOP3_VOP3 = 32,
77    VOP3_BOUNDCTRL = 64
78};
79
80struct CLRX_INTERNAL RegRange
81{
82    uint16_t start, end;
83    const AsmRegVar* regVar;
84   
85    RegRange(): start(0), end(0), regVar(nullptr)
86    { }
87    template<typename U1, typename U2>
88    RegRange(U1 t1, U2 t2 = 0, const AsmRegVar* rv = nullptr)
89            : start(t1), end(t2), regVar(rv)
90    { }
91   
92    bool operator!() const
93    { return start==0 && end==0; }
94    operator bool() const
95    { return start!=0 || end!=0; }
96   
97    uint16_t bstart() const
98    { return (regVar==nullptr) ? start : 0; }
99   
100    bool isRegVar() const
101    { return regVar!=nullptr; }
102   
103    bool isVal(uint16_t reg) const
104    { return (regVar==nullptr && start==reg); }
105   
106    bool isSGPR() const
107    { return (regVar==nullptr && start<108) || (regVar!=nullptr &&
108                regVar->type==REGTYPE_SGPR); }
109    bool isNonVGPR() const
110    { return (regVar==nullptr && start<256) || (regVar!=nullptr &&
111                regVar->type==REGTYPE_SGPR); }
112    bool isVGPR() const
113    { return (regVar==nullptr && start>=256) || (regVar!=nullptr &&
114                regVar->type==REGTYPE_VGPR); }
115};
116
117struct CLRX_INTERNAL GCNOperand
118{
119    RegRange range;
120    uint32_t value;
121    cxbyte vopMods;
122   
123    bool operator!() const
124    { return !range; }
125    operator bool() const
126    { return range; }
127};
128
129struct CLRX_INTERNAL VOPExtraModifiers
130{   // TODO: check that for MSVC 2015
131    cxbyte dstSel;
132    cxbyte dstUnused;
133    cxbyte src0Sel;
134    cxbyte src1Sel;
135    cxbyte bankMask;
136    cxbyte rowMask;
137    uint16_t dppCtrl;
138    bool needSDWA;
139    bool needDPP;
140};
141
142struct CLRX_INTERNAL VOPOpModifiers
143{
144    cxbyte absMod;
145    cxbyte negMod;
146    cxbyte sextMod;
147};
148
149enum class GCNEncSize
150{
151    UNKNOWN,
152    BIT32,
153    BIT64
154};
155
156enum class GCNVOPEnc
157{
158    NORMAL,
159    DPP,
160    SDWA
161};
162
163struct CLRX_INTERNAL GCNAsmUtils: AsmParseUtils
164{
165    static bool printRegisterRangeExpected(Assembler& asmr, const char* linePtr,
166               const char* regPoolName, cxuint regsNum, bool required);
167   
168    static void printXRegistersRequired(Assembler& asmr, const char* linePtr,
169               const char* regPoolName, cxuint requiredRegsNum);
170   
171    static bool parseRegVarRange(Assembler& asmr, const char*& linePtr,
172                 RegRange& regPair, uint16_t arch, cxuint regsNum, AsmRegField regField,
173                 Flags flags, bool required = true);
174   
175    static bool parseSymRegRange(Assembler& asmr, const char*& linePtr, RegRange& regPair,
176                 uint16_t arch, cxuint regsNum, AsmRegField regField, Flags flags,
177                 bool required = true);
178    /* return true if no error */
179    static bool parseVRegRange(Assembler& asmr, const char*& linePtr, RegRange& regPair,
180                   cxuint regsNum, AsmRegField regField, bool required = true,
181                   Flags flags = INSTROP_SYMREGRANGE);
182    /* return true if no error */
183    static bool parseSRegRange(Assembler& asmr, const char*& linePtr, RegRange& regPair,
184                   uint16_t arch, cxuint regsNum, AsmRegField regField,
185                   bool required = true, Flags flags = INSTROP_SYMREGRANGE);
186   
187    // bits=UINT_MAX - no range checking
188    /* return true if no error */
189    static bool parseImmInt(Assembler& asmr, const char*& linePtr, uint32_t& value,
190            std::unique_ptr<AsmExpression>* outTargetExpr, cxuint bits = 0,
191            cxbyte signess = WS_BOTH);
192   
193    template<typename T>
194    static bool parseImm(Assembler& asmr, const char*& linePtr, T& value,
195            std::unique_ptr<AsmExpression>* outTargetExpr, cxuint bits = 0,
196            cxbyte signess = WS_BOTH)
197    {
198        uint32_t v32;
199        bool ret = parseImmInt(asmr, linePtr, v32, outTargetExpr,
200               (bits!=0?bits:(sizeof(T)<<3)), signess);
201        if ((outTargetExpr==nullptr || *outTargetExpr==nullptr) && ret)
202            value = v32;
203        return ret;
204    }
205   
206    static bool parseLiteralImm(Assembler& asmr, const char*& linePtr, uint32_t& value,
207            std::unique_ptr<AsmExpression>* outTargetExpr, Flags instropMask = 0);
208   
209    /* withSDWAOperands - number operand that will be handled by SDWA modifer parser,
210     * (includes destination at begin) */
211    static bool parseVOPModifiers(Assembler& asmr, const char*& linePtr, uint16_t arch,
212                       cxbyte& mods, VOPOpModifiers& opMods,
213                       VOPExtraModifiers* extraMods = nullptr, bool withClamp = true,
214                       cxuint withSDWAOperands = 3);
215   
216    static bool parseOperand(Assembler& asmr, const char*& linePtr, GCNOperand& operand,
217               std::unique_ptr<AsmExpression>* outTargetExpr, uint16_t arch,
218               cxuint regsNum, Flags instrOpMask, AsmRegField regField);
219   
220    template<typename T>
221    static bool parseModImm(Assembler& asmr, const char*& linePtr, T& value,
222            std::unique_ptr<AsmExpression>* outTargetExpr, const char* modName,
223            cxuint bits = 0, cxbyte signess = WS_BOTH)
224    {
225        if (outTargetExpr!=nullptr)
226            outTargetExpr->reset();
227        const char* end = asmr.line+asmr.lineSize;
228        skipSpacesToEnd(linePtr, end);
229        if (linePtr!=end && *linePtr==':')
230        {
231            skipCharAndSpacesToEnd(linePtr, end);
232            return parseImm(asmr, linePtr, value, outTargetExpr, bits, signess);
233        }
234        asmr.printError(linePtr, (std::string("Expected ':' before ")+modName).c_str());
235        return false;
236    }
237   
238    static bool parseModEnable(Assembler& asmr, const char*& linePtr, bool& value,
239            const char* modName)
240    {
241        cxbyte val = 0;
242        const char* end = asmr.line+asmr.lineSize;
243        skipSpacesToEnd(linePtr, end);
244        if (linePtr==end || *linePtr!=':')
245        {   // by default is enabled
246            value = true;
247            return true;
248        }
249       
250        bool ret = parseModImm(asmr, linePtr, val, nullptr, modName, 1, WS_UNSIGNED);
251        value = val!=0;
252        return ret;
253    }
254   
255    static bool parseVINTRP0P10P20(Assembler& asmr, const char*& linePtr, RegRange& reg);
256    static bool parseVINTRPAttr(Assembler& asmr, const char*& linePtr, cxbyte& attr);
257   
258    static bool getMUBUFFmtNameArg(Assembler& asmr, size_t maxOutStrSize, char* outStr,
259               const char*& linePtr, const char* objName);
260   
261    static bool checkGCNEncodingSize(Assembler& asmr, const char* insnPtr,
262                     GCNEncSize gcnEncSize, uint32_t wordsNum);
263    static bool checkGCNVOPEncoding(Assembler& asmr, const char* insnPtr,
264                     GCNVOPEnc vopEnc, const VOPExtraModifiers* modifiers);
265    static bool checkGCNVOPExtraModifers(Assembler& asmr, bool needImm, bool sextFlags,
266                 bool vop3, GCNVOPEnc gcnVOPEnc, const GCNOperand& src0Op,
267                 VOPExtraModifiers& extraMods, const char* instrPlace);
268   
269    static bool parseSOP2Encoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
270                      const char* instrPlace, const char* linePtr, uint16_t arch,
271                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
272                      GCNEncSize gcnEncSize);
273    static bool parseSOP1Encoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
274                      const char* instrPlace, const char* linePtr, uint16_t arch,
275                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
276                      GCNEncSize gcnEncSize);
277    static bool parseSOPKEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
278                      const char* instrPlace, const char* linePtr, uint16_t arch,
279                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
280                      GCNEncSize gcnEncSize);
281    static bool parseSOPCEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
282                      const char* instrPlace, const char* linePtr, uint16_t arch,
283                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
284                      GCNEncSize gcnEncSize);
285    static bool parseSOPPEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
286                      const char* instrPlace, const char* linePtr, uint16_t arch,
287                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
288                      GCNEncSize gcnEncSize);
289   
290    static bool parseSMRDEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
291                      const char* instrPlace, const char* linePtr, uint16_t arch,
292                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
293                      GCNEncSize gcnEncSize);
294    static bool parseSMEMEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
295                      const char* instrPlace, const char* linePtr, uint16_t arch,
296                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
297                      GCNEncSize gcnEncSize);
298   
299    static bool parseVOP2Encoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
300                      const char* instrPlace, const char* linePtr, uint16_t arch,
301                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
302                      GCNEncSize gcnEncSize, GCNVOPEnc gcnVOPEnc);
303    static bool parseVOP1Encoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
304                      const char* instrPlace, const char* linePtr, uint16_t arch,
305                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
306                      GCNEncSize gcnEncSize, GCNVOPEnc gcnVOPEnc);
307    static bool parseVOPCEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
308                      const char* instrPlace, const char* linePtr, uint16_t arch,
309                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
310                      GCNEncSize gcnEncSize, GCNVOPEnc gcnVOPEnc);
311    static bool parseVOP3Encoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
312                      const char* instrPlace, const char* linePtr, uint16_t arch,
313                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
314                      GCNEncSize gcnEncSize, GCNVOPEnc gcnVOPEnc);
315    static bool parseVINTRPEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
316                      const char* instrPlace, const char* linePtr, uint16_t arch,
317                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
318                      GCNEncSize gcnEncSize, GCNVOPEnc gcnVOPEnc);
319    static bool parseDSEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
320                      const char* instrPlace, const char* linePtr, uint16_t arch,
321                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
322                      GCNEncSize gcnEncSize);
323    static bool parseMUBUFEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
324                      const char* instrPlace, const char* linePtr, uint16_t arch,
325                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
326                      GCNEncSize gcnEncSize);
327    static bool parseMIMGEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
328                      const char* instrPlace, const char* linePtr, uint16_t arch,
329                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
330                      GCNEncSize gcnEncSize);
331    static bool parseEXPEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
332                      const char* instrPlace, const char* linePtr, uint16_t arch,
333                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
334                      GCNEncSize gcnEncSize);
335    static bool parseFLATEncoding(Assembler& asmr, const GCNAsmInstruction& gcnInsn,
336                      const char* instrPlace, const char* linePtr, uint16_t arch,
337                      std::vector<cxbyte>& output, GCNAssembler::Regs& gcnRegs,
338                      GCNEncSize gcnEncSize);
339};
340
341static inline bool isXRegRange(RegRange pair, cxuint regsNum = 1)
342{   // second==0 - we assume that first is inline constant, otherwise we check range
343    return (pair.end==0) || cxuint(pair.end-pair.start)==regsNum;
344}
345
346static inline void updateVGPRsNum(cxuint& vgprsNum, cxuint vgpr)
347{
348    vgprsNum = std::min(std::max(vgprsNum, vgpr+1), 256U);
349}
350
351static inline void updateSGPRsNum(cxuint& sgprsNum, cxuint sgpr, uint16_t arch)
352{
353    cxuint maxSGPRsNum = getGPUMaxRegsNumByArchMask(arch, REGTYPE_SGPR);
354    if (sgpr < maxSGPRsNum) /* sgpr=-1 does not change sgprsNum */
355        sgprsNum = std::min(std::max(sgprsNum, sgpr+1), maxSGPRsNum-2);
356}
357
358static inline void updateRegFlags(Flags& regFlags, cxuint reg, uint16_t arch)
359{
360    reg &= ~1;
361    if (reg==106)
362        regFlags |= GCN_VCC;
363    else if (((arch&ARCH_GCN_1_2_4)!=0 && reg==102) ||
364            ((arch&ARCH_GCN_1_2_4)==0 && reg==104))
365        regFlags |= GCN_FLAT;
366    else if ((arch&ARCH_GCN_1_2_4)!=0 && reg==104)
367        regFlags |= GCN_XNACK;
368}
369
370};
371
372#endif
Note: See TracBrowser for help on using the repository browser.