1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2017-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 #ifndef _IGA_BACKEND_GED_DECODER_HPP_
10 #define _IGA_BACKEND_GED_DECODER_HPP_
11 
12 #include "GEDBitProcessor.hpp"
13 #include "GEDToIGATranslation.hpp"
14 #include "ged.h"
15 
16 
17 #define GED_DECODE_TO(FIELD, TRANS, DST) \
18     do { \
19         GED_RETURN_VALUE _status; \
20         DST = TRANS(GED_Get ## FIELD(&m_currGedInst, &_status)); \
21         if (_status != GED_RETURN_VALUE_SUCCESS) { \
22             handleGedDecoderError(__LINE__, #FIELD, _status); \
23         } \
24     } while (0)
25 
26 #define GED_DECODE_RAW_TO(FIELD, DST) \
27     do { \
28         GED_RETURN_VALUE _status; \
29         DST = GED_Get ## FIELD(&m_currGedInst, &_status); \
30         if (_status != GED_RETURN_VALUE_SUCCESS) { \
31             handleGedDecoderError(__LINE__, #FIELD, _status); \
32         } \
33     } while (0)
34 
35 #define GED_DECODE_RAW(GED_TYPE, ID, FIELD) \
36     GED_TYPE ID; \
37     GED_DECODE_RAW_TO(FIELD, ID);
38 
39 #define GED_DECODE(IGA_TYPE, GED_TYPE, ID, FIELD) \
40     GED_DECODE_RAW(GED_TYPE, GED_ ## ID, FIELD); \
41     IGA_TYPE ID = translate(GED_ ## ID);
42 
43 #define GED_DECODE_RAW_TO_SRC(DST, TYPE, FIELD) \
44     do { \
45         GED_RETURN_VALUE _STATUS; \
46         DST = GED_Get ## FIELD(&m_currGedInst, &_STATUS); \
47         if (_STATUS != GED_RETURN_VALUE_SUCCESS) { \
48             handleGedDecoderError(__LINE__, #FIELD, _STATUS); \
49         } \
50     } while (0)
51 
52 #define RETURN_GED_DECODE_RAW_TO_SRC(TYPE, FIELD) { \
53         TYPE _DST; \
54         GED_DECODE_RAW_TO_SRC(_DST, TYPE, FIELD); \
55         return _DST; \
56     }
57 // the extra namespace declaration is needed to make g++ happy
58 #define DEFINE_SOURCE_ACCESSOR(TYPE, FIELD, I) \
59     namespace iga { \
60         template <> TYPE Decoder::decodeSrc ## FIELD <SourceIndex::SRC##I>() { \
61             RETURN_GED_DECODE_RAW_TO_SRC(TYPE, Src ## I ## FIELD); \
62         } \
63     }
64 
65 /* #define DEFINE_SOURCE_ACCESSOR_INLINE(TYPE, FIELD, I) \
66 template <> TYPE decodeSrc ## FIELD <SourceIndex::SRC##I>() { \
67 RETURN_GED_DECODE_RAW_TO_SRC(TYPE, Src ## I ## FIELD); \
68 }
69 */
70 /* #define DEFINE_GED_SOURCE_ACCESSORS_INLINE_01(TYPE, FIELD) \
71 DEFINE_SOURCE_ACCESSOR_INLINE(TYPE, FIELD, 0) \
72 DEFINE_SOURCE_ACCESSOR_INLINE(TYPE, FIELD, 1)
73 */
74 #define DEFINE_GED_SOURCE_ACCESSORS_01(TYPE, FIELD) \
75     DEFINE_SOURCE_ACCESSOR(TYPE, FIELD, 0) \
76     DEFINE_SOURCE_ACCESSOR(TYPE, FIELD, 1)
77 
78 /* #define DEFINE_GED_SOURCE_ACCESSORS_INLINE_012(TYPE, FIELD) \
79 DEFINE_SOURCE_ACCESSOR_INLINE(TYPE, FIELD, 0) \
80 DEFINE_SOURCE_ACCESSOR_INLINE(TYPE, FIELD, 1) \
81 DEFINE_SOURCE_ACCESSOR_INLINE(TYPE, FIELD, 2)
82 */
83 #define DEFINE_GED_SOURCE_ACCESSORS_012(TYPE, FIELD) \
84     DEFINE_SOURCE_ACCESSOR(TYPE, FIELD, 0) \
85     DEFINE_SOURCE_ACCESSOR(TYPE, FIELD, 1) \
86     DEFINE_SOURCE_ACCESSOR(TYPE, FIELD, 2)
87 
88 
89 namespace iga
90 {
91     struct FlagRegInfo {
92         Predication    pred;
93         FlagModifier   modifier;
94         RegRef         reg;
95     };
96     struct DirRegOpInfo {
97         RegName   regName = RegName::INVALID; // e.g. "r" or "acc"
98         RegRef    regRef;  // 13
99         Type      type = Type::INVALID;
100     };
101 
102     class Decoder : public GEDBitProcessor
103     {
104     public:
105         // Constructs a new decoder with an error handler and an empty kernel
106         Decoder(const Model &model, ErrorHandler &errHandler);
107 
108         // the main entry point for decoding a kernel
109         Kernel *decodeKernelBlocks(
110             const void *binary,
111             size_t binarySize);
112         Kernel *decodeKernelNumeric(
113             const void *binary,
114             size_t binarySize);
115 
116         // Set the SWSB endcoding mode, if not set, derived from platform
setSWSBEncodingMode(SWSB_ENCODE_MODE mode)117         void setSWSBEncodingMode(SWSB_ENCODE_MODE mode)
118         {
119             if (mode != SWSB_ENCODE_MODE::SWSBInvalidMode)
120             {
121                 m_SWSBEncodeMode = mode;
122             }
123         }
124 
125         bool isMacro() const;
126 
127     private:
128         Kernel *decodeKernel(
129             const void *binary,
130             size_t binarySize,
131             bool numericLabels);
132 
133         // pass 1 decodes instructions with numeric labels
134         void decodeInstructions(
135             Kernel &kernel,
136             const void *binary,
137             size_t binarySize,
138             InstList &insts);
139         const OpSpec *decodeOpSpec(Op op);
140 
141         Instruction *decodeNextInstruction(Kernel &kernel);
142 
143         void decodeSWSB(Instruction* inst);
144 
145     protected:
146         GED_ACCESS_MODE    decodeAccessMode();
147         MaskCtrl           decodeMaskCtrl();
148         Predication        decodePredication();
149         void               decodePredInv(Predication& pred);
150         FlagRegInfo        decodeFlagRegInfo(bool imm64Src0Overlap = false); // pred, cond, ...
151         ExecSize           decodeExecSize();
152         ChannelOffset      decodeChannelOffset();
153 
154         void decodeJipToSrc(
155             Instruction *inst,
156             SourceIndex s = SourceIndex::SRC0,
157             Type type = Type::INVALID);
158         void               decodeUipToSrc1(Instruction *inst, Type type);
159         int32_t            decodeJip();
160         int32_t            decodeUip();
161 
162         // Reads a source from a the 'fromSrc'th source operand
163         // and creates the operand in IR as 'toSrc'.
164         // Typically this will be used directly as
165         //   createSoureOp(inst, SourceIndex::SRC0, SourceIndex::SRC0);
166         // However, for some operands with implicit operands such as
167         // jmpi, ths will show up as
168         //   createSoureOp(inst, SourceIndex::SRC1, SourceIndex::SRC0);
169         // since the first syntactic source is stored in src1's bits
170         // (src0 is ip for that op)
171 
172         ///////////////////////////////////////////////////////////////////////
173         // BASIC INSTRUCTIONS
174         ///////////////////////////////////////////////////////////////////////
175         Instruction *decodeBasicInstruction(Kernel &kernel);
176         void decodeBasicUnaryInstruction(Instruction *inst, GED_ACCESS_MODE accessMode);
177 
decodeBasicDestination(Instruction * inst,GED_ACCESS_MODE a)178         void decodeBasicDestination(Instruction *inst, GED_ACCESS_MODE a) {
179             if (a == GED_ACCESS_MODE_Align16)
180                 decodeBasicDestinationAlign16(inst);
181             else
182                 decodeBasicDestinationAlign1(inst);
183         }
184         void decodeBasicDestinationAlign16(Instruction *inst); // e.g. for math.invm and context save restore
185         void decodeBasicDestinationAlign1(Instruction *inst);
186         template <SourceIndex S>
decodeSourceBasic(Instruction * inst,GED_ACCESS_MODE a)187         void decodeSourceBasic(Instruction *inst, GED_ACCESS_MODE a) {
188             if (a == GED_ACCESS_MODE_Align16)
189                 decodeSourceBasicAlign16<S>(inst, S);
190             else
191                 decodeSourceBasicAlign1<S>(inst, S);
192         }
193         template <SourceIndex S>
decodeSourceBasic(Instruction * inst,SourceIndex toSrcIx,GED_ACCESS_MODE a)194         void decodeSourceBasic(Instruction *inst, SourceIndex toSrcIx, GED_ACCESS_MODE a) {
195             if (a == GED_ACCESS_MODE_Align16)
196                 decodeSourceBasicAlign16<S>(inst, toSrcIx);
197             else
198                 decodeSourceBasicAlign1<S>(inst, toSrcIx);
199         }
200         template <SourceIndex S>
decodeSourceBasicAlign1(Instruction * inst)201         void decodeSourceBasicAlign1(Instruction *inst) {
202             decodeSourceBasicAlign1<S>(inst, S);
203         }
204         template <SourceIndex S>
decodeSourceBasicAlign16(Instruction * inst)205         void decodeSourceBasicAlign16(Instruction *inst) {
206             decodeSourceBasicAlign16<S>(inst, S);
207         }
208         template <SourceIndex S>
209         void decodeSourceBasicAlign1(Instruction *inst, SourceIndex toSrcIx);
210         template <SourceIndex S>
211         void decodeSourceBasicAlign16(Instruction *inst, SourceIndex toSrcIx);
212 
213 
214         ///////////////////////////////////////////////////////////////////////
215         // TERNARY INSTRUCTIONS
216         ///////////////////////////////////////////////////////////////////////
217         Instruction *decodeTernaryInstruction(Kernel& kernel);
218         void decodeTernaryInstructionOperands(Kernel& kernel, Instruction *inst, GED_ACCESS_MODE accessMode);
219         // Align16
220         void decodeTernaryDestinationAlign16(Instruction *inst);
221         template <SourceIndex S> void decodeTernarySourceAlign16(Instruction *inst);
222         // Align1
223         void decodeTernaryDestinationAlign1(Instruction *inst);
224         template <SourceIndex S> void decodeTernarySourceAlign1(Instruction *inst);
225 
226         ///////////////////////////////////////////////////////////////////////
227         // SEND INSTRUCTIONS
228         ///////////////////////////////////////////////////////////////////////
229         Instruction *decodeSendInstruction(Kernel &kernel);
230         void decodeSendDestination(Instruction *inst);
231         GED_ADDR_MODE decodeSendSource0AddressMode();
232         void decodeSendSource0(Instruction *inst);
233         void decodeSendSource1(Instruction *inst);
234         SendDesc decodeSendExDesc();
235         SendDesc decodeSendDesc();
236 
237         // facilitates internal decoding logic
238         struct SendDescodeInfo {
239             SFID sfid = SFID::INVALID;
240             int dstLen = -1, src0Len = -1, src1Len = -1;
241             bool hasCps = false, hasExBSO = false;
242             SendDesc desc, exDesc;
243         };
244         void decodeSendInfoPreXe(SendDescodeInfo &sdi);
245         void decodeSendInfoXe(SendDescodeInfo &sdi);
246         void decodeSendInfoXeHP(SendDescodeInfo &sdi);
247         void decodeSendInfoXeHPG(SendDescodeInfo &sdi);
248 
249         ///////////////////////////////////////////////////////////////////////
250         // BRANCH INSTRUCTIONS
251         ///////////////////////////////////////////////////////////////////////
252         Instruction *decodeBranchInstruction(Kernel &kernel);
253         Instruction *decodeBranchSimplifiedInstruction(Kernel &kernel);
254         void decodeBranchDestination(Instruction *inst);
255 
256         ///////////////////////////////////////////////////////////////////////
257         // OTHER INSTRUCTIONS
258         ///////////////////////////////////////////////////////////////////////
259         Instruction *decodeWaitInstruction(Kernel &kernel);
260         Instruction *decodeSyncInstruction(Kernel &kernel);
261 
262         ///////////////////////////////////////////////////////////////////////
263         // OTHER HELPERS
264         ///////////////////////////////////////////////////////////////////////
265         void decodeReg(
266             int opIx, // dst => opIx<0
267             GED_REG_FILE regFile,
268             uint32_t regNumBits,
269             RegName &regName,
270             RegRef &regRef);
271 
272 
273         DirRegOpInfo decodeDstDirRegInfo();
274         Type decodeDstType();
275         int decodeDestinationRegNumAccBitsFromChEn();
276         MathMacroExt decodeDestinationMathMacroRegFromChEn();
277 
278         Subfunction decodeSubfunction();
279         bool hasImm64Src0Overlap();
280 
281         void decodeDstDirSubRegNum(DirRegOpInfo& dri);
282         bool hasImplicitScalingType(Type& type, DirRegOpInfo& dri);
283         void decodeNextInstructionEpilog(Instruction *inst);
284 
285         void decodeThreadOptions(Instruction *inst, GED_THREAD_CTRL trdCntrl);
286 
287         template <SourceIndex S> ImmVal decodeTernarySrcImmVal(Type t);
288 
289         // various GED source accessors
290         //some definitions created in Decoder.cpp using macros
291         //i.e. DEFINE_GED_SOURCE_ACCESSORS...
292         template <SourceIndex S> GED_ADDR_MODE    decodeSrcAddrMode();
293 
294 //#define DEFINE_SOURCE_ACCESSOR_INLINE(TYPE, FIELD, I)
295         //template <> GED_ADDR_MODE decodeSrcAddrMode <SourceIndex::SRC0>() {
296         //    RETURN_GED_DECODE_RAW_TO_SRC(GED_ADDR_MODE, Src0AddrMode);
297         //}
298 
299         template <SourceIndex S> GED_REG_FILE     decodeSrcRegFile();
300         template <SourceIndex S> GED_DATA_TYPE    decodeSrcDataType();
301 
302         // register direct fields
303         template <SourceIndex S> uint32_t         decodeSrcRegNum();
304         template <SourceIndex S> uint32_t         decodeSrcSubRegNum();
305         // implicit accumulators
306         template <SourceIndex S> GED_MATH_MACRO_EXT  decodeSrcMathMacroExt();
307 
308         // register indirect fields
309         template <SourceIndex S> int32_t          decodeSrcAddrImm();
310         template <SourceIndex S> uint32_t         decodeSrcAddrSubRegNum();
311         // immediate fields
312         ImmVal                                    decodeSrcImmVal(Type type);
313 
314         // register direct and indirect fields
315         // yeah, the naming convention dictates this name
316         //   (on for Src vs Dst) and one for the field name SrcMod
317         template <SourceIndex S> GED_SRC_MOD      decodeSrcSrcMod();
318 
319 
decodeSrcType()320         template <SourceIndex S> Type decodeSrcType() {
321             return translate(decodeSrcDataType<S>());
322         }
323 
decodeSrcRegionVWH()324         template <SourceIndex S> Region decodeSrcRegionVWH() {
325             return transateGEDtoIGARegion(
326                 decodeSrcVertStride<S>(),
327                 decodeSrcWidth<S>(),
328                 decodeSrcHorzStride<S>());
329         }
330 
331         template <SourceIndex S> Region decodeSrcRegionTernaryAlign1(const OpSpec &);
332 
decodeSrcMathMacroReg()333         template <SourceIndex S> MathMacroExt decodeSrcMathMacroReg() {
334             return translate(decodeSrcMathMacroExt<S>());
335         }
decodeSrcModifier()336         template <SourceIndex S> SrcModifier decodeSrcModifier() {
337             if (m_opSpec->supportsSourceModifiers()) {
338                 return translate(decodeSrcSrcMod<S>());
339             }
340             return SrcModifier::NONE;
341         }
342 
343         // decodes regname, regnum, and subreg num (if applicable)
344         // does *not* scale the subreg num
decodeSourceReg(RegRef & regRef)345         template <SourceIndex S> RegName decodeSourceReg(RegRef &regRef) {
346             uint32_t regNumBits = decodeSrcRegNum<S>();
347             RegName regName = RegName::INVALID;
348             GED_REG_FILE regFile = decodeSrcRegFile<S>();
349             decodeReg((int)S, regFile, regNumBits, regName, regRef);
350             if (!m_opSpec->isSendOrSendsFamily() && !isMacro()) {
351                 regRef.subRegNum = (uint16_t)decodeSrcSubRegNum<S>();
352             } else {
353                 regRef.subRegNum = 0;
354             }
355             return regName;
356         }
357 
decodeSrcDirRegOpInfo()358         template <SourceIndex S> DirRegOpInfo decodeSrcDirRegOpInfo() {
359             DirRegOpInfo dri;
360             dri.regName = decodeSourceReg<S>(dri.regRef);
361 
362             Type scalingType = Type::INVALID;
363             // FIXME: not sure what "hasImplicitScalingType" for, this cause the in-consistent
364             // between encoder and decoder. Still using it to keep it the same as before...
365             if (!hasImplicitScalingType(scalingType, dri)) {
366                 scalingType = dri.type = decodeSrcType<S>();
367             }
368 
369             if (scalingType == Type::INVALID) {
370                 scalingType = Type::UB;
371                 if (m_opSpec->isBranching())
372                     scalingType = Type::D;
373             }
374 
375             dri.regRef.subRegNum = (uint16_t)BinaryOffsetToSubReg(
376                 dri.regRef.subRegNum, dri.regName,
377                 scalingType, m_model.platform);
378 
379             return dri;
380         }
381 
382         template <SourceIndex S> uint32_t         decodeSrcVertStride();
383         template <SourceIndex S> uint32_t         decodeSrcWidth();
384         template <SourceIndex S> uint32_t         decodeSrcHorzStride();
385         template <SourceIndex S> uint32_t         decodeSrcChanSel();
386         template <SourceIndex S> GED_REP_CTRL     decodeSrcRepCtrl();
387         template <SourceIndex S> uint8_t          decodeSrcCtxSvRstAccBitsToRegNum();
388         void decodeChSelToSwizzle(uint32_t chanSel, GED_SWIZZLE swizzle[4]);
389         template <SourceIndex S> bool isChanSelPacked();
390 
391         void decodeOptions(Instruction *inst);
392 
393     protected:
394         GED_MODEL                     m_gedModel;
395 
396         // decode-level state (valid below decodeKernel variants)
397         Kernel                       *m_kernel;
398 
399         // state shared below decodeInstToBlock()
400         // info about the instruction being converted to IGA IR
401         ged_ins_t                     m_currGedInst;
402         const OpSpec                 *m_opSpec;
403         Subfunction                   m_subfunc;
404         const void                   *m_binary;
405 
406         // SWSB encoding mode
407         SWSB_ENCODE_MODE m_SWSBEncodeMode = SWSB_ENCODE_MODE::SWSBInvalidMode;
408 
409         // for GED workarounds: grab specific bits from the current instruction
410         uint32_t getBitField(int ix, int len) const;
411 
412         // helper for inserting instructions for decode errors
413         Instruction *createErrorInstruction(
414             Kernel &kernel,
415             const char *message,
416             const void *binary,
417             int32_t iLen);
418 
419         // used by the GED_DECODE macros
420         void handleGedDecoderError(
421             int line,
422             const char *field,
423             GED_RETURN_VALUE status);
424     }; // end class Decoder
425 
426 
427 
428 } //end: namespace iga*
429 
430 namespace iga
431 {
432     typedef Decoder Decoder;
433 }
434 
435 #endif //end: _IGA_DECODER_H_
436