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 IS_RELEASE_DLL
10 
11 #include "Common_ISA.h"
12 #include "Common_ISA_util.h"
13 
14 #include "VISADefines.h"
15 #include "IsaVerification.h"
16 
17 #include "IsaDisassembly.h"
18 #include "PreDefinedVars.h"
19 #include "Attributes.hpp"
20 
21 #include "G4_IR.hpp"
22 /* stdio.h portability code start */
23 #ifdef _WIN32
24 #else
25 #define _scprintf(...) \
26     snprintf(NULL, 0, __VA_ARGS__)
27 #endif
28 
29 #include <iostream>
30 #include <sstream>
31 #include <string>
32 #include <limits>
33 
34 using namespace vISA;
35 
36 #define REPORT_HEADER(opt, cond, ...)          \
37 do if (!(cond)) {                              \
38     int sz = _scprintf(__VA_ARGS__) + 1;       \
39     char* buf = (char*)malloc(sz);             \
40     assert(buf != NULL);                       \
41     memset(buf, 0, sz);                        \
42     SNPRINTF(buf, sz, __VA_ARGS__);            \
43     error_list.push_back(createIsaError(       \
44         isaHeader, header, std::string(buf), opt)); \
45     free(buf);                                 \
46 } while (0)
47 
48 
49 #define REPORT_INSTRUCTION(opt, cond, ...)           \
50 do if (!(cond)) {                                    \
51     int sz = _scprintf(__VA_ARGS__) + 1;             \
52     char* buf = (char*)malloc(sz);                   \
53     assert(buf != NULL);                             \
54     memset(buf, 0, sz);                              \
55     SNPRINTF(buf, sz, __VA_ARGS__);                  \
56     error_list.push_back(createIsaError(             \
57         isaHeader, header, std::string(buf), opt, inst)); \
58     free(buf);                                       \
59 } while (0)
60 
toString() const61 std::string raw_opnd::toString() const
62 {
63     std::stringstream sstr;
64     sstr << "V" << index;
65     if (offset != 0)
66     {
67         sstr << "." << offset;
68     }
69     return sstr.str();
70 }
71 
writeReport(const char * filename)72 void vISAVerifier::writeReport(const char* filename)
73 {
74     if (kerror_list.size() > 0 || error_list.size() > 0)
75     {
76         std::ofstream report;
77         report.open(filename);
78 
79         if (kerror_list.size() > 0)
80         {
81             report << "Kernel Header / Declare Errors:\n";
82             for (auto I = kerror_list.begin(), E = kerror_list.end(); I != E; I++)
83                 report << (*I) << "\n";
84             report << "\n\n\n";
85         }
86 
87         report << "Instruction / Operand / Region Errors:\n";
88 
89         for (auto I = error_list.begin(), E = error_list.end(); I != E; I++)
90             report << (*I) << "\n";
91 
92         report << "\n\n\n";
93         report.close();
94     }
95 }
96 
getDstIndex(const CISA_INST * inst)97 static int getDstIndex(const CISA_INST* inst)
98 {
99     ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
100     int dstIndex = -1;
101     if (inst->opnd_count > 0)
102     {
103         switch (ISA_Inst_Table[opcode].type)
104         {
105             case ISA_Inst_Mov:
106             case ISA_Inst_Arith:
107             case ISA_Inst_Logic:
108             case ISA_Inst_Address:
109                  dstIndex = 0;
110                  break;
111             case ISA_Inst_Compare:
112                  dstIndex = 1;
113                  break;
114             default:
115                  break; // Prevent gcc warning
116         }
117     }
118     return dstIndex;
119 }
120 
121 // diagDumpInstructionOperandDecls() is used to generate the error report
diagDumpInstructionOperandDecls(const common_isa_header & isaHeader,const print_format_provider_t * header,const CISA_INST * inst,Options * options)122 static std::string diagDumpInstructionOperandDecls(
123     const common_isa_header& isaHeader,
124     const print_format_provider_t* header,
125     const CISA_INST* inst,
126     Options *options)
127 {
128     std::stringstream sstr;
129 
130     unsigned numPreDefinedVars = Get_CISA_PreDefined_Var_Count();
131 
132     for (unsigned i = 0; i < inst->opnd_count; i++)
133     {
134         if (inst->opnd_array[i]->opnd_type == CISA_OPND_VECTOR)
135         {
136             const vector_opnd& opnd = getVectorOperand(inst, i);
137             uint32_t index = opnd.getOperandIndex();
138 
139             if (numPreDefinedVars <= index && index < header->getVarCount())
140             switch (opnd.getOperandClass())
141             {
142                 case OPERAND_STATE     :
143                 case OPERAND_GENERAL   : sstr << printVariableDecl  (header, index-numPreDefinedVars, options); break;
144                 case OPERAND_ADDRESS   :
145                 case OPERAND_INDIRECT  : sstr << printAddressDecl   (isaHeader, header, index); break;
146                 case OPERAND_PREDICATE : sstr << printPredicateDecl (header, index); break;
147                 case OPERAND_ADDRESSOF : sstr << "ADDRESSOF Operand decl... are those even allowed>\n"; break;
148                 case OPERAND_IMMEDIATE : sstr << "Immediate operand: " << getPrimitiveOperand<unsigned>(inst, i) << "\n"; break;
149                 default                : sstr << "Operand type: " << opnd.getOperandClass() << " unable to print." << "\n"; break;
150             }
151         }
152         else if (inst->opnd_array[i]->opnd_type == CISA_OPND_RAW)
153         {
154             uint32_t index = getRawOperand(inst, i).index;
155             if (numPreDefinedVars <= index && index < header->getVarCount() + numPreDefinedVars)
156                 sstr << printVariableDecl(header, index-numPreDefinedVars, options);
157         }
158         else if (inst->opnd_array[i]->opnd_type == CISA_OPND_OTHER) // new loader only
159         {
160         }
161         else
162         {
163             sstr << "unknown operand?";
164         }
165 
166         sstr << "\n";
167         if (i != inst->opnd_count-1)
168             sstr << std::setw(33) << "                               ";
169     }
170 
171     return sstr.str();
172 }
173 
createIsaError(const common_isa_header & isaHeader,const print_format_provider_t * header,std::string msg,Options * opt,const CISA_INST * inst=NULL)174 static std::string createIsaError(
175     const common_isa_header& isaHeader,
176     const print_format_provider_t* header,
177     std::string msg,
178     Options *opt,
179     const CISA_INST* inst = NULL)
180 {
181     std::stringstream sstr;
182     if (!inst)
183     sstr << "\n/-------------------------------------------!!!KERNEL HEADER ERRORS FOUND!!!-------------------------------------------\\\n";
184     else
185     sstr << "\n/--------------------------------------------!!!INSTRUCTION ERROR FOUND!!!---------------------------------------------\\\n";
186     sstr << std::setw(33) << "Error in CISA routine with name: " << (char*)header->getString(header->getNameIndex()) << "\n";
187     sstr << std::setw(33) << "Error Message: " << msg << "\n";
188 
189     if (NULL != inst)
190     {
191         sstr << std::setw(33) << "Diagnostics:\n";
192         sstr << std::setw(33) << " Instruction variables' decls: ";
193         sstr << diagDumpInstructionOperandDecls(isaHeader, header, inst, opt) << "\n";
194         sstr << std::setw(33) << " Violating Instruction: "  << printInstruction(header, inst, opt) << "\n";
195     }
196 
197     sstr << "\\----------------------------------------------------------------------------------------------------------------------/\n";
198     return sstr.str();
199 }
200 
201 // If region/offset is available, return true; otherwise, return false.
getRegion(const vector_opnd & VecOpnd,uint16_t & row_offset,uint16_t & col_offset,uint16_t & v_stride,uint16_t & width,uint16_t & h_stride) const202 bool vISAVerifier::getRegion(const vector_opnd& VecOpnd,
203     uint16_t& row_offset, uint16_t& col_offset,
204     uint16_t& v_stride, uint16_t& width, uint16_t& h_stride) const
205 {
206     Common_ISA_Operand_Class operand_class = VecOpnd.getOperandClass();
207 
208     uint16_t region = 0;
209     row_offset = 0;
210     col_offset = 0;
211 
212     switch (operand_class)
213     {
214     case OPERAND_GENERAL:
215         region = VecOpnd.opnd_val.gen_opnd.region;
216         row_offset = VecOpnd.opnd_val.gen_opnd.row_offset;
217         col_offset = VecOpnd.opnd_val.gen_opnd.col_offset;
218         break;
219     case OPERAND_INDIRECT:
220         region = VecOpnd.opnd_val.indirect_opnd.region;
221         break;
222     default:
223         return false;
224     }
225 
226     Common_ISA_Region_Val w = (Common_ISA_Region_Val)((region >> 4) & 0xF);
227     Common_ISA_Region_Val h = (Common_ISA_Region_Val)((region >> 8) & 0xF);
228     Common_ISA_Region_Val v = (Common_ISA_Region_Val)((region) & 0xF);
229 
230     v_stride = Common_ISA_Get_Region_Value(v);
231     h_stride = Common_ISA_Get_Region_Value(h);
232     width = Common_ISA_Get_Region_Value(w);
233     return true;
234 }
235 
getOperandVISAType(const CISA_INST * I,unsigned Ix) const236 VISA_Type vISAVerifier::getOperandVISAType(const CISA_INST* I, unsigned Ix) const
237 {
238     switch (getOperandType(I, Ix))
239     {
240     case CISA_OPND_VECTOR:
241     {
242         const vector_opnd& vec_opnd = getVectorOperand(I, Ix);
243         return getVectorOperandType(header, vec_opnd);
244     }
245     case CISA_OPND_RAW:
246     {
247         const raw_opnd& raw_opnd = getRawOperand(I, Ix);
248         return getRawOperandType(header, raw_opnd);
249     }
250     default:
251         break;
252     }
253     return ISA_TYPE_NUM;
254 }
255 
256 // If any of I's operands uses the GivenType, return true; otherwise, return false.
useGivenVISAType(const CISA_INST * I,VISA_Type GivenType) const257 bool vISAVerifier::useGivenVISAType(const CISA_INST* I, VISA_Type GivenType) const
258 {
259     ISA_Opcode opc = (ISA_Opcode)I->opcode;
260     int ndst = (int)ISA_Inst_Table[opc].n_dsts;
261     if (opc == ISA_CMP)
262     {
263         // cmp's 1st opnd is cmp relop, which returns ISA_TYPE_NUM as its type.
264         // Thus, it is ignored as expected.
265         ++ndst;
266     }
267     for (int j = 0; j < ndst; j++)
268     {
269         VISA_Type dstType = getOperandVISAType(I, j);
270         if (dstType == GivenType)
271             return true;
272     }
273     for (int j = 0; j < ISA_Inst_Table[opc].n_srcs; j++)
274     {
275         VISA_Type srcType = getOperandVISAType(I, j + ndst);
276         if (srcType == GivenType)
277             return true;
278     }
279     return false;
280 }
281 
verifyPredicateDecl(unsigned declID)282 void vISAVerifier::verifyPredicateDecl(unsigned declID)
283 {
284     std::string declError =
285         std::string(" Error in predicate variable decl: ") + printPredicateDecl(header, declID);
286 
287     REPORT_HEADER(options,header->getPred(declID)->name_index < header->getStringCount(), "P%d's name index(%d) is not valid: %s", declID, header->getPred(declID)->name_index, declError.c_str());
288 
289     switch (header->getPred(declID)->num_elements)
290     {
291         case 1:
292         case 2:
293         case 4:
294         case 8:
295         case 16:
296         case 32:
297             break;
298         default:
299             REPORT_HEADER(options,false, "P%d's number of elements(%d) is not valid: %s", declID, header->getPred(declID)->num_elements, declError.c_str());
300     }
301 }
302 
verifyAddressDecl(unsigned declID)303 void vISAVerifier::verifyAddressDecl(unsigned declID)
304 {
305     std::string declError = std::string(" Error in address variable decl: ") +
306         printAddressDecl(isaHeader, header, declID);
307 
308     REPORT_HEADER(options,header->getAddr(declID)->name_index < header->getStringCount(), "A%d's name index(%d) is not valid: %s", declID, header->getAddr(declID)->name_index, declError.c_str());
309     REPORT_HEADER(options,header->getAddr(declID)->num_elements <= 16, "Max possible address registers are 16 on BDW+: %s", declError.c_str());
310 
311     /// TODO: Fix/Reenable this verification check.
312     #if 0
313     switch (header->getAddr(declID)->num_elements)
314     {
315         case 1:
316         case 2:
317         case 4:
318         case 8:
319         case 16:
320             break;
321         default:
322             REPORT_HEADER(options,false, "A%d's number of elements(%d) is not valid.", declID, header->getAddr(declID)->num_elements);
323     }
324     #endif
325 }
326 
verifyVariableDecl(unsigned declID)327 void vISAVerifier::verifyVariableDecl(
328     unsigned declID)
329 {
330     std::string declError = std::string(" Error in CISA variable decl: ") +
331         printVariableDecl(header, declID, options);
332 
333     const var_info_t* var = header->getVar(declID);
334     VISA_Align align = var->getAlignment();
335 
336     unsigned numPreDefinedVars = Get_CISA_PreDefined_Var_Count();
337 
338     REPORT_HEADER(options, var->name_index < header->getStringCount(),
339                   "V%d's name index(%d) is not valid: %s",
340                   declID + numPreDefinedVars, var->name_index,
341                   declError.c_str());
342 
343     switch (var->getType())
344     {
345         case ISA_TYPE_V:
346         case ISA_TYPE_VF:
347         case ISA_TYPE_BOOL:
348         case ISA_TYPE_UV:
349             REPORT_HEADER(options,false, "V%d's type(%s) is not legal: %s", declID, CISATypeTable[var->getType()].typeName, declError.c_str());
350             return;
351         default:
352             break; // Prevent gcc warning
353     }
354 
355     REPORT_HEADER(options, var->num_elements != 0 && var->num_elements <= COMMON_ISA_MAX_VARIABLE_SIZE,
356                   "V%d's number of elements(%d) is out of range: %s",
357                   declID + numPreDefinedVars, var->num_elements,
358                   declError.c_str());
359     REPORT_HEADER(options, !(var->alias_index == 0 && var->alias_offset != 0),
360                   "V%d's alias offset must be zero when it is not aliased: %s",
361                   declID + numPreDefinedVars, declError.c_str());
362 
363     if (var->alias_index >= numPreDefinedVars)
364     {
365         const var_info_t* currAliasVar = header->getVar(var->alias_index-numPreDefinedVars);
366         unsigned totalOffset = var->alias_offset;
367 
368         std::set<uint32_t> visitedAliasIndices;
369 
370         while (currAliasVar->alias_index >= numPreDefinedVars)
371         {
372             if (visitedAliasIndices.find(currAliasVar->alias_index) != visitedAliasIndices.end())
373             {
374                 REPORT_HEADER(options,false, "Circular alias detected, alias index: %d", currAliasVar->alias_index);
375                 break;
376             }
377 
378             visitedAliasIndices.insert(currAliasVar->alias_index);
379 
380             REPORT_HEADER(options,currAliasVar->alias_index < header->getVarCount() + numPreDefinedVars,
381                               "Aliased variable aliases to an invalid alias index. "
382                               "Variable count: %d. invalid index: %d. %s",
383                               header->getVarCount() + numPreDefinedVars,
384                               currAliasVar->alias_index, declError.c_str());
385 
386             totalOffset += currAliasVar->alias_offset;
387             currAliasVar = header->getVar(currAliasVar->alias_index-numPreDefinedVars);
388         }
389 
390         if (currAliasVar->alias_index < header->getVarCount() + numPreDefinedVars)
391         {
392             REPORT_HEADER(options,totalOffset < (currAliasVar->num_elements * (unsigned)CISATypeTable[currAliasVar->getType()].typeSize),
393                               "Variable decl's alias offset exceeds the bounds of the aliased variable decl allocation size: %s", declError.c_str());
394             VISA_Align baseAlign = std::max(currAliasVar->getAlignment(), currAliasVar->getTypeAlignment());
395             REPORT_HEADER(options, baseAlign >= var->getTypeAlignment(),
396                 "base variable must be at least type-aligned to this variable: %s", declError.c_str());
397         }
398     }
399 
400     switch (align)
401     {
402         case ALIGN_BYTE:
403             break;
404         case ALIGN_WORD:
405             break;
406         case ALIGN_DWORD:
407             break;
408         case ALIGN_QWORD:
409             break;
410         case ALIGN_OWORD:
411             break;
412         case ALIGN_GRF:
413             break;
414         case ALIGN_2_GRF:
415             break;
416         case ALIGN_HWORD:
417             break;
418         case ALIGN_32WORD:
419             break;
420         case ALIGN_64WORD:
421             break;
422         default:
423             REPORT_HEADER(options,false, "V%d's variable alignment is not a valid alignment value: %s", declID, declError.c_str());
424     }
425 
426     REPORT_HEADER(options, !(var->alias_index != 0 &&
427                              var->alias_index >=
428                                  header->getVarCount() + numPreDefinedVars),
429                   "V%d's alias index must point to a valid CISA variable index "
430                   "between 0 and %d. Currently points to invalid index V%d: %s",
431                   declID + numPreDefinedVars,
432                   header->getVarCount() + numPreDefinedVars - 1,
433                   var->alias_index, declError.c_str());
434 
435     /// INFO: Got rid of this verification check a long time ago.
436     ///       Checking for unused variables is not that important
437     ///       and it made it a lot simpler for refactoring to just
438     ///       get rid of code that did the analysis required for it.
439     #if 0
440     REPORT_HEADER(options,m_used, "V%d is an unused variable in the CISA bytecode. Find out why it is declared.", declID);
441     #endif
442 }
443 
444 // get the start byte offset from the top level declare
getStartByteOffset(const print_format_provider_t * header,const var_info_t * var,unsigned int numPredefinedVars)445 static unsigned int getStartByteOffset(
446     const print_format_provider_t* header,
447     const var_info_t* var,
448     unsigned int numPredefinedVars)
449 {
450     unsigned int offset = 0;
451     while (var->alias_index != 0)
452     {
453         offset += var->alias_offset;
454         if (var->alias_index <= numPredefinedVars)
455         {
456             // predefined variables don't have aliases, so we can stop
457             break;
458         }
459         else
460         {
461             var = header->getVar(var->alias_index-numPredefinedVars);
462         }
463     }
464     return offset;
465 }
466 
verifyRegion(const CISA_INST * inst,unsigned i)467 void vISAVerifier::verifyRegion(
468     const CISA_INST* inst,
469     unsigned i)
470 {
471     ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
472     /// Dataport instructions must be verified separately
473     if (ISA_Inst_Data_Port == ISA_Inst_Table[opcode].type) return;
474 
475     ASSERT_USER(inst->opnd_array[i]->opnd_type == CISA_OPND_VECTOR, "Should only be verifying region on a vector operand");
476     const vector_opnd& vect = getVectorOperand(inst, i);
477 
478     uint32_t                 operand_index    = vect.getOperandIndex();
479     Common_ISA_Operand_Class operand_class    = vect.getOperandClass();
480 
481     unsigned dstIndex = getDstIndex(inst);
482 
483     unsigned numPreDefinedVars = Get_CISA_PreDefined_Var_Count();
484 
485     uint16_t region     = 0;
486     uint8_t  row_offset = 0;
487     uint8_t  col_offset = 0;
488 
489     switch (operand_class)
490     {
491         case OPERAND_GENERAL:
492             region     = vect.opnd_val.gen_opnd.region;
493             row_offset = vect.opnd_val.gen_opnd.row_offset;
494             col_offset = vect.opnd_val.gen_opnd.col_offset;
495             break;
496         case OPERAND_INDIRECT:
497             region = vect.opnd_val.indirect_opnd.region;
498             break;
499         default:
500             return;
501     }
502 
503     Common_ISA_Region_Val width    = (Common_ISA_Region_Val)((region >> 4) & 0xF);
504     Common_ISA_Region_Val h_stride = (Common_ISA_Region_Val)((region >> 8) & 0xF);
505     Common_ISA_Region_Val v_stride = (Common_ISA_Region_Val)((region    ) & 0xF);
506 
507     short v_stride_val = Common_ISA_Get_Region_Value(v_stride);
508     short h_stride_val = Common_ISA_Get_Region_Value(h_stride);
509     short width_val    = Common_ISA_Get_Region_Value(width  );
510 
511     /// INFO: Catch zero width, because we'll sigsegv otherwise.
512     REPORT_INSTRUCTION(options,width_val, "CISA region has width of 0");
513 
514     uint8_t exec_sz = 0;
515     switch (inst->getExecSize())
516     {
517     case EXEC_SIZE_1:  exec_sz = 1;  break;
518     case EXEC_SIZE_2:  exec_sz = 2;  break;
519     case EXEC_SIZE_4:  exec_sz = 4;  break;
520     case EXEC_SIZE_8:  exec_sz = 8;  break;
521     case EXEC_SIZE_16: exec_sz = 16; break;
522     case EXEC_SIZE_32: exec_sz = 32; break;
523     default: REPORT_INSTRUCTION(options, false, "Invalid execution size");
524     }
525 
526     if (i == dstIndex)
527     {
528         REPORT_INSTRUCTION(options,0 != h_stride_val, "Horizontal Stride should not be 0 for a destination operand.");
529 
530         // for dst set width = exec size and vstride = width * hstride, so their bound can be verified
531         width_val = exec_sz;
532         v_stride_val = width_val * h_stride_val;
533     }
534 
535     if (width_val == 0)
536     {
537         return;
538     }
539 
540     REPORT_INSTRUCTION(options,h_stride != REGION_NULL, "Horizontal Stride should not be REGION_NULL");
541 
542     switch (h_stride_val)
543     {
544         case 0:
545         case 1:
546         case 2:
547         case 4:
548             break;
549         default: REPORT_INSTRUCTION(options,false, "Legal CISA region horizontal stride parameter values: {0, 1, 2, 4}.");
550     }
551 
552     if (width != REGION_NULL)
553     {
554         switch (width_val)
555         {
556         case 1:
557         case 2:
558         case 4:
559         case 8:
560         case 16:
561             break;
562         default: REPORT_INSTRUCTION(options,false, "Legal CISA region width parameter values: {1, 2, 4, 8, 16}.");
563         }
564 
565         REPORT_INSTRUCTION(options,exec_sz >= width_val, "Execution size must be greater than width.");
566         if (exec_sz < width_val)
567         {
568             // no point in continuing verifiication
569             return;
570         }
571     }
572 
573     if (v_stride != REGION_NULL)
574     {
575         switch (v_stride_val)
576         {
577         case 0:
578         case 1:
579         case 2:
580         case 4:
581         case 8:
582         case 16:
583         case 32:
584             break;
585         default: REPORT_INSTRUCTION(options,false, "Legal CISA region vertical stride parameter values: {0, 1, 2, 4, 8, 16, 32}.");
586         }
587     }
588     else if (dstIndex != i)
589     {
590         // check for out-of-bound addresses for VxH operand
591         int numAddr = exec_sz / width_val;
592         REPORT_INSTRUCTION(options, numAddr <= 16, "Number of Address for indirect operand exceeds 16");
593     }
594 
595     if (operand_index >= numPreDefinedVars)
596         if (operand_class == OPERAND_GENERAL)
597         {
598             const var_info_t*      var      = header->getVar(vect.getOperandIndex()-numPreDefinedVars);
599             VISA_Type  isa_type = getVectorOperandType(header, vect);
600             unsigned         VN_size  = CISATypeTable[isa_type].typeSize;
601 
602             uint16_t num_elements = var->num_elements;
603             unsigned var_size = VN_size * num_elements;
604 
605             unsigned last_region_elt_byte;
606             if (width_val != -1)
607             {
608                 unsigned last_region_element = (((exec_sz / width_val) - 1) * v_stride_val) +
609                     ((width_val - 1) * h_stride_val);
610                 last_region_elt_byte = (last_region_element * VN_size) + VN_size - 1;
611             }
612             else
613             {
614                 // DstRegRegion with width 0 (width_val=-1)
615                 last_region_elt_byte =
616                     (exec_sz - 1) * h_stride_val * VN_size + VN_size - 1;
617             }
618 
619             // Check if the operand may touch more than 2 GRFs due to bad alignment
620             // So far vISA is able to handle the splitting of:
621             // moves, logic, cmp and arithmetic instructions
622             if (ISA_Inst_Table[opcode].type != ISA_Inst_Mov &&
623                 ISA_Inst_Table[opcode].type != ISA_Inst_Logic &&
624                 ISA_Inst_Table[opcode].type != ISA_Inst_Compare &&
625                 ISA_Inst_Table[opcode].type != ISA_Inst_Arith)
626             {
627                 REPORT_INSTRUCTION(options, (COMMON_ISA_GRF_REG_SIZE * 2u) > last_region_elt_byte,
628                     "CISA operand region access out of 2 GRF boundary (within %d bytes): %d",
629                     (COMMON_ISA_GRF_REG_SIZE * 2),
630                     last_region_elt_byte);
631 
632                 // check if the operand may touch more than 2 GRFs due to bad alignment
633                 unsigned startByte = getStartByteOffset(header, var, numPreDefinedVars) +
634                     row_offset * COMMON_ISA_GRF_REG_SIZE +
635                     col_offset * CISATypeTable[var->getType()].typeSize;
636                 unsigned endByte = startByte + last_region_elt_byte;
637                 unsigned startGRF = startByte / COMMON_ISA_GRF_REG_SIZE;
638                 unsigned endGRF = endByte / COMMON_ISA_GRF_REG_SIZE;
639                 REPORT_INSTRUCTION(options, endGRF == startGRF || endGRF == (startGRF + 1),
640                     "CISA operand accesses more than 2 GRF due to mis-alignment: start byte offset = %d, end byte offset = %d",
641                     startByte, endByte);
642             }
643 
644             unsigned firstElementIndex = row_offset * COMMON_ISA_GRF_REG_SIZE + col_offset;
645 
646             for (int i = 0; i < exec_sz / width_val; i++)
647             {
648                 for (int j = 0; j < width_val; j++)
649                 {
650                     unsigned region_offset = firstElementIndex +
651                         (((i * v_stride_val)  + (j * h_stride_val)) * VN_size);
652 
653                     if (region_offset > var_size)
654                     {
655 #ifndef DLL_MODE
656                         std::cout << "WARNING: CISA region and offset cause an out of bounds byte access: "<< region_offset << "\n";
657                         std::cout << "An access should not exceed the declared allocation size: " << var_size << "\n";
658                         std::cout << "  The access fails the following check to determine correct bounds (see CISA manual section 5.1 Region-based Addressing):\n";
659                         std::cout << "  (row_offset * GRF_SIZE + col_offset) + (((i * v_stride) + (j * h_stride)) * type_size) <= type_size * num_elements:\n";
660                         std::cout << "(" << (int)row_offset << " * "<< COMMON_ISA_GRF_REG_SIZE << " + "<< (int)col_offset << ") + (((" <<
661                             i << " * " << v_stride_val <<") + (" << j <<" * " << h_stride_val << ")) * " << VN_size <<
662                             ") <= " << VN_size << " * " << num_elements << "\n";
663                         std::cout << "Violating Instruction: " <<
664                             printInstruction(header, inst, options) << "\n";
665 #endif // DLL_MODE
666                     }
667                 }
668             }
669         }
670 
671 }
672 
isDWordType(VISA_Type type)673 static bool isDWordType(VISA_Type type)
674 {
675     return CISATypeTable[type].typeSize == 4;
676 }
677 
678 // verify if this raw operand has the correct type as determined by typeFunc (false means illegal type)
679 // Many vISA messages require the raw operand to have certain types
verifyRawOperandType(const CISA_INST * inst,const raw_opnd & opnd,bool (* typeFunc)(VISA_Type))680 void vISAVerifier::verifyRawOperandType(
681     const CISA_INST* inst,
682     const raw_opnd& opnd,
683     bool (*typeFunc)(VISA_Type))
684 {
685     unsigned numPreDefinedVars = Get_CISA_PreDefined_Var_Count();
686     uint32_t variable_count    = header->getVarCount();
687 
688     uint32_t opnd_index  = opnd.index;
689 
690     if (opnd_index < variable_count + numPreDefinedVars &&
691         numPreDefinedVars <= opnd_index)
692     {
693         const var_info_t* currVar = header->getVar(opnd_index-numPreDefinedVars);
694         REPORT_INSTRUCTION(options,typeFunc(currVar->getType()), "Raw Operand %s has incorrect type %s",
695             opnd.toString().c_str(), CISATypeTable[currVar->getType()].typeName);
696     }
697 }
698 
verifyRawOperand(const CISA_INST * inst,unsigned i)699 void vISAVerifier::verifyRawOperand(
700     const CISA_INST* inst, unsigned i)
701 {
702     unsigned numPreDefinedVars = Get_CISA_PreDefined_Var_Count();
703     uint32_t variable_count    = header->getVarCount();
704 
705     const raw_opnd& opnd = getRawOperand(inst, i);
706 
707     if (numPreDefinedVars > opnd.index)
708     {
709         return; // allow raw operands to be predefined variables
710     }
711 
712     uint32_t opnd_index  = opnd.index - numPreDefinedVars;
713     uint16_t opnd_offset = opnd.offset;
714 
715 
716     if (opnd_index < variable_count)
717     {
718         const var_info_t* currVar = header->getVar(opnd_index);
719         unsigned totalOffset = opnd_offset;
720 
721         std::set<uint32_t> visitedAliasIndices;
722 
723         while (numPreDefinedVars <= currVar->alias_index)
724         {
725             if (visitedAliasIndices.find(currVar->alias_index) != visitedAliasIndices.end())
726             {
727                 REPORT_INSTRUCTION(options,false, "Circular alias detected, alias index: %d", currVar->alias_index);
728                 break;
729             }
730 
731             visitedAliasIndices.insert(currVar->alias_index);
732 
733             REPORT_INSTRUCTION(options,currVar->alias_index < variable_count + numPreDefinedVars,
734                               "Aliased variable aliases to an invalid alias index. "
735                               "Variable count: %d. invalid index: %d",
736                               variable_count + numPreDefinedVars,
737                               currVar->alias_index);
738 
739             totalOffset += currVar->alias_offset;
740             if (numPreDefinedVars > currVar->alias_index)
741             {
742                 break; // // allow alias index to be predefined variables
743             }
744             currVar = header->getVar(currVar->alias_index-numPreDefinedVars);
745         }
746 
747         if (currVar->getSize() >= numEltPerGRF<Type_UB>() && totalOffset % numEltPerGRF<Type_UB>() != 0)
748         {
749             // raw operand must be GRF-aligned if it's >= 1GRF
750             REPORT_INSTRUCTION(options,false, "Raw operand should be GRF-aligned: Raw offset is %d", totalOffset);
751         }
752 
753         if (numPreDefinedVars <= currVar->alias_index)
754         {
755             REPORT_INSTRUCTION(options,totalOffset < currVar->num_elements * (unsigned)CISATypeTable[currVar->getType()].typeSize,
756                     "A CISA raw operand's offset field must be within the allocated operand size. "
757                     "Raw offset is %d, allocated number of elements is %d",
758                     (int)opnd_offset, (int)currVar->num_elements);
759         }
760     }
761     else
762     {
763         /// TODO: Verify predefined vars.
764     }
765 }
766 
isReadWritePreDefinedVar(const common_isa_header & isaHeader,uint32_t index,uint32_t byteOffset)767 static bool isReadWritePreDefinedVar(
768     const common_isa_header& isaHeader, uint32_t index, uint32_t byteOffset)
769 {
770     PreDefinedVarsInternal internalIndex = mapExternalToInternalPreDefVar(index);
771     if (internalIndex == PreDefinedVarsInternal::ARG ||   internalIndex == PreDefinedVarsInternal::RET || internalIndex == PreDefinedVarsInternal::FE_SP ||
772         internalIndex == PreDefinedVarsInternal::FE_FP || internalIndex == PreDefinedVarsInternal::CR0 || internalIndex == PreDefinedVarsInternal::DBG ||
773         internalIndex == PreDefinedVarsInternal::VAR_NULL)
774     {
775         return true;
776     }
777     else if (internalIndex == PreDefinedVarsInternal::TSC && byteOffset == 16)
778     {
779         // tm0.4
780         return true;
781     }
782     else if (internalIndex == PreDefinedVarsInternal::SR0 && (byteOffset == 8 || byteOffset == 12))
783     {
784         // sr0.2, sr0.3
785         return true;
786     }
787     else
788     {
789         return false;
790     }
791 }
792 
verifyVectorOperand(const CISA_INST * inst,unsigned i)793 void vISAVerifier::verifyVectorOperand(
794     const CISA_INST* inst,
795     unsigned i)
796 {
797     unsigned numPreDefinedVars = Get_CISA_PreDefined_Var_Count();
798 
799     ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
800 
801     const vector_opnd& opnd = getVectorOperand(inst, i);
802 
803     uint32_t                 operand_index    = opnd.getOperandIndex();
804     Common_ISA_Operand_Class operand_class    = opnd.getOperandClass();
805     VISA_Modifier      operand_modifier = opnd.getOperandModifier();
806 
807 
808     unsigned dstIndex = getDstIndex(inst);
809 
810     if (inst->opnd_count <= 0)
811     {
812         REPORT_INSTRUCTION(options,false, "Incorrect number of operands loaded.");
813         return;
814     }
815 
816     if (operand_class != OPERAND_GENERAL && operand_class != OPERAND_INDIRECT)
817     {
818         REPORT_INSTRUCTION(options,operand_modifier == MODIFIER_NONE,
819                           "Operand modifier for non-general and "
820                           "non-indirect operands must be MODIFIER_NONE.");
821     }
822 
823     switch (operand_modifier)
824     {
825         case MODIFIER_ABS:
826         case MODIFIER_NEG:
827         case MODIFIER_SAT:
828         case MODIFIER_NEG_ABS:
829              if (!isShiftOp(opcode))
830              {
831                  REPORT_INSTRUCTION(options,ISA_Inst_Table[opcode].type != ISA_Inst_Logic,
832                                    "Only arithmetic modifiers should be used with "
833                                    "arithmetic instruction general or indirect operands.");
834              }
835              break;
836         case MODIFIER_NOT:
837              REPORT_INSTRUCTION(options,ISA_Inst_Table[opcode].type == ISA_Inst_Logic,
838                                "Only logical modifiers should be used with "
839                                "logical instruction general or indirect operands.");
840              break;
841         default:
842             break; // Prevent gcc warning
843     }
844 
845     if (operand_class == OPERAND_IMMEDIATE)
846     {
847         /// Do checks for immediate operands here
848         REPORT_INSTRUCTION(options,getVectorOperandType(header, opnd) != ISA_TYPE_BOOL,
849             "Boolean types for immediate (constant literals) operands are disallowed.");
850     }
851 
852     if (operand_class == OPERAND_GENERAL)
853     {
854         REPORT_INSTRUCTION(options,operand_index < header->getVarCount() + numPreDefinedVars, "Variable V%d is not declaired in CISA symtab.", operand_index);
855 
856         if (operand_index < header->getVarCount() + numPreDefinedVars &&
857             numPreDefinedVars <= operand_index)
858         {
859             //var_info_t* var = &header->variables[operand_index-numPreDefinedVars];
860             /// do some var verifications here.
861 
862             //VISA_Type isa_type_decl = (VISA_Type)((var->bit_properties) & 0xF);
863             //VISA_Type isa_type_var  = getVectorOperandType(isaHeader, header, opnd);
864 
865         }
866     }
867 
868     verifyRegion(inst, i);
869 
870     if (dstIndex == i)
871     {
872         REPORT_INSTRUCTION(options,operand_class != OPERAND_IMMEDIATE, "Constant Immediate operands are not allowed to be used as destination operands.");
873 
874         if (operand_class == OPERAND_GENERAL)
875         {
876             if (operand_index < numPreDefinedVars)
877             {
878                 uint32_t byteOffset = opnd.opnd_val.gen_opnd.row_offset * COMMON_ISA_GRF_REG_SIZE +
879                     opnd.opnd_val.gen_opnd.col_offset *
880                     Get_VISA_Type_Size(getPredefinedVarType(mapExternalToInternalPreDefVar(operand_index)));
881                 REPORT_INSTRUCTION(options, isReadWritePreDefinedVar(isaHeader, operand_index, byteOffset), "Not allowed to write to a read only variable");
882             }
883         }
884     }
885 
886     // ToDo: add bounds check for pre-defined variables
887 }
888 
verifyOperand(const CISA_INST * inst,unsigned i)889 void vISAVerifier::verifyOperand(
890     const CISA_INST* inst,
891     unsigned i)
892 {
893     if (inst->opcode == ISA_DPAS || inst->opcode == ISA_DPASW)
894     {
895         // skip, as dpas is verified in verifyInstructionMisc().
896         return;
897     }
898     MUST_BE_TRUE(header, "Argument Exception: argument header is NULL.");
899     MUST_BE_TRUE(inst  , "Argument Exception: argument inst   is NULL.");
900     MUST_BE_TRUE(inst->opnd_count > i, "No such operand, i, for instruction inst.");
901     switch (getOperandType(inst, i))
902     {
903         case CISA_OPND_OTHER  : /* unable to verify some random primitive operand. */ break;
904         case CISA_OPND_VECTOR : verifyVectorOperand(inst, i); break;
905         case CISA_OPND_RAW    : verifyRawOperand   (inst, i); break;
906         default               : MUST_BE_TRUE(false, "Invalid operand type.");
907     }
908 }
909 
verifyInstructionSVM(const CISA_INST * inst)910 void vISAVerifier::verifyInstructionSVM(
911     const CISA_INST* inst)
912 {
913     if (hasExecSize((ISA_Opcode)inst->opcode))
914     {
915         REPORT_INSTRUCTION(options, EXEC_SIZE_32 != inst->getExecSize(),
916             "Execution size should not be SIMD32 for SVM messages.");
917     }
918 }
919 
verifyInstructionMove(const CISA_INST * inst)920 void vISAVerifier::verifyInstructionMove(
921     const CISA_INST* inst)
922 {
923     ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
924 
925     unsigned i = 0;
926 
927     uint8_t opext = opcode == ISA_FMINMAX ? getPrimitiveOperand<uint8_t>(inst, i++) : 0;
928 
929     const vector_opnd& dst  = getVectorOperand(inst, i++);
930     const vector_opnd& src0 = getVectorOperand(inst, i++);
931 
932     Common_ISA_Operand_Class operand_class_dst  =  dst.getOperandClass();
933     Common_ISA_Operand_Class operand_class_src0 = src0.getOperandClass();
934 
935     switch (opcode)
936     {
937         case ISA_MOV:
938         {
939              VISA_Type     dstType     = getVectorOperandType(header, dst);
940              VISA_Type     src0Type    = getVectorOperandType(header, src0);
941              VISA_Modifier dstModifier = dst.getOperandModifier();
942 
943              if (OPERAND_PREDICATE == operand_class_src0)
944              {
945                  REPORT_INSTRUCTION(options,EXEC_SIZE_1 == inst->getExecSize(),
946                          "Execution size for a flag copy mov instruction should be 1, as it is a scalar copy.");
947                  REPORT_INSTRUCTION(options, IsIntType(dstType) && dstType != ISA_TYPE_Q && dstType != ISA_TYPE_UQ,
948                          "dst operand type for a flag copy mov instruction should be non-64-bit integer.");
949                  REPORT_INSTRUCTION(options,CISATypeTable[dstType].typeSize >= CISATypeTable[src0Type].typeSize,
950                          "dst operand type for a flag copy mov instruction should be "
951                          "greater than or equal to the size of the src0 operand's type size.");
952                  REPORT_INSTRUCTION(options,dstModifier != MODIFIER_SAT,
953                           "saturation is not allowed for dst operands of a flag copy mov instruction");
954                  REPORT_INSTRUCTION(options,inst->pred.isNullPred(),
955                           "predication is not allowed for dst operands of a flag copy mov instruction");
956              }
957 
958              /* Commented out because we are too lame to follow our own specification. */
959              /*
960              REPORT_INSTRUCTION(options,operand_class_dst == OPERAND_GENERAL  ||
961                                operand_class_dst == OPERAND_INDIRECT,
962                                "Destination operand of CISA MOV instruction only "
963                                "supports general and indirect operands.");
964 
965              REPORT_INSTRUCTION(options,operand_class_src0 == OPERAND_GENERAL  ||
966                                operand_class_src0 == OPERAND_INDIRECT ||
967                                operand_class_src0 == OPERAND_IMMEDIATE,
968                                "Source0 operand of CISA MOV instruction only "
969                                "supports general, indirect, and immediate operands.");
970                                */
971              break;
972         }
973 
974         case ISA_MOVS:
975         {
976              REPORT_INSTRUCTION(options,operand_class_dst == OPERAND_GENERAL ||
977                                operand_class_dst == OPERAND_STATE,
978                                "Destination operand of CISA MOVS instruction only "
979                                "supports general and indirect operands.");
980 
981             REPORT_INSTRUCTION(options,operand_class_src0 == OPERAND_GENERAL  ||
982                                operand_class_src0 == OPERAND_STATE    ||
983                                operand_class_src0 == OPERAND_INDIRECT ||
984                                operand_class_src0 == OPERAND_IMMEDIATE,
985                                "Source0 operand of CISA MOVS instruction only "
986                                "supports general, indirect, and immediate operands.");
987             break;
988         }
989         case ISA_BF_CVT:
990         {
991             REPORT_INSTRUCTION(options, getGenxPlatform() >= XeHP_SDV,
992                 "BF_CVT is only supported on this platform");
993             REPORT_INSTRUCTION(options, operand_class_dst == OPERAND_GENERAL,
994                 "Destination operand of BF_CVT instruction only "
995                 "supports general and operands.");
996 
997             REPORT_INSTRUCTION(options, operand_class_src0 == OPERAND_GENERAL,
998                 "Source0 operand of BF_CVT instruction only "
999                 "supports general,  operands.");
1000 
1001             VISA_Type     dstType = getVectorOperandType(header, dst);
1002             VISA_Type     src0Type = getVectorOperandType(header, src0);
1003 
1004             // toBeDeletedSoon: checking ISA_TYPE_HF tool
1005             if (dstType == ISA_TYPE_UW || dstType == ISA_TYPE_HF)
1006             {
1007                 REPORT_INSTRUCTION(options, src0Type == ISA_TYPE_F,
1008                     "BF_CVT with UW(actually BF) dst must have F src");
1009             }
1010             else if (src0Type == ISA_TYPE_UW || src0Type == ISA_TYPE_HF)
1011             {
1012                 REPORT_INSTRUCTION(options, dstType == ISA_TYPE_F,
1013                     "BF_CVT with UW(actually BF) src must have F dst");
1014             }
1015             else
1016             {
1017                 REPORT_INSTRUCTION(options, false,
1018                     "BF_CVT must have either UW(actually BF) dst or src");
1019             }
1020 
1021             VISA_Modifier dstModifier = dst.getOperandModifier();
1022             REPORT_INSTRUCTION(options, dstModifier == MODIFIER_NONE,
1023                 "destination modifier not supported for BF conversion");
1024 
1025             VISA_Modifier srcModifier = src0.getOperandModifier();
1026             REPORT_INSTRUCTION(options, srcModifier == MODIFIER_NONE,
1027                 "source modifier not supported for BF conversion");
1028             break;
1029 
1030         }
1031         case ISA_FCVT:
1032         {
1033             REPORT_INSTRUCTION(options, getGenxPlatform() >= GENX_PVC,
1034                 "fcvt is not supported on the selected platform");
1035 
1036             REPORT_INSTRUCTION(options, operand_class_dst == OPERAND_GENERAL,
1037                 "Destination operand of fcvt instruction only "
1038                 "supports general and operands.");
1039 
1040             REPORT_INSTRUCTION(options, operand_class_src0 == OPERAND_GENERAL,
1041                 "Source0 operand of fcvt instruction only "
1042                 "supports general,  operands.");
1043 
1044             VISA_Type     dstType = getVectorOperandType(header, dst);
1045             VISA_Type     src0Type = getVectorOperandType(header, src0);
1046 
1047             if (dstType == ISA_TYPE_UB)
1048             {
1049                 REPORT_INSTRUCTION(options, src0Type == ISA_TYPE_HF,
1050                     "F_CVT with UB(actually BF8) dst must have HF src");
1051             }
1052             else if (src0Type == ISA_TYPE_UB)
1053             {
1054                 REPORT_INSTRUCTION(options, dstType == ISA_TYPE_HF,
1055                     "F_CVT with UB(actually BF8) src must have HF dst");
1056             }
1057             else if (dstType == ISA_TYPE_UD)
1058             {
1059                 REPORT_INSTRUCTION(options, src0Type == ISA_TYPE_F,
1060                     "F_CVT with UD(actually TF32) dst must have F src");
1061             }
1062             else if (src0Type == ISA_TYPE_UD)
1063             {
1064                 REPORT_INSTRUCTION(options, dstType == ISA_TYPE_F,
1065                     "F_CVT with UD(actually TF32) src0 must have F dst");
1066             }
1067             else
1068             {
1069                 REPORT_INSTRUCTION(options, false,
1070                     "F_CVT must have either UB(actually BF8) dst or src");
1071             }
1072 
1073             VISA_Modifier dstModifier = dst.getOperandModifier();
1074             VISA_Modifier srcModifier = src0.getOperandModifier();
1075             REPORT_INSTRUCTION(options, dstModifier == MODIFIER_NONE,
1076                 "destination modifier not supported for BF8/TF32 conversion");
1077             REPORT_INSTRUCTION(options, srcModifier == MODIFIER_NONE,
1078                 "source modifier not supported for BF8/TF32 conversion");
1079             break;
1080 
1081         }
1082         case ISA_SETP:
1083         {
1084              REPORT_INSTRUCTION(options,operand_class_dst == OPERAND_PREDICATE,
1085                                "Destination operand of CISA SETP instruction only "
1086                                "supports predicate operands.");
1087 
1088 
1089             REPORT_INSTRUCTION(options,operand_class_src0 == OPERAND_GENERAL  ||
1090                               operand_class_src0 == OPERAND_INDIRECT ||
1091                               operand_class_src0 == OPERAND_IMMEDIATE,
1092                               "Source0 operand of CISA SETP instruction only "
1093                               "supports general, indirect, and immediate operands.");
1094              break;
1095         }
1096         case ISA_SEL:
1097         case ISA_FMINMAX:
1098         {
1099              REPORT_INSTRUCTION(options,opext <= 1, "FMINMAX opext must be either 0x0 or 0x1 (min or max).");
1100 
1101              const vector_opnd& src1 = getVectorOperand(inst, i++);
1102              Common_ISA_Operand_Class operand_class_src1 = src1.getOperandClass();
1103 
1104              REPORT_INSTRUCTION(options,operand_class_dst == OPERAND_GENERAL  ||
1105                                operand_class_dst == OPERAND_INDIRECT,
1106                                "Destination operand of CISA SEL instruction only "
1107                                "supports general and indirect operands.");
1108 
1109              REPORT_INSTRUCTION(options,operand_class_src0 == OPERAND_GENERAL  ||
1110                                operand_class_src0 == OPERAND_INDIRECT ||
1111                                operand_class_src0 == OPERAND_IMMEDIATE,
1112                                "Source0 operand of CISA SEL instruction only "
1113                                "supports general, indirect, and immediate operands.");
1114 
1115              REPORT_INSTRUCTION(options,operand_class_src1 == OPERAND_GENERAL  ||
1116                                operand_class_src1 == OPERAND_INDIRECT ||
1117                                operand_class_src1 == OPERAND_IMMEDIATE,
1118                                "Source1 operand of CISA SEL instruction only "
1119                                "supports general, indirect, and immediate operands.");
1120              break;
1121         }
1122         default: REPORT_INSTRUCTION(options,false, "Illegal Move Instruction Opcode: %d, %s.", opcode, ISA_Inst_Table[opcode].str);
1123     }
1124 }
1125 
verifyInstructionSync(const CISA_INST * inst)1126 void vISAVerifier::verifyInstructionSync(
1127     const CISA_INST* inst)
1128 {
1129     ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
1130     switch (opcode)
1131     {   case ISA_BARRIER            : return;
1132         case ISA_SAMPLR_CACHE_FLUSH : return;
1133         case ISA_WAIT               : return;
1134         case ISA_FENCE              : return;
1135         case ISA_YIELD              : return;
1136         case ISA_SBARRIER           : return;
1137         case ISA_NBARRIER           : return;
1138         default: REPORT_INSTRUCTION(options,false, "Illegal Synchronization Instruction Opcode: %d, %s.", opcode, ISA_Inst_Table[opcode].str);
1139     }
1140 }
1141 
verifyInstructionControlFlow(const CISA_INST * inst)1142 void vISAVerifier::verifyInstructionControlFlow(
1143     const CISA_INST* inst)
1144 {
1145     ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
1146 
1147     switch (opcode)
1148     {
1149         case ISA_JMP:
1150         case ISA_CALL:
1151         {
1152             bool isFC = static_cast<G4_Label*>(inst->opnd_array[0]->g4opnd)->isFCLabel();
1153             auto labelId = getPrimitiveOperand<uint16_t>(inst, 0);
1154             if (labelId >= header->getLabelCount())
1155             {
1156                 REPORT_INSTRUCTION(options, false, "bad label id %d", labelId);
1157             }
1158             else
1159             {
1160                 auto iter = labelDefs.find(labelId);
1161                 if (iter == labelDefs.end() && !isFC)
1162                 {
1163                     labelDefs[labelId] = false;
1164                 }
1165                 // nothing needs to be done if the label is already in the map
1166             }
1167             break;
1168         }
1169         case ISA_RET:
1170         case ISA_FRET:
1171         case ISA_IFCALL:
1172         case ISA_FADDR:     // no checks for now
1173              break;
1174         case ISA_SUBROUTINE:
1175         case ISA_LABEL:
1176         {
1177             auto labelId = getPrimitiveOperand<uint16_t>(inst, 0);
1178             if (labelId >= header->getLabelCount())
1179             {
1180                 REPORT_INSTRUCTION(options, false, "bad label id %d", labelId);
1181             }
1182             else
1183             {
1184                 auto iter = labelDefs.find(labelId);
1185                 if (iter != labelDefs.end() && iter->second)
1186                 {
1187                     REPORT_INSTRUCTION(options, false, "label is redefined");
1188                 }
1189                 labelDefs[labelId] = true;
1190             }
1191             break;
1192         }
1193         case ISA_FCALL:
1194         {
1195              break;
1196         }
1197         case ISA_SWITCHJMP:
1198         {
1199             REPORT_INSTRUCTION(options, !irBuilder->hasFusedEU(), "switchjmp is not supported on this platform");
1200             break;
1201         }
1202         default: REPORT_INSTRUCTION(options,false, "Illegal Scalar Control Flow Instruction Opcode: %d, %s.", opcode, ISA_Inst_Table[opcode].str);
1203     }
1204 }
1205 
verifyInstructionMisc(const CISA_INST * inst)1206 void vISAVerifier::verifyInstructionMisc(
1207     const CISA_INST* inst)
1208 {
1209     unsigned i = 0;
1210     unsigned numPreDefinedSurfs = Get_CISA_PreDefined_Surf_Count();
1211 
1212     ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
1213     switch (opcode)
1214     {
1215         case ISA_VME_IME:
1216         {
1217             uint8_t stream_mode = getPrimitiveOperand<uint8_t>(inst, i++);
1218             REPORT_INSTRUCTION(options,stream_mode == VME_STREAM_DISABLE ||
1219                               stream_mode == VME_STREAM_OUT     ||
1220                               stream_mode == VME_STREAM_IN      ||
1221                               stream_mode == VME_STREAM_IN_OUT,
1222                               "CISA ISA_VME_IME instruction uses illegal stream mode.");
1223 
1224             uint8_t search_ctrl = getPrimitiveOperand<uint8_t>(inst, i++);
1225             REPORT_INSTRUCTION(options,search_ctrl == VME_SEARCH_SINGLE_REF_SINGLE_REC_SINGLE_START ||
1226                               search_ctrl == VME_SEARCH_SINGLE_REF_SINGLE_REC_DUAL_START   ||
1227                               search_ctrl == VME_SEARCH_SINGLE_REF_DUAL_REC                ||
1228                               search_ctrl == VME_SEARCH_DUAL_REF_DUAL_REC,
1229                               "CISA ISA_VME_IME instruction uses illegal search ctrl.");
1230 
1231             i++; /// uni input
1232             i++; /// ime input
1233 
1234             uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1235             REPORT_INSTRUCTION(options,(unsigned)surface < numPreDefinedSurfs + header->getSurfaceCount(),
1236                 "CISA ISA_VME_IME uses undeclared surface.");
1237 
1238             break;
1239         }
1240         case ISA_VME_SIC:
1241         {
1242              i++; /// uni input
1243              i++; /// sic input
1244 
1245              uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1246              REPORT_INSTRUCTION(options,(unsigned)surface < numPreDefinedSurfs + header->getSurfaceCount(),
1247                  "CISA ISA_VME_SIC uses undeclared surface.");
1248 
1249              break;
1250         }
1251         case ISA_VME_FBR:
1252         {
1253              getRawOperand(inst, i++);  // const raw_opnd& UNIInput
1254              getRawOperand(inst, i++);  // const raw_opnd& FBRInput
1255 
1256              uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1257              REPORT_INSTRUCTION(options,(unsigned)surface < numPreDefinedSurfs + header->getSurfaceCount(),
1258                  "CISA ISA_VME_FBR uses undeclared surface.");
1259 
1260              Common_ISA_Operand_Class operand_class_FBRMbMode = getVectorOperand(inst, i++).getOperandClass();
1261              REPORT_INSTRUCTION(options,operand_class_FBRMbMode == OPERAND_GENERAL  ||
1262                                operand_class_FBRMbMode == OPERAND_INDIRECT ||
1263                                operand_class_FBRMbMode == OPERAND_IMMEDIATE,
1264                                "FBRMbMode operand of CISA VME_FBR instrution should "
1265                                "be either a general, indirect, or immediate operand.");
1266 
1267              Common_ISA_Operand_Class operand_class_FBRSubMbShape = getVectorOperand(inst, i++).getOperandClass();
1268              REPORT_INSTRUCTION(options,operand_class_FBRSubMbShape == OPERAND_GENERAL  ||
1269                                operand_class_FBRSubMbShape == OPERAND_INDIRECT ||
1270                                operand_class_FBRSubMbShape == OPERAND_IMMEDIATE,
1271                                "FBRSubMbShape operand of CISA VME_FBR instrution should "
1272                                "be either a general, indirect, or immediate operand.");
1273 
1274              Common_ISA_Operand_Class operand_class_FBRSubPredMode = getVectorOperand(inst, i++).getOperandClass();
1275              REPORT_INSTRUCTION(options,operand_class_FBRSubPredMode == OPERAND_GENERAL  ||
1276                                operand_class_FBRSubPredMode == OPERAND_INDIRECT ||
1277                                operand_class_FBRSubPredMode == OPERAND_IMMEDIATE,
1278                                "FBRSubPredMode operand of CISA VME_FBR instrution should "
1279                                "be either a general, indirect, or immediate operand.");
1280 
1281              getRawOperand(inst, i++);  // const raw_opnd& output
1282 
1283              break;
1284         }
1285         case ISA_VME_IDM:
1286         {
1287             break;
1288         }
1289         case ISA_LOC:
1290         {
1291             break;
1292         }
1293         case ISA_FILE:
1294         {
1295             break;
1296         }
1297         case ISA_RAW_SEND:
1298         {
1299             getPrimitiveOperand<uint8_t>(inst, i++);    // uint8_t modifier
1300 
1301             getPrimitiveOperand<uint8_t>(inst, i++);    // unit8_t exMsgDesc
1302 
1303             uint8_t numSrc = getPrimitiveOperand<uint8_t>(inst, i++);
1304             REPORT_INSTRUCTION(options,numSrc >= 1 && numSrc <= 15, "Number of message source GRFs must be between 1 and 15");
1305 
1306             uint8_t numDst = getPrimitiveOperand<uint8_t>(inst, i++);
1307             REPORT_INSTRUCTION(options,numDst <= 16, "Number of message destination GRFs must be between 0 and 16");
1308 
1309             const vector_opnd& desc = getVectorOperand(inst, i++);
1310             Common_ISA_Operand_Class operand_class_desc = desc.getOperandClass();
1311             REPORT_INSTRUCTION(options, operand_class_desc == OPERAND_GENERAL ||
1312                               operand_class_desc == OPERAND_INDIRECT ||
1313                               operand_class_desc == OPERAND_IMMEDIATE,
1314                               "desc operand of CISA RAW_SEND instrution should "
1315                               "be either a general, indirect, or immediate operand.");
1316 
1317             if (operand_class_desc == OPERAND_IMMEDIATE)
1318             {
1319                 /// Structure describes a send message descriptor. Only expose
1320                 /// several data fields; others are unnamed.
1321                 struct MsgDescLayout {
1322                     uint32_t funcCtrl : 19;     // Function control (bit 0:18)
1323                     uint32_t headerPresent : 1; // Header present (bit 19)
1324                     uint32_t rspLength : 5;     // Response length (bit 20:24)
1325                     uint32_t msgLength : 4;     // Message length (bit 25:28)
1326                     uint32_t simdMode2 : 1;     // 16-bit input (bit 29)
1327                     uint32_t returnFormat : 1;  // 16-bit return (bit 30)
1328                     uint32_t EOT : 1;           // EOT
1329                 };
1330 
1331                 /// View a message descriptor in two different ways:
1332                 /// - as a 32-bit unsigned integer
1333                 /// - as a structure
1334                 /// This simplifies the implementation of extracting subfields.
1335                 union DescData {
1336                     uint32_t value;
1337                     MsgDescLayout layout;
1338                 }udesc;
1339 
1340                 udesc.value = desc.opnd_val.const_opnd._val.ival;
1341 
1342                 REPORT_INSTRUCTION(options, numSrc >= udesc.layout.msgLength,
1343                                   "message length mismatch for raw send: msgLength (%d) must be not greater than numSrc (%d)",
1344                                   udesc.layout.msgLength, numSrc);
1345                 REPORT_INSTRUCTION(options, numDst >= udesc.layout.rspLength,
1346                                   "response length mismatch for raw send: rspLength (%d) must be not greater than numDst (%d)",
1347                                   udesc.layout.rspLength, numDst);
1348             }
1349 
1350 
1351             /// src: todo
1352             /// dst: todo
1353 
1354             break;
1355         }
1356         case ISA_RAW_SENDS:
1357         {
1358             getPrimitiveOperand<uint8_t>(inst, i++);    // uint8_t modifier
1359 
1360             uint8_t numSrc0 = getPrimitiveOperand<uint8_t>(inst, i++);
1361             REPORT_INSTRUCTION(options,numSrc0 >= 1 && numSrc0 <= 32, "Number of source0 GRFs must be between 1 and 32");
1362 
1363             uint8_t numSrc1 = getPrimitiveOperand<uint8_t>(inst, i++);
1364             REPORT_INSTRUCTION(options, numSrc1 <= 32, "Number of source1 GRFs must be between 1 and 32");
1365 
1366             uint8_t numDst = getPrimitiveOperand<uint8_t>(inst, i++);
1367             REPORT_INSTRUCTION(options,numDst <= 32, "Number of message destination GRFs must be between 0 and 32");
1368 
1369             getPrimitiveOperand<uint8_t>(inst, i++);    // uint8_t exMsgDesc
1370 
1371             Common_ISA_Operand_Class operand_class_desc = getVectorOperand(inst, i++).getOperandClass();
1372             REPORT_INSTRUCTION(options,operand_class_desc == OPERAND_GENERAL  ||
1373                               operand_class_desc == OPERAND_INDIRECT ||
1374                               operand_class_desc == OPERAND_IMMEDIATE,
1375                               "desc operand of CISA RAW_SEND instrution should "
1376                               "be either a general, indirect, or immediate operand.");
1377 
1378             /// src0: todo
1379             /// src1: todo
1380             /// dst: todo
1381 
1382             break;
1383         }
1384         case ISA_3D_URB_WRITE:
1385         {
1386             uint8_t numOut = getPrimitiveOperand<uint8_t>(inst, i++);
1387             getPrimitiveOperand<uint16_t>(inst, i++);   // uint16_t channelMask
1388             uint16_t globalOff = getPrimitiveOperand<uint16_t>(inst, i++);
1389 
1390             REPORT_INSTRUCTION(options,!(numOut < 1 || numOut > 8) , "Valid range for num_out parameter of URB write is [1,8]");
1391             REPORT_INSTRUCTION(options,globalOff <= 2047, "Valid range for global_offset parameter of URB write is [0,2047]");
1392             REPORT_INSTRUCTION(options, inst->getExecSize() == EXEC_SIZE_1 || inst->getExecSize() == EXEC_SIZE_8,
1393                 "Only execution size of 1 or 8 is supported for URB write");
1394 
1395             break;
1396         }
1397         case ISA_DPAS:
1398         case ISA_DPASW:
1399         {
1400             auto FNIsInt = [](VISA_Type Ty) -> bool {
1401                 return (Ty == ISA_TYPE_UD || Ty == ISA_TYPE_D);
1402             };
1403             auto FNIsIntOrFloat = [](VISA_Type Ty) -> bool {
1404                 bool isHFOrBF = false;
1405                 if (getGenxPlatform() >= GENX_PVC)
1406                 {
1407                     // W or UW means BF
1408                     isHFOrBF = (Ty == ISA_TYPE_HF || Ty == ISA_TYPE_UW || Ty == ISA_TYPE_W);
1409                 }
1410                 return (Ty == ISA_TYPE_UD || Ty == ISA_TYPE_D || Ty == ISA_TYPE_F || isHFOrBF);
1411             };
1412 
1413             // No predicate
1414             REPORT_INSTRUCTION(options, inst->pred.isNullPred(), "%s inst does not support predicate", ISA_Inst_Table[opcode].str);
1415 
1416             // execsize must be simd8 for XeHP_SDV and simd16 for PVC
1417             if (getGenxPlatform() >= GENX_PVC)
1418             {
1419                 REPORT_INSTRUCTION(options, opcode != ISA_DPASW,
1420                     "%s instuction is not supported on selected platform", ISA_Inst_Table[opcode].str);
1421                 REPORT_INSTRUCTION(options, inst->getExecSize() == EXEC_SIZE_16,
1422                     "Only execution size of 16 is supported for %s on platform %s",
1423                     ISA_Inst_Table[opcode].str, getGenxPlatformString(getGenxPlatform()));
1424             }
1425             else
1426             {
1427                 REPORT_INSTRUCTION(options, inst->getExecSize() == EXEC_SIZE_8,
1428                     "Only execution size of 8 is supported for %s on platform %s",
1429                     ISA_Inst_Table[opcode].str, getGenxPlatformString(getGenxPlatform()));
1430             }
1431 
1432             // dst
1433             verifyRawOperand(inst, i);
1434             const raw_opnd&  dst = getRawOperand(inst, i);
1435             verifyRawOperandType(inst, dst, FNIsIntOrFloat);
1436 
1437             // src0
1438             verifyRawOperand(inst, ++i);
1439             const raw_opnd&  src0 = getRawOperand(inst, i);
1440             verifyRawOperandType(inst, src0, FNIsIntOrFloat);
1441 
1442             // src1
1443             verifyRawOperand(inst, ++i);
1444             const raw_opnd&  src1 = getRawOperand(inst, i);
1445             verifyRawOperandType(inst, src1, FNIsInt);
1446 
1447             // src2
1448             const vector_opnd&  src2 = getVectorOperand(inst, ++i);
1449             VISA_Type  src2Ty = getVectorOperandType(header, src2);
1450             VISA_Modifier src2Mod = src2.getOperandModifier();
1451             REPORT_INSTRUCTION(options, src2Mod == MODIFIER_NONE,  "Modifier not allowed for %s", ISA_Inst_Table[opcode].str);
1452             REPORT_INSTRUCTION(options, FNIsInt(src2Ty), "Only U/UD allowed for %s", ISA_Inst_Table[opcode].str);
1453 
1454             break;
1455         }
1456         case ISA_LIFETIME:
1457         {
1458             uint8_t properties = getPrimitiveOperand<uint8_t>(inst, i++);
1459             getPrimitiveOperand<uint32_t>(inst, i++);   // uint32_t varId
1460 
1461             unsigned char type = (properties >> 4) & 0x3;
1462 
1463             if (type != OPERAND_GENERAL && type != OPERAND_ADDRESS && type != OPERAND_PREDICATE)
1464             {
1465                 REPORT_INSTRUCTION(options, false, "Invalid encoding for register file");
1466             }
1467 
1468             break;
1469         }
1470         default: REPORT_INSTRUCTION(options,false, "Illegal Miscellaneous Flow Instruction Opcode: %d, %s.", opcode, ISA_Inst_Table[opcode].str);
1471     }
1472 }
1473 
1474 /// Returns true if this vector operand is an integer immediate constant and
1475 /// its value fits into an expected type. Returns false, otherwise.
1476 ///
checkImmediateIntegerOpnd(const vector_opnd & opnd,VISA_Type expected_type)1477 bool vISAVerifier::checkImmediateIntegerOpnd(
1478     const vector_opnd& opnd,
1479     VISA_Type expected_type)
1480 {
1481     MUST_BE_TRUE(IsIntType(expected_type), "integer type expected");
1482 
1483     // Not an immediate.
1484     if (!opnd.isImmediate())
1485         return false;
1486 
1487     VISA_Type opnd_type = opnd.getImmediateType();
1488     if (!IsIntOrIntVecType(opnd_type))
1489     {
1490         return false;
1491     }
1492 
1493     bool is_vector = (opnd_type == ISA_TYPE_V || opnd_type == ISA_TYPE_UV);
1494     if (is_vector)
1495     {
1496         // if the operand type is unsigned, then always fits;
1497         // if the expected type is signed, then always fits;
1498         // otherwise, to be determined.
1499         if ((opnd_type == ISA_TYPE_UV) || IsSingedIntType(expected_type))
1500             return true;
1501     }
1502 
1503     // Retrieve the immediate integer value.
1504     int64_t val = 0;
1505     if (opnd_type == ISA_TYPE_Q || opnd_type == ISA_TYPE_UQ)
1506         val = typecastVals(&opnd.opnd_val.const_opnd._val.lval, opnd_type);
1507     else
1508         val = typecastVals(&opnd.opnd_val.const_opnd._val.ival, opnd_type);
1509 
1510     // The operand type is signed, and the expected type is unsigned.
1511     // All elements in this packed integer vector should be non-negative,
1512     // otherwise it does not fit.
1513     if (is_vector)
1514     {
1515         MUST_BE_TRUE(IsUnsignedIntType(expected_type), "unexpected signed type");
1516 
1517         // Truncate to 32 bit, each 4 bits consist of a vector component.
1518         // Sign bits are 3, 7, 11, 15, 19, 23, 27 and 31.
1519         return ((int32_t)val & 0x88888888) == 0;
1520     }
1521 
1522     switch (expected_type) {
1523     case ISA_TYPE_B:
1524         return (int8_t)val == val;
1525     case ISA_TYPE_UB:
1526         return (val >= 0) && ((uint8_t)val == val);
1527     case ISA_TYPE_W:
1528         return (int16_t)val == val;
1529     case ISA_TYPE_UW:
1530         return (val >= 0) && ((uint16_t)val == val);
1531     case ISA_TYPE_D:
1532         return (int32_t)val == val;
1533     case ISA_TYPE_UD:
1534         return (val >= 0) && ((uint32_t)val == val);
1535     case ISA_TYPE_Q:
1536     {
1537         // It does not fit into Q only if operand has type UQ and its value
1538         // exceeds the limit.
1539         if (opnd_type == ISA_TYPE_UQ)
1540         {
1541             // The actual value is to reprensent as an unsigned integer.
1542             uint64_t u_val = static_cast<uint64_t>(val);
1543             return u_val <= (uint64_t)std::numeric_limits<int64_t>::max();
1544         }
1545 
1546         // Fit for all other cases.
1547         return true;
1548     }
1549     case ISA_TYPE_UQ:
1550     {
1551         // UQ values fit.
1552         if (opnd_type == ISA_TYPE_UQ)
1553             return true;
1554 
1555         // Not UQ, but Q or smaller types.
1556         return val >= 0;
1557     }
1558     default:
1559         break;
1560     }
1561     return false;
1562 }
1563 
verifyInstructionArith(const CISA_INST * inst)1564 void vISAVerifier::verifyInstructionArith(
1565     const CISA_INST* inst)
1566 {
1567     ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
1568 
1569     if (opcode == ISA_SRND)
1570     {
1571         verifyInstructionSrnd(inst);
1572         return;
1573     }
1574     if (useGivenVISAType(inst, ISA_TYPE_BF))
1575     {
1576         // Let bfmode verifier to verify it.
1577         return;
1578     }
1579 
1580     unsigned i = 0;
1581     const vector_opnd& dst = getVectorOperand(inst, i);
1582     VISA_Type         dstType = getVectorOperandType(header, dst);
1583     VISA_Modifier dstModifier = dst.getOperandModifier();
1584     auto platform = getGenxPlatform();
1585 
1586     REPORT_INSTRUCTION(options, dst.getOperandClass() == OPERAND_GENERAL ||
1587         dst.getOperandClass() == OPERAND_INDIRECT,
1588         "Destination of CISA arithmetic instruction should be general or indirect operand.");
1589 
1590     REPORT_INSTRUCTION(options, dstModifier == MODIFIER_NONE ||
1591         dstModifier == MODIFIER_SAT,
1592         "Illegal destination modifier for CISA arithmetic instruction.");
1593 
1594     // check if sat is allowed for this instruction
1595     if (dstModifier == MODIFIER_SAT)
1596     {
1597         switch (opcode)
1598         {
1599         case ISA_FRC:
1600         case ISA_LZD:
1601         case ISA_MOD:
1602         case ISA_MULH:
1603         case ISA_MADW:
1604             REPORT_INSTRUCTION(options, false,
1605                 "%s does not support saturation",
1606                 ISA_Inst_Table[opcode].str);
1607             break;
1608         case ISA_DIV:
1609             REPORT_INSTRUCTION(options, dstType == ISA_TYPE_F || dstType == ISA_TYPE_HF,
1610                 "%s does not support saturation on integer types.",
1611                 ISA_Inst_Table[opcode].str);
1612         default:
1613             break;
1614         }
1615     }
1616 
1617     if (dstType == ISA_TYPE_DF)
1618     {
1619         if (opcode != ISA_MUL && opcode != ISA_ADD && opcode != ISA_MAD && opcode != ISA_DIV &&
1620             opcode != ISA_INV && opcode != ISA_SQRTM && opcode != ISA_SQRT && opcode != ISA_DIVM)
1621         {
1622             REPORT_INSTRUCTION(options, false,
1623                 "Only mul/add/mad/div/inv/sqrtm/sqrt/divm are allowed to use double precision floating point operands.");
1624         }
1625     }
1626 
1627     if ((opcode == ISA_DIV && IsIntType(dstType)) || opcode == ISA_MOD)
1628     {
1629         REPORT_INSTRUCTION(options, platform < XeHP_SDV, "int divide/remainder is not supported for this platform");
1630     }
1631 
1632     /// check dst type is supported by the instruction
1633     switch (opcode)
1634     {
1635     case ISA_COS:
1636     case ISA_EXP:
1637     case ISA_LOG:
1638     case ISA_POW:
1639     case ISA_SIN:
1640         /// float and half float
1641         REPORT_INSTRUCTION(options, dstType == ISA_TYPE_F || dstType == ISA_TYPE_HF,
1642             "%s only supports single and half float type", ISA_Inst_Table[opcode].str);
1643         break;
1644     case ISA_RNDD:
1645     case ISA_RNDU:
1646     case ISA_RNDE:
1647     case ISA_RNDZ:
1648     case ISA_PLANE:
1649     case ISA_DP2:
1650     case ISA_DP3:
1651     case ISA_DP4:
1652     case ISA_DPH:
1653     case ISA_FRC:
1654     case ISA_LRP:
1655         /// float only
1656         REPORT_INSTRUCTION(options, dstType == ISA_TYPE_F, "%s only supports single float type", ISA_Inst_Table[opcode].str);
1657         break;
1658     case ISA_LINE:
1659         /// float or int only
1660         REPORT_INSTRUCTION(options, dstType == ISA_TYPE_F || IsIntType(dstType),
1661             "%s only supports integer and single precision float types", ISA_Inst_Table[opcode].str);
1662         break;
1663     case ISA_AVG:
1664     case ISA_MOD:
1665         /// int only
1666         REPORT_INSTRUCTION(options, dstType == ISA_TYPE_UD ||
1667             dstType == ISA_TYPE_D ||
1668             dstType == ISA_TYPE_UW ||
1669             dstType == ISA_TYPE_W ||
1670             dstType == ISA_TYPE_UB ||
1671             dstType == ISA_TYPE_B,
1672             "%s only supports integer type", ISA_Inst_Table[opcode].str);
1673         break;
1674     case ISA_LZD:
1675         /// UD only
1676         REPORT_INSTRUCTION(options, dstType == ISA_TYPE_UD, "lzd only supports UD type");
1677         break;
1678     case ISA_MULH:
1679     case ISA_DP4A:
1680     case ISA_MADW:
1681         /// U or UD only
1682         REPORT_INSTRUCTION(options, dstType == ISA_TYPE_D || dstType == ISA_TYPE_UD,
1683             "%s only support D/UD dst type", ISA_Inst_Table[opcode].str);
1684         break;
1685     case ISA_SAD2:
1686     case ISA_SAD2ADD:
1687         /// dst must be w or uw
1688         REPORT_INSTRUCTION(options, dstType == ISA_TYPE_W || dstType == ISA_TYPE_UW, "sad2/sad2add only supports W/UW dst type.");
1689         REPORT_INSTRUCTION(options, getPlatformGeneration(getGenxPlatform()) != PlatformGen::XE, "sad2/sad2add is not supported on Xe.");
1690         break;
1691     case ISA_ADDC:
1692     case ISA_SUBB:
1693         REPORT_INSTRUCTION(options, dstType == ISA_TYPE_UD, "%s only supports single UD type", ISA_Inst_Table[opcode].str);
1694         break;
1695     case ISA_ADD3:
1696     case ISA_ADD3O:
1697         REPORT_INSTRUCTION(options, dstType == ISA_TYPE_UD || dstType == ISA_TYPE_D ||
1698             dstType == ISA_TYPE_UW || dstType == ISA_TYPE_W,
1699             "%s only supports interger D/W type", ISA_Inst_Table[opcode].str);
1700         break;
1701     default:
1702         REPORT_INSTRUCTION(options, dstType == ISA_TYPE_F || dstType == ISA_TYPE_DF || dstType == ISA_TYPE_HF || IsIntType(dstType), "%s has illegal dst type", ISA_Inst_Table[opcode].str);
1703     }
1704 
1705     // verify each source operand
1706     for (unsigned i = 0; i < ISA_Inst_Table[opcode].n_srcs; i++)
1707     {
1708         const vector_opnd& src = getVectorOperand(inst, i + ISA_Inst_Table[opcode].n_dsts); /// dst is at index 0, addc/subbb have two destinations
1709         VISA_Type         srcType = getVectorOperandType(header, src);
1710         VISA_Modifier srcModifier = src.getOperandModifier();
1711 
1712         REPORT_INSTRUCTION(options, srcModifier != MODIFIER_SAT && srcModifier != MODIFIER_NOT,
1713             "unsupported source modifier for arithmetic instruction");
1714 
1715         REPORT_INSTRUCTION(options, src.getOperandClass() == OPERAND_GENERAL ||
1716             src.getOperandClass() == OPERAND_INDIRECT ||
1717             src.getOperandClass() == OPERAND_IMMEDIATE,
1718             "source in arithmetic instruction must be general, indirect, or immediate");
1719 
1720         if (srcType == ISA_TYPE_DF)
1721         {
1722             if (opcode != ISA_MUL && opcode != ISA_ADD && opcode != ISA_MAD && opcode != ISA_DIV &&
1723                 opcode != ISA_INV && opcode != ISA_SQRTM && opcode != ISA_SQRT && opcode != ISA_DIVM)
1724             {
1725                 REPORT_INSTRUCTION(options, false,
1726                     "Only mul/add/mad/div/inv/sqrtm/sqrt/divm are allowed to use double precision floating point operands.");
1727             }
1728         }
1729 
1730         if (dstType == ISA_TYPE_F ||
1731             dstType == ISA_TYPE_DF ||
1732             dstType == ISA_TYPE_HF ||
1733             srcType == ISA_TYPE_DF ||
1734             srcType == ISA_TYPE_F ||
1735             srcType == ISA_TYPE_HF)
1736         {
1737             REPORT_INSTRUCTION(options, dstType == srcType ||
1738                 (dstType == ISA_TYPE_F && srcType == ISA_TYPE_VF) ||
1739                 (dstType == ISA_TYPE_F && srcType == ISA_TYPE_HF) ||
1740                 (dstType == ISA_TYPE_HF && srcType == ISA_TYPE_F),
1741                 "Arithmetic instructions that use single or double precision or half float types "
1742                 "must use the same type for all of their operannds: dst(%s) and src%d(%s).",
1743                 CISATypeTable[dstType].typeName, i, CISATypeTable[srcType].typeName);
1744         }
1745         else
1746         {
1747             /// source must have integer type
1748             REPORT_INSTRUCTION(options, IsIntType(srcType) ||
1749                 (src.getOperandClass() == OPERAND_IMMEDIATE &&
1750                 (srcType == ISA_TYPE_V || srcType == ISA_TYPE_UV)),
1751                 "immediate src%d has %d type, and it must have integer type", i, srcType);
1752         }
1753 
1754         switch (opcode)
1755         {
1756         case ISA_SAD2:
1757         case ISA_SAD2ADD:
1758         {
1759             bool is_valid_imm = false;
1760             if (i == 2)
1761             {
1762                 is_valid_imm = checkImmediateIntegerOpnd(src, ISA_TYPE_W) ||
1763                     checkImmediateIntegerOpnd(src, ISA_TYPE_UW);
1764             }
1765             else
1766             {
1767                 is_valid_imm = checkImmediateIntegerOpnd(src, ISA_TYPE_B) ||
1768                     checkImmediateIntegerOpnd(src, ISA_TYPE_UB);
1769             }
1770             REPORT_INSTRUCTION(options, is_valid_imm ||
1771                 (i == 2 && (srcType == ISA_TYPE_W || srcType == ISA_TYPE_UW)) ||
1772                 (i <= 1 && (srcType == ISA_TYPE_B || srcType == ISA_TYPE_UB)),
1773                 "sad2/sad2add only supports B/UB types for src0 and src1; W/UW for src2 (sad2add). src%d has invalid type.", i);
1774             break;
1775         }
1776         case ISA_MUL:
1777         case ISA_DIV:
1778             REPORT_INSTRUCTION(options, srcType != ISA_TYPE_Q && srcType != ISA_TYPE_UQ,
1779                 "mul does not support Q/UQ types for src%d", i);
1780             break;
1781         case ISA_DIVM:
1782             REPORT_INSTRUCTION(options, srcType == ISA_TYPE_F || srcType == ISA_TYPE_DF || srcType == ISA_TYPE_VF,
1783                 "ieee div does not support types for src%d, other than F/DF/VF", i);
1784             break;
1785         case ISA_SQRTM:
1786             REPORT_INSTRUCTION(options, srcType == ISA_TYPE_F || srcType == ISA_TYPE_DF || srcType == ISA_TYPE_VF,
1787                 "ieee sqrt does not support types for src%d, other than F/DF/VF", i);
1788             break;
1789         case ISA_ADDC:
1790         case ISA_SUBB:
1791         {
1792             REPORT_INSTRUCTION(options, srcType == ISA_TYPE_UD || srcType == ISA_TYPE_UV,
1793                 "%s src0 and src1 only supports single UD type", ISA_Inst_Table[opcode].str);
1794             break;
1795         }
1796         case ISA_DP4A:
1797             REPORT_INSTRUCTION(options,
1798                 srcType == ISA_TYPE_D || srcType == ISA_TYPE_UD,
1799                 "%s src0 and src1 only supports single UD type",
1800                 ISA_Inst_Table[opcode].str);
1801             break;
1802         case ISA_ADD3:
1803         case ISA_ADD3O:
1804             REPORT_INSTRUCTION(options,
1805                 srcType == ISA_TYPE_D || srcType == ISA_TYPE_UD ||
1806                 srcType == ISA_TYPE_W || srcType == ISA_TYPE_UW,
1807                 "%s src operand only supports integer D/W type", ISA_Inst_Table[opcode].str);
1808             break;
1809         default:
1810             break; // Prevent gcc warning
1811         }
1812     }
1813 
1814     // check for IEEE macros support
1815     // !hasMadm() check
1816     bool noMadm = (platform == GENX_ICLLP || platform == GENX_TGLLP);
1817     noMadm |= platform == GENX_DG2;
1818     if (noMadm)
1819     {
1820         bool fOpcodeIEEE = (opcode == ISA_DIVM) || (opcode == ISA_SQRTM);
1821         bool dfOpcodeIEEE = fOpcodeIEEE || (opcode == ISA_INV) || (opcode == ISA_DIV) || (opcode == ISA_SQRT);
1822         REPORT_INSTRUCTION(options,
1823             !(dstType == ISA_TYPE_DF && dfOpcodeIEEE) &&
1824                 !(dstType == ISA_TYPE_F && fOpcodeIEEE),
1825             "IEEE instruction %s is not supported on %s platform",
1826             ISA_Inst_Table[opcode].str, getGenxPlatformString(platform));
1827     }
1828 }
1829 
verifyInstructionLogic(const CISA_INST * inst)1830 void vISAVerifier::verifyInstructionLogic(
1831     const CISA_INST* inst)
1832 {
1833     ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
1834 
1835     bool pred_logic = false;
1836     unsigned opend_count = inst->opnd_count;
1837     if (opcode == ISA_BFN)
1838     {
1839         // check opnd type of the last opend, which is BooleanFuncCtrl
1840         REPORT_INSTRUCTION(options,
1841             getOperandType(inst, opend_count - 1) == CISA_OPND_OTHER,
1842             "last opnd should be CISA_OPND_OTHER type");
1843         // skip below type check for booleanFuncCtrl
1844         --opend_count;
1845     }
1846     for (unsigned i = 0; i < opend_count; i++)
1847     {
1848         const vector_opnd& opnd = getVectorOperand(inst, i);
1849         VISA_Type opnd_type = getVectorOperandType(header, opnd);
1850 
1851         REPORT_INSTRUCTION(
1852             options, opnd.getOperandClass() != OPERAND_ADDRESS,
1853             "Common ISA Logic instrutions are not allowed to have address operands.");
1854 
1855         REPORT_INSTRUCTION(options,
1856             !pred_logic || opnd_type == ISA_TYPE_BOOL,
1857             "Operand type of logic operantion for predicate operands should all be BOOL "
1858             "(ie if one operand is BOOL they all have to be BOOL).");
1859 
1860         if (opcode == ISA_ROR || opcode == ISA_ROL)
1861         {
1862             switch (opnd_type)
1863             {
1864             case ISA_TYPE_B:
1865             case ISA_TYPE_UB:
1866                 REPORT_INSTRUCTION(options, false,
1867                     "ror/rol does not support i8 types");
1868                 break;
1869             case ISA_TYPE_UQ:
1870             case ISA_TYPE_Q:
1871                 // This string was changed from "ror/rol only support i64 types on PVC+" due to IP leak concers.
1872                 REPORT_INSTRUCTION(options, getGenxPlatform() >= GENX_PVC,
1873                     "ror/rol does not support i64 types on the selected platform");
1874                 break;
1875             default:
1876                 break;
1877             }
1878         }
1879 
1880         switch (opnd_type)
1881         {
1882             case ISA_TYPE_B:
1883             case ISA_TYPE_UB:
1884             case ISA_TYPE_W:
1885             case ISA_TYPE_D:
1886             case ISA_TYPE_UW:
1887             case ISA_TYPE_UD:
1888             case ISA_TYPE_V:
1889             case ISA_TYPE_UV:
1890                  break;
1891             case ISA_TYPE_UQ:
1892             case ISA_TYPE_Q:
1893                  REPORT_INSTRUCTION(options,opcode != ISA_FBL && opcode != ISA_FBH && opcode != ISA_CBIT,
1894                     "fbl/fbh/cbit does not support Q/UQ type.");
1895                  break;
1896             case ISA_TYPE_BOOL:
1897             {
1898                  pred_logic = true;
1899                  REPORT_INSTRUCTION(options, inst->pred.isNullPred(),
1900                     "Predicate can not be used in logic operantion for predicate operands.");
1901                  break;
1902             }
1903             case ISA_TYPE_DF:
1904             case ISA_TYPE_F:
1905             case ISA_TYPE_HF:
1906             {
1907                  REPORT_INSTRUCTION(options,false,
1908                         "All operands of logic instructions must be of integral type! opnd %d has float type %d",
1909                         i, (int)(opnd_type));
1910                  break;
1911             }
1912             default:
1913             {
1914                 REPORT_INSTRUCTION(options,false,
1915                          "All operands of logic instructions must be of integral type! opnd %d has unknow type %d",
1916                          i, (int)(opnd_type));
1917             }
1918         }
1919     }
1920 }
1921 
verifyInstructionCompare(const CISA_INST * inst)1922 void vISAVerifier::verifyInstructionCompare(
1923     const CISA_INST* inst)
1924 {
1925     ///     opnd0              opnd1  opnd2 opnd3
1926     /// cmp.rel_op (exec_size) dst    src1  src2
1927 
1928     ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
1929     ASSERT_USER(ISA_CMP == opcode, "illegal opcode for compare instruction");
1930 
1931     for (unsigned i = 0; i < inst->opnd_count; i++)
1932     {
1933         if (i > 0)
1934         {
1935             Common_ISA_Operand_Class operand_class = getVectorOperand(inst, i).getOperandClass();
1936             switch (i)
1937             {
1938                 case 1:
1939                     REPORT_INSTRUCTION(options,operand_class == OPERAND_PREDICATE || operand_class == OPERAND_GENERAL,
1940                                        "CISA compare instruction destination only supports a predicate operand.");
1941                     break;
1942                 default:
1943                     REPORT_INSTRUCTION(options,operand_class != OPERAND_ADDRESS && operand_class != OPERAND_PREDICATE,
1944                                        "CISA compare instruction sources do not support address or predicate operands.");
1945                     break;
1946             }
1947         }
1948         else
1949         {
1950             /// TODO: Verify rel_op
1951         }
1952     }
1953 }
1954 
verifyInstructionAddress(const CISA_INST * inst)1955 void vISAVerifier::verifyInstructionAddress(
1956     const CISA_INST* inst)
1957 {
1958     ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
1959     ASSERT_USER(ISA_ADDR_ADD == opcode, "Illegal opcode for address instruction.");
1960 
1961     for (unsigned i = 0; i < inst->opnd_count; i++)
1962     {
1963         Common_ISA_Operand_Class operand_class = getVectorOperand(inst, i).getOperandClass();
1964 
1965         if (0 == i)
1966         {
1967             REPORT_INSTRUCTION(options,operand_class == OPERAND_ADDRESS,
1968                               "CISA address instruction destination only supports an address operand.");
1969             continue;
1970         }
1971 
1972         REPORT_INSTRUCTION(options,operand_class != OPERAND_PREDICATE,
1973                           "CISA ADDR_ADD instruction sources do not support predicate operands.");
1974         if (1 == i)
1975         {
1976             if (operand_class == OPERAND_GENERAL)
1977             {
1978                 uint32_t numPredefinedVars = Get_CISA_PreDefined_Var_Count();
1979                 uint32_t varIndex = getVectorOperand(inst, i).opnd_val.gen_opnd.index;
1980                 REPORT_INSTRUCTION(options, varIndex >= numPredefinedVars, "Can not take the address of a pre-defined variable");
1981             }
1982             else if (operand_class == OPERAND_STATE)
1983             {
1984                 if (getVectorOperand(inst, i).getStateOpClass() == STATE_OPND_SURFACE)
1985                 {
1986                     uint32_t numPredefinedSurfs = Get_CISA_PreDefined_Surf_Count();
1987                     uint32_t surfIndex = getVectorOperand(inst, i).opnd_val.state_opnd.index;
1988                     REPORT_INSTRUCTION(options, surfIndex >= numPredefinedSurfs, "Can not take the address of a pre-defined surface");
1989                 }
1990             }
1991         }
1992 
1993         if (2 == i)
1994         {
1995             VISA_Type opnd_type = getVectorOperandType(header, getVectorOperand(inst, i));
1996             REPORT_INSTRUCTION(options,opnd_type == ISA_TYPE_B || opnd_type == ISA_TYPE_UB ||
1997                               opnd_type == ISA_TYPE_W || opnd_type == ISA_TYPE_UW,
1998                               "Data type of the second source of ADDR_ADD should be WORD or BYTE.");
1999         }
2000 
2001     }
2002 }
2003 
verifyInstructionSampler(const CISA_INST * inst)2004 void vISAVerifier::verifyInstructionSampler(const CISA_INST* inst)
2005 {
2006     ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
2007     unsigned numPreDefinedSurfs = Get_CISA_PreDefined_Surf_Count();
2008     unsigned i = 0;
2009 
2010     switch (opcode)
2011     {
2012         case ISA_SAMPLE_UNORM:
2013         {
2014             uint8_t channel = getPrimitiveOperand<uint8_t>(inst, i++);
2015             REPORT_INSTRUCTION(options,channel, "CISA SAMPLER ISA_SAMPLE_UNORM instruction only accepts non-zero channel masks.");
2016 
2017             uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
2018             REPORT_INSTRUCTION(options,sampler < header->getSamplerCount(), "CISA SAMPLER ISA_SAMPLE_UNORM instruction uses undeclared sampler.");
2019 
2020             uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2021             REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for the SAMPLER instruction ISA_SAMPLE_UNORM.");
2022             REPORT_INSTRUCTION(options,surface-numPreDefinedSurfs< header->getSurfaceCount(),
2023                 "CISA SAMPLER instruction ISA_SAMPLE_UNORM uses undefined surface.");
2024 
2025             Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2026             REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL  ||
2027                                operand_class_uoff == OPERAND_INDIRECT ||
2028                                operand_class_uoff == OPERAND_IMMEDIATE,
2029                                "u_offset operand of CISA SAMPLER ISA_SAMPLE_UNORM instrution should "
2030                                "be either a general, indirect, or immediate operand.");
2031 
2032             Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2033             REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL  ||
2034                                operand_class_voff == OPERAND_INDIRECT ||
2035                                operand_class_voff == OPERAND_IMMEDIATE,
2036                                "v_offset operand of CISA SAMPLER ISA_SAMPLE_UNORM instrution should "
2037                                "be either a general, indirect, or immediate operand.");
2038 
2039 
2040             Common_ISA_Operand_Class operand_class_udelta = getVectorOperand(inst, i++).getOperandClass();
2041             REPORT_INSTRUCTION(options,operand_class_udelta == OPERAND_GENERAL  ||
2042                                operand_class_udelta == OPERAND_INDIRECT ||
2043                                operand_class_udelta == OPERAND_IMMEDIATE,
2044                                "u_delta operand of CISA SAMPLER ISA_SAMPLE_UNORM instrution should "
2045                                "be either a general, indirect, or immediate operand.");
2046 
2047             Common_ISA_Operand_Class operand_class_vdelta = getVectorOperand(inst, i++).getOperandClass();
2048             REPORT_INSTRUCTION(options,operand_class_vdelta == OPERAND_GENERAL  ||
2049                                operand_class_vdelta == OPERAND_INDIRECT ||
2050                                operand_class_vdelta == OPERAND_IMMEDIATE,
2051                                "v_delta operand of CISA SAMPLER ISA_SAMPLE_UNORM instrution should "
2052                                "be either a general, indirect, or immediate operand.");
2053 
2054             /// dst: TODO
2055 
2056             break;
2057         }
2058         case ISA_LOAD:
2059         case ISA_SAMPLE:
2060         {
2061             uint8_t mod = getPrimitiveOperand<uint8_t>(inst, i++);
2062 
2063             if (opcode == ISA_SAMPLE)
2064             {
2065                 uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
2066                 REPORT_INSTRUCTION(options,sampler < header->getSamplerCount(), "CISA SAMPLER SAMPLE/LOAD instruction uses undeclared sampler.");
2067             }
2068 
2069             uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2070             REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for the SAMPLER instruction ISA_SAMPLE/ISA_LOAD.");
2071             REPORT_INSTRUCTION(options,surface-numPreDefinedSurfs < header->getSurfaceCount(),
2072                 "CISA SAMPLER instruction ISA_SAMPLE/ISA_LOAD uses undefined surface.");
2073 
2074             uint8_t channel = mod & 0xF;
2075             REPORT_INSTRUCTION(options,channel, "CISA SAMPLER ISA_SAMPLE/ISA_LOAD instruction only accepts non-zero channel masks.");
2076 
2077             uint8_t SIMD_mode = (mod >> 4) & 0x3;
2078             if ((unsigned)SIMD_mode == 0)
2079             {
2080                 SIMD_mode = 8;
2081             }
2082             else if ((unsigned)SIMD_mode == 1)
2083             {
2084                 SIMD_mode = 16;
2085             }
2086             else
2087             {
2088                 REPORT_INSTRUCTION(options,false, "Illegal SIMD mode used in ISA_SAMPLE/ISA_LOAD inst.");
2089             }
2090 
2091             /// u/r/v/dst:TODO
2092 
2093             break;
2094         }
2095         case ISA_3D_SAMPLE:
2096         {
2097             uint8_t value = getPrimitiveOperand<uint8_t>(inst, i++);
2098             bool pixelNullMask = (value & (1<<5)) != 0;
2099             bool cpsEnable = (value & (1<<6)) != 0;
2100             VISASampler3DSubOpCode subOp = VISASampler3DSubOpCode(value & 0x1F);
2101 
2102             if (pixelNullMask)
2103             {
2104                 REPORT_INSTRUCTION(options, getGenxPlatform() >= GENX_SKL,
2105                                    "Pixel Null Mask Enable only valid for SKL+");
2106             }
2107 
2108             if (cpsEnable)
2109             {
2110                 auto execSize = inst->getExecSize();
2111 
2112                 REPORT_INSTRUCTION(options,
2113                                    execSize == EXEC_SIZE_8 || execSize == EXEC_SIZE_16,
2114                                    "CPS LOD Compensation Enable must be disabled unless"
2115                                    " SIMD mode is simd8* or simd16*");
2116 
2117                 bool isSupportedOp = subOp == VISA_3D_SAMPLE ||
2118                                      subOp == VISA_3D_SAMPLE_B ||
2119                                      subOp == VISA_3D_SAMPLE_C ||
2120                                      subOp == VISA_3D_SAMPLE_B_C ||
2121                                      subOp == VISA_3D_LOD;
2122 
2123                 REPORT_INSTRUCTION(options, isSupportedOp,
2124                                    "CPS LOD Compensation Enable is only supported for"
2125                                    " sample, sample_b, sample_b_c, sample_c and LOD");
2126             }
2127             break;
2128         }
2129         case ISA_3D_LOAD:
2130         case ISA_3D_GATHER4:
2131         {
2132             uint8_t value = getPrimitiveOperand<uint8_t>(inst, i++);
2133             bool pixelNullMask = (value >> 5) != 0;
2134 
2135             if (pixelNullMask)
2136             {
2137                 REPORT_INSTRUCTION(options, getGenxPlatform() >= GENX_SKL,
2138                                    "Pixel Null Mask Enable only valid for SKL+");
2139             }
2140             break;
2141         }
2142         case ISA_3D_INFO:
2143         case ISA_3D_RT_WRITE:
2144         case ISA_3D_URB_WRITE:
2145         {
2146             // TODO: Add verification code for 3d specific opcodes
2147             break;
2148         }
2149         case ISA_AVS:
2150         {
2151             uint8_t channel = getPrimitiveOperand<uint8_t>(inst, i++);
2152             REPORT_INSTRUCTION(options,channel, "CISA SAMPLER AVS instruction only accepts non-zero channel masks.");
2153 
2154             uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
2155             REPORT_INSTRUCTION(options,sampler < header->getSamplerCount(), "CISA VA MINMAXFILTER instruction uses undeclared sampler.");
2156 
2157             uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2158             REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for the SAMPLER AVS instruction.");
2159             REPORT_INSTRUCTION(options,surface < numPreDefinedSurfs + header->getSurfaceCount(),
2160                 "CISA VA instruction MINMAX uses undefined surface.");
2161 
2162             Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2163             REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL  ||
2164                                operand_class_uoff == OPERAND_INDIRECT ||
2165                                operand_class_uoff == OPERAND_IMMEDIATE,
2166                                "u_offset operand of CISA SAMPLER AVS instrution should "
2167                                "be either a general, indirect, or immediate operand.");
2168 
2169             Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2170             REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL  ||
2171                                operand_class_voff == OPERAND_INDIRECT ||
2172                                operand_class_voff == OPERAND_IMMEDIATE,
2173                                "v_offset operand of CISA SAMPLER AVS instrution should "
2174                                "be either a general, indirect, or immediate operand.");
2175 
2176             Common_ISA_Operand_Class operand_class_udelta = getVectorOperand(inst, i++).getOperandClass();
2177             REPORT_INSTRUCTION(options,operand_class_udelta == OPERAND_GENERAL  ||
2178                                operand_class_udelta == OPERAND_INDIRECT ||
2179                                operand_class_udelta == OPERAND_IMMEDIATE,
2180                                "u_delta operand of CISA SAMPLER AVS instrution should "
2181                                "be either a general, indirect, or immediate operand.");
2182 
2183             Common_ISA_Operand_Class operand_class_vdelta = getVectorOperand(inst, i++).getOperandClass();
2184             REPORT_INSTRUCTION(options,operand_class_vdelta == OPERAND_GENERAL  ||
2185                                operand_class_vdelta == OPERAND_INDIRECT ||
2186                                operand_class_vdelta == OPERAND_IMMEDIATE,
2187                                "v_delta operand of CISA SAMPLER AVS instrution should "
2188                                "be either a general, indirect, or immediate operand.");
2189 
2190             Common_ISA_Operand_Class operand_class_u2d = getVectorOperand(inst, i++).getOperandClass();
2191             REPORT_INSTRUCTION(options,operand_class_u2d == OPERAND_GENERAL  ||
2192                                operand_class_u2d == OPERAND_INDIRECT ||
2193                                operand_class_u2d == OPERAND_IMMEDIATE,
2194                                "u2d operand of CISA SAMPLER AVS instrution should "
2195                                "be either a general, indirect, or immediate operand.");
2196 
2197             Common_ISA_Operand_Class operand_class_groupid = getVectorOperand(inst, i++).getOperandClass();
2198             REPORT_INSTRUCTION(options,operand_class_groupid == OPERAND_GENERAL  ||
2199                                operand_class_groupid == OPERAND_INDIRECT ||
2200                                operand_class_groupid == OPERAND_IMMEDIATE,
2201                                "groupid operand of CISA SAMPLER AVS instrution should "
2202                                "be either a general, indirect, or immediate operand.");
2203 
2204             Common_ISA_Operand_Class operand_class_verticalBlockNumber = getVectorOperand(inst, i++).getOperandClass();
2205             REPORT_INSTRUCTION(options,operand_class_verticalBlockNumber == OPERAND_GENERAL  ||
2206                                operand_class_verticalBlockNumber == OPERAND_INDIRECT ||
2207                                operand_class_verticalBlockNumber == OPERAND_IMMEDIATE,
2208                                "verticalBlockNumber operand of CISA SAMPLER AVS instrution should "
2209                                "be either a general, indirect, or immediate operand.");
2210 
2211             uint8_t cntrl = ((getPrimitiveOperand<uint8_t>(inst, i++)) & 0xF);
2212 
2213             switch (cntrl)
2214             {
2215                 case 0:
2216                 case 1:
2217                 case 2:
2218                 case 3: break;
2219                 default: REPORT_INSTRUCTION(options,false, "cntrl for CISA SAMPLER AVS intruction should be a "
2220                                                   "value 0-3 (8/16bit full/chrominance down sample).");
2221             }
2222 
2223             Common_ISA_Operand_Class operand_class_v2d = getVectorOperand(inst, i++).getOperandClass();
2224             REPORT_INSTRUCTION(options,operand_class_v2d == OPERAND_GENERAL  ||
2225                                operand_class_v2d == OPERAND_INDIRECT ||
2226                                operand_class_v2d == OPERAND_IMMEDIATE,
2227                                "v2d operand of CISA SAMPLER AVS instrution should "
2228                                "be either a general, indirect, or immediate operand.");
2229 
2230             uint8_t execMode = ((getPrimitiveOperand<uint8_t>(inst, i++)) & 0xF);
2231 
2232             switch (execMode)
2233             {
2234                 case 0:
2235                 case 1:
2236                 case 2:
2237                 case 3: break;
2238                 default: REPORT_INSTRUCTION(options,false, "execMode for CISA SAMPLER AVS intruction should "
2239                                                   "be a value 0-3 (16x4, 8x4, 16x8, or 4x4).");
2240             }
2241 
2242             Common_ISA_Operand_Class operand_class_iefbypass = getVectorOperand(inst, i++).getOperandClass();
2243             REPORT_INSTRUCTION(options,operand_class_iefbypass == OPERAND_GENERAL ||
2244                                operand_class_iefbypass == OPERAND_INDIRECT ||
2245                                operand_class_iefbypass == OPERAND_IMMEDIATE,
2246                                "iefbypass operand of CISA SAMPLER AVS instruction should "
2247                                "be either a general, indirect, or immediate operand.");
2248 
2249             /// dst: TODO
2250 
2251             break;
2252         }
2253         case ISA_VA:
2254         {
2255             ISA_VA_Sub_Opcode subOpcode = (ISA_VA_Sub_Opcode)getPrimitiveOperand<uint8_t>(inst, i++);
2256              switch (subOpcode)
2257              {
2258                  case MINMAX_FOPCODE:
2259                  {
2260                      uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2261                      REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for VA instructions.");
2262                      REPORT_INSTRUCTION(options,surface-numPreDefinedSurfs< header->getSurfaceCount(),
2263                          "CISA VA instruction MINMAX uses undefined surface.");
2264 
2265                      Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2266                      REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL  ||
2267                                         operand_class_uoff == OPERAND_INDIRECT ||
2268                                         operand_class_uoff == OPERAND_IMMEDIATE,
2269                                         "u_offset operand of CISA MINMAX instrution should "
2270                                         "be either a general, indirect, or immediate operand.");
2271 
2272                      Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2273                      REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL  ||
2274                                         operand_class_voff == OPERAND_INDIRECT ||
2275                                         operand_class_voff == OPERAND_IMMEDIATE,
2276                                         "v_offset operand of CISA MINMAX instrution should "
2277                                         "be either a general, indirect, or immediate operand.");
2278 
2279                      /// mmf mode
2280                      const vector_opnd& mmf = getVectorOperand(inst, i++);
2281                      if (mmf.getOperandClass() == OPERAND_IMMEDIATE)
2282                      {
2283                          unsigned val = mmf.opnd_val.const_opnd._val.ival;
2284                          ASSERT_USER(val <= VA_MIN_ENABLE, "MINMAX MMF Mode operand out of range.");
2285                      }
2286 
2287                      /// dst: TODO
2288 
2289                      break;
2290                  }
2291                  case MINMAXFILTER_FOPCODE:
2292                  {
2293                      uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
2294                      REPORT_INSTRUCTION(options,sampler < header->getSamplerCount(), "CISA VA MINMAXFILTER instruction uses undeclared sampler.");
2295 
2296                      uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2297                      REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for VA instructions.");
2298                      REPORT_INSTRUCTION(options,surface-numPreDefinedSurfs< header->getSurfaceCount(),
2299                          "CISA VA instruction MINMAXFILTER uses undefined surface.");
2300 
2301                      Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2302                      REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL  ||
2303                                         operand_class_uoff == OPERAND_INDIRECT ||
2304                                         operand_class_uoff == OPERAND_IMMEDIATE,
2305                                         "u_offset operand of CISA MINMAXFILTER instrution should "
2306                                         "be either a general, indirect, or immediate operand.");
2307 
2308                      Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2309                      REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL  ||
2310                                         operand_class_voff == OPERAND_INDIRECT ||
2311                                         operand_class_voff == OPERAND_IMMEDIATE,
2312                                         "v_offset operand of CISA MINMAXFILTER instrution should "
2313                                         "be either a general, indirect, or immediate operand.");
2314 
2315                      getPrimitiveOperand<uint8_t>(inst, i++); // uint8_t cntrl, &0xf
2316                      getPrimitiveOperand<uint8_t>(inst, i++); // uint8_t execMode, &0xf
2317 
2318                      /// mmf mode
2319                      const vector_opnd& mmf = getVectorOperand(inst, i++);
2320                      if (mmf.getOperandClass() == OPERAND_IMMEDIATE)
2321                      {
2322                          unsigned val = mmf.opnd_val.const_opnd._val.ival;
2323                          ASSERT_USER(val <= VA_MIN_ENABLE, "MINMAXFILTER MMF Mode operand out of range.");
2324                      }
2325 
2326                      /// dst
2327 
2328                      break;
2329                  }
2330                  case BoolCentroid_FOPCODE:
2331                  case Centroid_FOPCODE:
2332                  {
2333                      uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2334                      REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for VA instructions.");
2335                      REPORT_INSTRUCTION(options,surface-numPreDefinedSurfs< header->getSurfaceCount(),
2336                          "CISA VA VA CENTROID/BOOLCENTROID instruction MINMAX uses undefined surface.");
2337 
2338                      Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2339                      REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL  ||
2340                                         operand_class_uoff == OPERAND_INDIRECT ||
2341                                         operand_class_uoff == OPERAND_IMMEDIATE,
2342                                         "u_offset operand of CISA VA CENTROID/BOOLCENTROID instrution should "
2343                                         "be either a general, indirect, or immediate operand.");
2344 
2345                      Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2346                      REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL  ||
2347                                         operand_class_voff == OPERAND_INDIRECT ||
2348                                         operand_class_voff == OPERAND_IMMEDIATE,
2349                                         "v_offset operand of CISA VA CENTROID/BOOLCENTROID instrution should "
2350                                         "be either a general, indirect, or immediate operand.");
2351 
2352                      Common_ISA_Operand_Class operand_class_vsize = getVectorOperand(inst, i++).getOperandClass();
2353                      REPORT_INSTRUCTION(options,operand_class_vsize == OPERAND_GENERAL  ||
2354                                         operand_class_vsize == OPERAND_INDIRECT ||
2355                                         operand_class_vsize == OPERAND_IMMEDIATE,
2356                                         "v_size operand of CISA VA CENTROID/BOOLCENTROID instrution should "
2357                                         "be either a general, indirect, or immediate operand.");
2358 
2359                      /// h size
2360                      if (subOpcode == BoolCentroid_FOPCODE)
2361                      {
2362                          Common_ISA_Operand_Class operand_class_hsize = getVectorOperand(inst, i++).getOperandClass();
2363                          REPORT_INSTRUCTION(options,operand_class_hsize == OPERAND_GENERAL  ||
2364                                             operand_class_hsize == OPERAND_INDIRECT ||
2365                                             operand_class_hsize == OPERAND_IMMEDIATE,
2366                                             "h_size operand of CISA VA CENTROID/BOOLCENTROID instrution should "
2367                                             "be either a general, indirect, or immediate operand.");
2368                      }
2369 
2370                      /// dst: TODO
2371 
2372                      break;
2373                  }
2374                  case Convolve_FOPCODE:
2375                  case Dilate_FOPCODE:
2376                  case ERODE_FOPCODE:
2377                  {
2378                      uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
2379                      REPORT_INSTRUCTION(options,sampler < header->getSamplerCount(), "CISA VA CONVOLVE/ERODE/DILATE instruction uses undeclared sampler.");
2380 
2381                      uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2382                      REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for VA instructions.");
2383                      REPORT_INSTRUCTION(options,surface-numPreDefinedSurfs < header->getSurfaceCount(),
2384                          "CISA VA CONVOLVE/ERODE/DILATE instruction MINMAX uses undefined surface.");
2385 
2386                      Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2387                      REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL  ||
2388                                         operand_class_uoff == OPERAND_INDIRECT ||
2389                                         operand_class_uoff == OPERAND_IMMEDIATE,
2390                                         "u_offset operand of CISA CONVOLVE/ERODE/DILATE instrution should "
2391                                         "be either a general, indirect, or immediate operand.");
2392 
2393                      Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2394                      REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL  ||
2395                                         operand_class_voff == OPERAND_INDIRECT ||
2396                                         operand_class_voff == OPERAND_IMMEDIATE,
2397                                         "v_offset operand of CISA CONVOLVE/ERODE/DILATE instrution should "
2398                                         "be either a general, indirect, or immediate operand.");
2399 
2400                      /// uint8_t execMode   = ((getPrimitiveOperand<uint8_t>(inst, i)) & 0x3);
2401                      /// uint8_t regionSize = ((getPrimitiveOperand<uint8_t>(inst, i)) & 0xC) >> 0x2;
2402                      /// dst: TODO
2403 
2404                      break;
2405                  }
2406                  default:
2407                      REPORT_INSTRUCTION(options,false, "Invalid VA sub-opcode: %d.", subOpcode);
2408              }
2409 
2410              break;
2411         }
2412         case ISA_VA_SKL_PLUS:
2413         {
2414             ISA_VA_Sub_Opcode subOpcode = (ISA_VA_Sub_Opcode)getPrimitiveOperand<uint8_t>(inst, i++);
2415             switch (subOpcode)
2416             {
2417                 case VA_OP_CODE_LBP_CORRELATION:
2418                 {
2419                      uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2420                      REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for VA++ instructions.");
2421                      REPORT_INSTRUCTION(options,surface-numPreDefinedSurfs < header->getSurfaceCount(),
2422                          "CISA VA++ instruction LBP Correlation uses undefined surface.");
2423 
2424                      Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2425                      REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL  ||
2426                                         operand_class_uoff == OPERAND_INDIRECT ||
2427                                         operand_class_uoff == OPERAND_IMMEDIATE,
2428                                         "u_offset operand of CISA LBP Correlation instrution "
2429                                         "should be either a general, indirect, or immediate operand.");
2430 
2431                      Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2432                      REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL  ||
2433                                         operand_class_voff == OPERAND_INDIRECT ||
2434                                         operand_class_voff == OPERAND_IMMEDIATE,
2435                                         "v_offset operand of CISA LBP Correlation instrution "
2436                                         "should be either a general, indirect, or immediate operand.");
2437 
2438                      Common_ISA_Operand_Class operand_class_disparity = getVectorOperand(inst, i++).getOperandClass();
2439                      REPORT_INSTRUCTION(options,operand_class_disparity == OPERAND_GENERAL  ||
2440                                         operand_class_disparity == OPERAND_INDIRECT ||
2441                                         operand_class_disparity == OPERAND_IMMEDIATE,
2442                                         "Disparity operand of CISA LBP Correlation instrution "
2443                                         "should be either a general, indirect, or immediate operand.");
2444 
2445                      /// dst
2446                      /// TODO: Check dst for type W for for GRF alignment
2447 
2448                      break;
2449                 }
2450                 case VA_OP_CODE_1PIXEL_CONVOLVE:
2451                 case VA_OP_CODE_1D_CONVOLVE_VERTICAL:
2452                 case VA_OP_CODE_1D_CONVOLVE_HORIZONTAL:
2453                 {
2454                      uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
2455                      REPORT_INSTRUCTION(options,sampler < header->getSamplerCount(), "CISA VA++ instruction uses undeclared sampler.");
2456 
2457                      uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2458                      REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for VA++ instructions.");
2459                      REPORT_INSTRUCTION(options,surface-numPreDefinedSurfs < header->getSurfaceCount(),
2460                          "CISA VA++ instruction uses undefined surface.");
2461 
2462                      Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2463                      REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL  ||
2464                                         operand_class_uoff == OPERAND_INDIRECT ||
2465                                         operand_class_uoff == OPERAND_IMMEDIATE,
2466                                         "u_offset operand of CISA VA++ instrution "
2467                                         "should be either a general, indirect, or immediate operand.");
2468 
2469                      Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2470                      REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL  ||
2471                                         operand_class_voff == OPERAND_INDIRECT ||
2472                                         operand_class_voff == OPERAND_IMMEDIATE,
2473                                         "v_offset operand of CISA VA++ instrution "
2474                                         "should be either a general, indirect, or immediate operand.");
2475 
2476                      uint8_t mode = ((getPrimitiveOperand<uint8_t>(inst, i++)) & 0xF);
2477 
2478                      switch (mode & 0x3)
2479                      {
2480                          case 0: break;
2481                          case 2: break;
2482                          case 3: break;
2483                          default: REPORT_INSTRUCTION(options,false, "Invalid mode field for CISA VA++ instruction. "
2484                                                            "Only 4x16, 1x16, and 1x1 (in the case of "
2485                                                            "1 pixel convolve) are supported.");
2486                      }
2487 
2488                      break;
2489                 }
2490                 case VA_OP_CODE_LBP_CREATION:
2491                 {
2492                      uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2493                      REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for VA++ instructions.");
2494                      REPORT_INSTRUCTION(options,surface-numPreDefinedSurfs < header->getSurfaceCount(),
2495                          "CISA LBP Creation VA++ instruction uses undefined surface.");
2496 
2497                      Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2498                      REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL  ||
2499                                         operand_class_uoff == OPERAND_INDIRECT ||
2500                                         operand_class_uoff == OPERAND_IMMEDIATE,
2501                                         "u_offset operand of CISA LBP Creation VA++ instrution "
2502                                         "should be either a general, indirect, or immediate operand.");
2503 
2504                      Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2505                      REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL  ||
2506                                         operand_class_voff == OPERAND_INDIRECT ||
2507                                         operand_class_voff == OPERAND_IMMEDIATE,
2508                                         "v_offset operand of CISA LBP Creation VA++ instrution "
2509                                         "should be either a general, indirect, or immediate operand.");
2510 
2511                      uint8_t mode = ((getPrimitiveOperand<uint8_t>(inst, i++)) & 0xF);
2512 
2513                      switch (mode & 0x3)
2514                      {
2515                          case 0: break;
2516                          case 1: break;
2517                          case 2: break;
2518                          default: REPORT_INSTRUCTION(options,false, "Invalid mode field for CISA LBP Creation VA++ instruction. "
2519                                                            "Only 5x5, 3x3, or both modes are supported.");
2520                      }
2521 
2522                      /// dst
2523                      /// TODO: Checks for modes/types/decls
2524 
2525                      break;
2526                 }
2527                 case VA_OP_CODE_FLOOD_FILL:
2528                 {
2529                      getPrimitiveOperand<uint8_t>(inst, i++);   // uint8_t is8Connect
2530 
2531                      i++; /// h-mask
2532 
2533                      Common_ISA_Operand_Class operand_class_vmask_left = getVectorOperand(inst, i++).getOperandClass();
2534                      REPORT_INSTRUCTION(options,operand_class_vmask_left == OPERAND_GENERAL  ||
2535                                         operand_class_vmask_left == OPERAND_INDIRECT ||
2536                                         operand_class_vmask_left == OPERAND_IMMEDIATE,
2537                                         "Pixel direction v-mask left of CISA VA++ FloodFill instruction only "
2538                                         "supports general, indirect, and immediate operands.");
2539 
2540                      Common_ISA_Operand_Class operand_class_vmask_right = getVectorOperand(inst, i++).getOperandClass();
2541                      REPORT_INSTRUCTION(options,operand_class_vmask_right == OPERAND_GENERAL  ||
2542                                         operand_class_vmask_right == OPERAND_INDIRECT ||
2543                                         operand_class_vmask_right == OPERAND_IMMEDIATE,
2544                                         "Pixel direction v-mask right of CISA VA++ FloodFill instruction only "
2545                                         "supports general, indirect, and immediate operands.");
2546 
2547                      Common_ISA_Operand_Class operand_class_loopcount = getVectorOperand(inst, i++).getOperandClass();
2548                      REPORT_INSTRUCTION(options,operand_class_loopcount == OPERAND_GENERAL  ||
2549                                         operand_class_loopcount == OPERAND_INDIRECT ||
2550                                         operand_class_loopcount == OPERAND_IMMEDIATE,
2551                                         "loop_count of Common ISA sample instrution is invalid type.");
2552 
2553                      break;
2554                 }
2555                 case VA_OP_CODE_CORRELATION_SEARCH:
2556                 {
2557                      uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2558                      REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for VA++ instructions.");
2559                      REPORT_INSTRUCTION(options,surface < numPreDefinedSurfs + header->getSurfaceCount(),
2560                          "CISA VA++ instruction uses undefined surface.");
2561 
2562                      Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2563                      REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL  ||
2564                                         operand_class_uoff == OPERAND_INDIRECT ||
2565                                         operand_class_uoff == OPERAND_IMMEDIATE,
2566                                         "u_offset of Common ISA Meida LD/ST instrution "
2567                                         "should not be address or predicate operand.");
2568 
2569                      Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2570                      REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL  ||
2571                                         operand_class_voff == OPERAND_INDIRECT ||
2572                                         operand_class_voff == OPERAND_IMMEDIATE,
2573                                         "v_offset of Common ISA Meida LD/ST instrution "
2574                                         "should not be address or predicate operand.");
2575 
2576                      Common_ISA_Operand_Class operand_class_verticalOrigin = getVectorOperand(inst, i++).getOperandClass();
2577                      REPORT_INSTRUCTION(options,operand_class_verticalOrigin == OPERAND_GENERAL  ||
2578                                         operand_class_verticalOrigin == OPERAND_INDIRECT ||
2579                                         operand_class_verticalOrigin == OPERAND_IMMEDIATE,
2580                                         "CISA VA++ instruction Correlation search operand verticalOrigin "
2581                                         "can only be of operand class general, indirect, or immediate.");
2582 
2583                      Common_ISA_Operand_Class operand_class_horizontalOrigin = getVectorOperand(inst, i++).getOperandClass();
2584                      REPORT_INSTRUCTION(options,operand_class_horizontalOrigin == OPERAND_GENERAL  ||
2585                                         operand_class_horizontalOrigin == OPERAND_INDIRECT ||
2586                                         operand_class_horizontalOrigin == OPERAND_IMMEDIATE,
2587                                         "CISA VA++ instruction Correlation search operand horizontalOrigin "
2588                                         "can only be of operand class general, indirect, or immediate.");
2589 
2590                      Common_ISA_Operand_Class operand_class_xDirectionSize = getVectorOperand(inst, i++).getOperandClass();
2591                      REPORT_INSTRUCTION(options,operand_class_xDirectionSize == OPERAND_GENERAL  ||
2592                                         operand_class_xDirectionSize == OPERAND_INDIRECT ||
2593                                         operand_class_xDirectionSize == OPERAND_IMMEDIATE,
2594                                         "CISA VA++ instruction Correlation search operand xDirectionSize "
2595                                         "can only be of operand class general, indirect, or immediate.");
2596 
2597                      Common_ISA_Operand_Class operand_class_yDirectionSize = getVectorOperand(inst, i++).getOperandClass();
2598                      REPORT_INSTRUCTION(options,operand_class_yDirectionSize == OPERAND_GENERAL  ||
2599                                         operand_class_yDirectionSize == OPERAND_INDIRECT ||
2600                                         operand_class_yDirectionSize == OPERAND_IMMEDIATE,
2601                                         "CISA VA++ instruction Correlation search operand yDirectionSize "
2602                                         "can only be of operand class general, indirect, or immediate.");
2603 
2604                      Common_ISA_Operand_Class operand_class_xDirectionSearchSize = getVectorOperand(inst, i++).getOperandClass();
2605                      REPORT_INSTRUCTION(options,operand_class_xDirectionSearchSize == OPERAND_GENERAL  ||
2606                                         operand_class_xDirectionSearchSize == OPERAND_INDIRECT ||
2607                                         operand_class_xDirectionSearchSize == OPERAND_IMMEDIATE,
2608                                         "CISA VA++ instruction Correlation search operand xDirectionSearchSize "
2609                                         "can only be of operand class general, indirect, or immediate.");
2610 
2611                      Common_ISA_Operand_Class operand_class_yDirectionSearchSize = getVectorOperand(inst, i++).getOperandClass();
2612                      REPORT_INSTRUCTION(options,operand_class_yDirectionSearchSize == OPERAND_GENERAL  ||
2613                                         operand_class_yDirectionSearchSize == OPERAND_INDIRECT ||
2614                                         operand_class_yDirectionSearchSize == OPERAND_IMMEDIATE,
2615                                         "CISA VA++ instruction Correlation search operand yDirectionSearchSize "
2616                                         "can only be of operand class general, indirect, or immediate.");
2617 
2618                      /// dst
2619                      /// TODO: Check dst type that it is only Type_D
2620 
2621                      break;
2622                 }
2623                 case ISA_HDC_CONV:
2624                 case ISA_HDC_ERODE:
2625                 case ISA_HDC_DILATE:
2626                 case ISA_HDC_LBPCORRELATION:
2627                 case ISA_HDC_LBPCREATION:
2628                 case ISA_HDC_MMF:
2629                 case ISA_HDC_1PIXELCONV:
2630                 case ISA_HDC_1DCONV_H:
2631                 case ISA_HDC_1DCONV_V:
2632                     {
2633                         if (subOpcode != ISA_HDC_LBPCORRELATION &&
2634                             subOpcode !=  ISA_HDC_LBPCREATION)
2635                         {
2636                             /// sampler
2637                             uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
2638                             REPORT_INSTRUCTION(options,sampler < header->getSamplerCount(), "CISA VA++ instruction uses undeclared sampler.");
2639                         }
2640 
2641                         //input surface
2642                         uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2643                         REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for VA++ instructions.");
2644                         REPORT_INSTRUCTION(options,surface < numPreDefinedSurfs + header->getSurfaceCount(),
2645                             "CISA VA++ instruction uses undefined surface.");
2646 
2647                         //u_offset
2648                         Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2649                         REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL  ||
2650                                            operand_class_uoff == OPERAND_INDIRECT ||
2651                                            operand_class_uoff == OPERAND_IMMEDIATE,
2652                                            "u_offset of Common ISA HDC INSTRUCTION "
2653                                            "should not be address or predicate operand.");
2654 
2655                         //v_offset
2656                         Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2657                         REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL  ||
2658                                            operand_class_voff == OPERAND_INDIRECT ||
2659                                            operand_class_voff == OPERAND_IMMEDIATE,
2660                                            "v_offset of Common ISA HDC instruction "
2661                                            "should not be address or predicate operand.");
2662 
2663                         if (subOpcode == ISA_HDC_CONV ||
2664                             subOpcode == ISA_HDC_MMF ||
2665                             subOpcode == ISA_HDC_1PIXELCONV ||
2666                             subOpcode == ISA_HDC_1DCONV_H ||
2667                             subOpcode == ISA_HDC_1DCONV_V)
2668                         {
2669                             //pixel size
2670                             //FOr 2D Convovle bit 4 is for indicating SKL or BDW mode
2671                             uint8_t pixel_size = getPrimitiveOperand<uint8_t>(inst, i++)&0XF;
2672                             REPORT_INSTRUCTION(options,pixel_size < 2, "CISA VA++ instruction uses invalid output pixel size.");
2673                         }
2674 
2675                         if (subOpcode == ISA_HDC_MMF ||
2676                             subOpcode == ISA_HDC_LBPCREATION)
2677                         {
2678                             //mode
2679                             uint8_t mode = getPrimitiveOperand<uint8_t>(inst, i++);
2680                             REPORT_INSTRUCTION(options,mode <= 2, "CISA VA++ instruction uses invalid mode.");
2681                         }
2682 
2683                         if (subOpcode == ISA_HDC_LBPCORRELATION)
2684                         {
2685                             /// disparity
2686                             Common_ISA_Operand_Class operand_class_disparity = getVectorOperand(inst, i++).getOperandClass();
2687                             REPORT_INSTRUCTION(options,operand_class_disparity == OPERAND_GENERAL  ||
2688                                                operand_class_disparity == OPERAND_INDIRECT ||
2689                                                operand_class_disparity == OPERAND_IMMEDIATE,
2690                                                "disparity of Common ISA HDC LBPCORRELATION "
2691                                                "should not be address or predicate operand.");
2692                         }
2693 
2694                         if (subOpcode == ISA_HDC_1PIXELCONV)
2695                         {
2696                             /// offsets raw operand
2697                             i++;
2698                         }
2699 
2700                         /// dst surface
2701                         uint8_t dstsurface = getPrimitiveOperand<uint8_t>(inst, i++);
2702                         REPORT_INSTRUCTION(options,0 != dstsurface, "Surface T0 (the SLM surface) is not allowed for VA++ instructions.");
2703                         REPORT_INSTRUCTION(options,dstsurface < numPreDefinedSurfs + header->getSurfaceCount(),
2704                             "CISA VA++ instruction uses undefined destination surface.");
2705 
2706                         /// x offset
2707                         Common_ISA_Operand_Class operand_class_xoff = getVectorOperand(inst, i++).getOperandClass();
2708                         REPORT_INSTRUCTION(options,operand_class_xoff == OPERAND_GENERAL  ||
2709                                            operand_class_xoff == OPERAND_INDIRECT ||
2710                                            operand_class_xoff == OPERAND_IMMEDIATE,
2711                                            "x_offset of Common ISA HDC instruction "
2712                                            "should not be address or predicate operand.");
2713 
2714                         /// y offset
2715                         Common_ISA_Operand_Class operand_class_yoff = getVectorOperand(inst, i++).getOperandClass();
2716                         REPORT_INSTRUCTION(options,operand_class_yoff == OPERAND_GENERAL  ||
2717                                            operand_class_yoff == OPERAND_INDIRECT ||
2718                                            operand_class_yoff == OPERAND_IMMEDIATE,
2719                                            "y_offset of Common ISA HDC instruction "
2720                                            "should not be address or predicate operand.");
2721                         break;
2722                     }
2723                 default:
2724                      REPORT_INSTRUCTION(options,false, "Invalid VA++ sub-opcode: %d.", subOpcode);
2725             }
2726 
2727             break;
2728         }
2729         default: REPORT_INSTRUCTION(options,false, "Illegal Sampler Instruction Opcode: %d, %s.", opcode, ISA_Inst_Table[opcode].str);
2730     }
2731 }
2732 
verifyInstructionSIMDFlow(const CISA_INST * inst)2733 void vISAVerifier::verifyInstructionSIMDFlow(
2734     const CISA_INST* inst)
2735 {
2736     ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
2737     switch (opcode)
2738     {
2739         case ISA_GOTO:
2740         {
2741             auto labelId = getPrimitiveOperand<uint16_t>(inst, 0);
2742             if (labelId >= header->getLabelCount())
2743             {
2744                 REPORT_INSTRUCTION(options, false, "bad label id %d", labelId);
2745             }
2746             else
2747             {
2748                 auto iter = labelDefs.find(labelId);
2749                 if (iter == labelDefs.end())
2750                 {
2751                     labelDefs[labelId] = false;
2752                 }
2753                 // nothing needs to be done if the label is already in the map
2754             }
2755             break;
2756         }
2757         default: REPORT_INSTRUCTION(options,false, "Illegal SIMD CF Instruction Opcode: %d, %s.", opcode, ISA_Inst_Table[opcode].str);
2758     }
2759 }
2760 
isUDType(VISA_Type T)2761 static bool isUDType(VISA_Type T)
2762 {
2763     return ISA_TYPE_UD == T;
2764 }
2765 
isDType(VISA_Type T)2766 static bool isDType(VISA_Type T)
2767 {
2768     return ISA_TYPE_D == T;
2769 }
2770 
isDorUDTYpe(VISA_Type T)2771 static bool isDorUDTYpe(VISA_Type T)
2772 {
2773     return isUDType(T) || isDType(T);
2774 }
2775 
isFType(VISA_Type T)2776 static bool isFType(VISA_Type T)
2777 {
2778     return ISA_TYPE_F == T;
2779 }
2780 
verifyInstructionDataport(const CISA_INST * inst)2781 void vISAVerifier::verifyInstructionDataport(
2782     const CISA_INST* inst)
2783 {
2784     ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
2785     unsigned numPreDefinedSurfs = Get_CISA_PreDefined_Surf_Count();
2786 
2787     unsigned i = 0;
2788 
2789     uint8_t surface  = 0;
2790     uint8_t modifier = 0;
2791 
2792     switch (opcode)
2793     {
2794         case ISA_MEDIA_ST:
2795         case ISA_MEDIA_LD:
2796         {
2797              uint8_t plane        = 0;
2798              uint8_t block_width  = 0;
2799              uint8_t block_height = 0;
2800 
2801              if (ISA_MEDIA_LD == opcode || ISA_MEDIA_ST == opcode)
2802              {
2803                  modifier = getPrimitiveOperand<uint8_t>(inst, i++); // for skipping the modifier
2804 
2805                  if (ISA_MEDIA_LD == opcode)
2806                      REPORT_INSTRUCTION(options,modifier < MEDIA_LD_Mod_NUM,
2807                              "MEDIA_LD modifier must be 0-5 not %d", modifier);
2808 
2809                  if (ISA_MEDIA_ST == opcode)
2810                      REPORT_INSTRUCTION(options,modifier < MEDIA_ST_Mod_NUM,
2811                              "MEDIA_ST modifier must be 0-3 not %d", modifier);
2812              }
2813 
2814              surface = getPrimitiveOperand<uint8_t>(inst, i++);
2815              REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for MEDIA_LD/MEDIA_ST");
2816              REPORT_INSTRUCTION(options,surface < numPreDefinedSurfs + header->getSurfaceCount(),
2817                  "CISA dataport instruction uses an undeclared surface.");
2818 
2819              if (ISA_MEDIA_LD == opcode || ISA_MEDIA_ST == opcode)
2820              {
2821                  plane = getPrimitiveOperand<uint8_t>(inst, i++);
2822                  REPORT_INSTRUCTION(options,plane <= 3, "MEDIA_LD/MEDIA_ST plane must be in the range [0, 3]: %d", plane);
2823              }
2824 
2825              block_width  = getPrimitiveOperand<uint8_t>(inst, i++);
2826              block_height = getPrimitiveOperand<uint8_t>(inst, i++);
2827 
2828              if (ISA_MEDIA_LD == opcode || ISA_MEDIA_ST == opcode)
2829              {
2830                  REPORT_INSTRUCTION(options,1 <= block_width && block_width <= COMMON_ISA_MAX_MEDIA_BLOCK_WIDTH_BDW_PLUS,
2831                          "MEDIA_LD/MEDIA_ST block width must be in the range [1, 32]: %d",
2832                          block_width);
2833 
2834                  REPORT_INSTRUCTION(options,1 <= block_height && block_height <= COMMON_ISA_MAX_MEDIA_BLOCK_HEIGHT,
2835                          "MEDIA_LD/MEDIA_ST block height must be in the range [1, 64]: %d",
2836                          block_height);
2837              }
2838 
2839              if (ISA_MEDIA_LD == opcode)
2840              {
2841                  REPORT_INSTRUCTION(options,((1  <= block_width && block_width <=  4 && block_height <= 64)  ||
2842                                     (5  <= block_width && block_width <=  8 && block_height <= 32)  ||
2843                                     (9  <= block_width && block_width <= 16 && block_height <= 16)  ||
2844                                     (17 <= block_width && block_width <= 32 && block_height <=  8)  ||
2845                                     (33 <= block_width && block_width <= 64 && block_height <=  4)) &&
2846                                     (block_width * block_height <= 256                          ),
2847                                     "MEDIA_LD only supports objects that fit into a single dataport "
2848                                     "transaction where block width <= 64 bytes and size <= 256 bytes. "
2849                                     "Block width: %d. Block height: %d", block_width, block_height);
2850              }
2851              else if (ISA_MEDIA_ST == opcode)
2852              {
2853                  REPORT_INSTRUCTION(options,((1  <= block_width && block_width <=  4 && block_height <= 64)  ||
2854                                     (5  <= block_width && block_width <=  8 && block_height <= 32)  ||
2855                                     (9  <= block_width && block_width <= 16 && block_height <= 16)  ||
2856                                     (17 <= block_width && block_width <= 32 && block_height <=  8)  ||
2857                                     (33 <= block_width && block_width <= 64 && block_height <=  4)) &&
2858                                     (block_width * block_height <= 256                          ),
2859                                     "MEDIA_ST only supports objects that fit into a single dataport "
2860                                     "transaction where block width <= 64 bytes and size <= 256 bytes. "
2861                                     "Block width: %d. Block height: %d", block_width, block_height);
2862              }
2863 
2864              Common_ISA_Operand_Class operand_class_xoff = getVectorOperand(inst, i++).getOperandClass();
2865              REPORT_INSTRUCTION(options,operand_class_xoff != OPERAND_ADDRESS && operand_class_xoff != OPERAND_PREDICATE,
2866                                "x_offset of Common ISA Meida LD/ST instrution should not be address or predicate operand.");
2867 
2868              Common_ISA_Operand_Class operand_class_yoff = getVectorOperand(inst, i++).getOperandClass();
2869              REPORT_INSTRUCTION(options,operand_class_yoff != OPERAND_ADDRESS && operand_class_yoff != OPERAND_PREDICATE,
2870                                "y_offset of Common ISA Meida LD/ST instrution should not be address or predicate operand.");
2871 
2872              break;
2873         }
2874         case ISA_OWORD_ST:
2875         case ISA_OWORD_LD:
2876         case ISA_OWORD_LD_UNALIGNED:
2877         {
2878              uint8_t size = getPrimitiveOperand<uint8_t>(inst, i++);
2879              size = size & 0x7;
2880 
2881              REPORT_INSTRUCTION(options,size < OWORD_NUM_ILLEGAL,
2882                      "OWORD_LD*/OWORD_ST size must be in the range [0, 3] "
2883                      "(ie, OWord block size must be 1/2/4/8. OWord block size: %d", size);
2884 
2885              if (ISA_OWORD_ST != opcode)
2886              {
2887                  modifier = getPrimitiveOperand<uint8_t>(inst, i++);
2888              }
2889 
2890              surface = getPrimitiveOperand<uint8_t>(inst, i++);
2891              if (getGenxPlatform() < GENX_ICLLP)
2892              {
2893                  REPORT_INSTRUCTION(options, 0 != surface, "Surface T0 (the SLM surface) is not allowed for OWORD_LD*/OWORD_ST");
2894              }
2895              REPORT_INSTRUCTION(options,surface < numPreDefinedSurfs + header->getSurfaceCount(),
2896                  "CISA dataport instruction uses an undeclared surface.");
2897 
2898              Common_ISA_Operand_Class operand_class = getVectorOperand(inst, i++).getOperandClass();
2899              REPORT_INSTRUCTION(options,operand_class != OPERAND_ADDRESS && operand_class != OPERAND_PREDICATE,
2900                                "Offset of Common ISA OWORD LD/ST instrutions should not be address or predicate operands.");
2901 
2902              break;
2903         }
2904         case ISA_GATHER:
2905         case ISA_SCATTER:
2906         {
2907              uint8_t elt_size = 0;
2908              uint8_t num_elts = 0;
2909              if (ISA_SCATTER == opcode || ISA_GATHER == opcode)
2910              {
2911                  elt_size = getPrimitiveOperand<uint8_t>(inst, i++);
2912                  elt_size = elt_size & 0x3;
2913                  switch ((GATHER_SCATTER_ELEMENT_SIZE)elt_size)
2914                  {
2915                      case GATHER_SCATTER_BYTE:
2916                          elt_size = 1;
2917                          break;
2918                      case GATHER_SCATTER_WORD:
2919                          elt_size = 2;
2920                          break;
2921                      case GATHER_SCATTER_DWORD:
2922                          elt_size = 4;
2923                          break;
2924                      default:
2925                          REPORT_INSTRUCTION(options,false, "Incorrect element size for Gather/Scatter CISA inst.");
2926                          break;
2927                  }
2928              }
2929 
2930              if (ISA_GATHER  == opcode)
2931                  getPrimitiveOperand<uint8_t>(inst, i++);
2932 
2933              num_elts = getPrimitiveOperand<uint8_t>(inst, i++);
2934              num_elts = num_elts & 0x3;
2935              if      ((unsigned)num_elts == 0) num_elts =  8;
2936              else if ((unsigned)num_elts == 1) num_elts = 16;
2937              else if ((unsigned)num_elts == 2) num_elts =  1;
2938 
2939              surface = getPrimitiveOperand<uint8_t>(inst, i++);
2940              //SLM uses surface0 as seen in nbody_SLM: gather
2941              REPORT_INSTRUCTION(options,surface < numPreDefinedSurfs + header->getSurfaceCount(),
2942                 "CISA dataport instruction uses an undeclared surface.");
2943 
2944              Common_ISA_Operand_Class operand_class_goff = getVectorOperand(inst, i++).getOperandClass();
2945              REPORT_INSTRUCTION(options,operand_class_goff != OPERAND_ADDRESS && operand_class_goff != OPERAND_PREDICATE,
2946                                "global_offset of Common ISA gather/scatter instrution should not be address or predicate operand.");
2947 
2948              // check that dst/src have dword type
2949              getRawOperand(inst, i++);  // const raw_opnd& elementOffset
2950              const raw_opnd& srcDst = getRawOperand(inst, i++);
2951              verifyRawOperandType(inst, srcDst, isDWordType);
2952              break;
2953         }
2954         case ISA_GATHER4_TYPED:
2955         case ISA_SCATTER4_TYPED:
2956         {
2957             if (getVersionAsInt(isaHeader.major_version, isaHeader.minor_version) >=
2958                 getVersionAsInt(3, 2))
2959             {
2960                 uint8_t ch_mask  = 0;
2961                 ch_mask = getPrimitiveOperand<uint8_t>(inst, i++);
2962                 ch_mask = ch_mask & 0xF;
2963                 REPORT_INSTRUCTION(options,ch_mask != 0x0, "At least one channel must be enabled for TYPED GATEHR4/SCATTER4");
2964 
2965                 surface = getPrimitiveOperand<uint8_t>(inst, i++);
2966                 REPORT_INSTRUCTION(options, (0 != surface && 5 != surface), "Surface T0/T5 (the SLM surface) is not allowed for TYPED SCATTTER4/GATHER4");
2967                 REPORT_INSTRUCTION(options,surface < numPreDefinedSurfs + header->getSurfaceCount(),
2968                     "CISA dataport TYPED SCATTTER4/GATHER4 instruction uses an undeclared surface.");
2969             }
2970              break;
2971         }
2972         case ISA_GATHER4_SCALED:
2973         case ISA_SCATTER4_SCALED:
2974         {
2975             break;
2976         }
2977         case ISA_GATHER_SCALED:
2978         case ISA_SCATTER_SCALED:
2979         {
2980             break;
2981         }
2982         case ISA_DWORD_ATOMIC:
2983         {
2984             unsigned subOpc = getPrimitiveOperand<uint8_t>(inst, i++);
2985             auto subOp = static_cast<VISAAtomicOps>(subOpc & 0x1F);
2986             switch (subOp) {
2987             default:
2988                 REPORT_INSTRUCTION(options, false, "Invalid DWORD ATOMIC sub op.");
2989             case ATOMIC_ADD:
2990             case ATOMIC_SUB:
2991             case ATOMIC_INC:
2992             case ATOMIC_DEC:
2993             case ATOMIC_MIN:
2994             case ATOMIC_MAX:
2995             case ATOMIC_XCHG:
2996             case ATOMIC_CMPXCHG:
2997             case ATOMIC_AND:
2998             case ATOMIC_OR:
2999             case ATOMIC_XOR:
3000             case ATOMIC_IMIN:
3001             case ATOMIC_IMAX:
3002             case ATOMIC_PREDEC:
3003             case ATOMIC_FMAX:
3004             case ATOMIC_FMIN:
3005             case ATOMIC_FCMPWR:
3006             case ATOMIC_FADD:
3007             case ATOMIC_FSUB:
3008                 break;
3009             }
3010             surface = getPrimitiveOperand<uint8_t>(inst, i++);
3011             REPORT_INSTRUCTION(options, surface < numPreDefinedSurfs + header->getSurfaceCount(),
3012                                "CISA dataport instruction uses an undeclared surface.");
3013 
3014             const raw_opnd& offsets = getRawOperand(inst, i++);
3015             verifyRawOperandType(inst, offsets, isUDType);
3016 
3017             // Check remaining raw operands.
3018             VISAAtomicOps subOpKind = static_cast<VISAAtomicOps>(subOpc);
3019             bool (*typeFn)(VISA_Type) = 0;
3020             switch (subOpKind) {
3021             default:
3022                 typeFn = isUDType;
3023                 break;
3024             case ATOMIC_IMAX:
3025             case ATOMIC_IMIN:
3026                 typeFn = isDType;
3027                 break;
3028             case ATOMIC_ADD:
3029             case ATOMIC_SUB:
3030                 typeFn = isDorUDTYpe;
3031                 break;
3032             case ATOMIC_FMAX:
3033             case ATOMIC_FMIN:
3034             case ATOMIC_FCMPWR:
3035             case ATOMIC_FADD:
3036             case ATOMIC_FSUB:
3037                 typeFn = isFType;
3038                 break;
3039             }
3040 
3041             // Check src0:
3042             //
3043             // - for INC and DEC operations, src0 must be V0 (the null variable);
3044             // - for IMIN and IMAX it must have type D;
3045             // - for all other operations, it must have type UD.
3046             const raw_opnd& src0 = getRawOperand(inst, i++);
3047             if (subOpKind == ATOMIC_INC || subOpKind == ATOMIC_DEC || subOpKind == ATOMIC_PREDEC)
3048             {
3049                 REPORT_INSTRUCTION(options, src0.index == 0,
3050                                    "src0 in ISA_DWORD_ATOMIC inst must be "
3051                                    "V0 for INC/DEC/PREDEC.");
3052             }
3053             else
3054             {
3055                 verifyRawOperandType(inst, src0, typeFn);
3056             }
3057             // Check src1:
3058             //
3059             // - for CMPXCHG operation, it must have type UD;
3060             // - for all other operations, it must be V0 (the null variable).
3061             //
3062             const raw_opnd& src1 = getRawOperand(inst, i++);
3063             if (subOpKind == ATOMIC_CMPXCHG || subOpKind == ATOMIC_FCMPWR)
3064             {
3065                 verifyRawOperandType(inst, src1, typeFn);
3066             }
3067             else
3068             {
3069                 REPORT_INSTRUCTION(options, src1.index == 0,
3070                                    "src1 in ISA_DWORD_ATOMIC inst must be "
3071                                    "V0 for non CMPXCHG operations.");
3072             }
3073             // Check dst:
3074             //
3075             // - for IMIN and IMAX, it must have type D;
3076             // - for all other operations, it must have type UD.
3077             //
3078             const raw_opnd& dst = getRawOperand(inst, i++);
3079             verifyRawOperandType(inst, dst, typeFn);
3080             break;
3081         }
3082         case ISA_3D_TYPED_ATOMIC:
3083         case ISA_3D_RT_WRITE:
3084         case ISA_QW_GATHER:
3085         case ISA_QW_SCATTER:
3086         {
3087             // no verification for now
3088             break;
3089         }
3090         default: REPORT_INSTRUCTION(options,false, "Illegal dataport Instruction Opcode: %d, %s.", opcode, ISA_Inst_Table[opcode].str);
3091     }
3092 }
3093 
verifyBFMixedMode(const CISA_INST * inst)3094 void vISAVerifier::verifyBFMixedMode(const CISA_INST* inst)
3095 {
3096     // Only verify inst type: Mov/Compare/Arith for BF mixed mode
3097     ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
3098     switch (ISA_Inst_Table[opcode].type)
3099     {
3100     case ISA_Inst_Mov:
3101     case ISA_Inst_Arith:
3102     case ISA_Inst_Compare:
3103         break;
3104     default:
3105         return;
3106     }
3107 
3108     if (!useGivenVISAType(inst, ISA_TYPE_BF))
3109     {
3110         // Skip if inst does not use BF
3111         return;
3112     }
3113 
3114     if (!irBuilder->hasBFMixMode())
3115     {
3116         REPORT_INSTRUCTION(options, false, "BF type is not allowed on this platform");
3117         return;
3118     }
3119 
3120     switch (opcode)
3121     {
3122     case ISA_MUL:
3123     case ISA_MAD:
3124     case ISA_MOV:
3125     case ISA_ADD:
3126     case ISA_SEL:
3127     case ISA_CMP:
3128         break;
3129     default:
3130         REPORT_INSTRUCTION(options, false, "BF opnd is not allowed on this instruction");
3131         return;
3132     }
3133 
3134     // Only F or BF are allowed
3135     // opernads: 0 : srcStart-1        --> dst
3136     //           srcStart : n_srcs-1   --> src
3137     int srcStart = (int)ISA_Inst_Table[opcode].n_dsts;
3138 
3139     // CMP's target must be bool, skip checking cmp's dst
3140     if (opcode != ISA_CMP)
3141     {
3142         for (int j = 0; j < srcStart; j++)
3143         {
3144             VISA_Type dstType = getOperandVISAType(inst, j);
3145             REPORT_INSTRUCTION(options,
3146                 (dstType == ISA_TYPE_F || dstType == ISA_TYPE_BF),
3147                 "Dst opnd in BF mixed mode should be either BF or F");
3148         }
3149     }
3150     else {
3151         // cmp's 1st opnd is cmp relop
3152         ++srcStart;
3153     }
3154     for (int j = 0; j < ISA_Inst_Table[opcode].n_srcs; j++)
3155     {
3156         VISA_Type srcType = getOperandVISAType(inst, j + srcStart);
3157         REPORT_INSTRUCTION(options,
3158             (srcType == ISA_TYPE_F || srcType == ISA_TYPE_BF),
3159             "Src opnd in BF mixed mode should be either BF or F");
3160     }
3161     return;
3162 }
3163 
3164 struct LscInstVerifier {
3165     const common_isa_header          &isaHeader;
3166     const print_format_provider_t*    header;
3167     const CISA_INST*                  inst;
3168     std::stringstream                 errorStream;
3169     Options                          *options;
3170     int                               execSize;
3171 
3172     LscOpInfo                         opInfo;
3173     LSC_OP                            subOp;
3174     LSC_SFID                          sfid;
3175 
3176     int                               currOpIx = 0;
3177 
LscInstVerifierLscInstVerifier3178     LscInstVerifier(
3179         const common_isa_header& _isaHeader,
3180         const print_format_provider_t* _header,
3181         const CISA_INST* _inst,
3182         Options *_options)
3183         : isaHeader(_isaHeader)
3184         , header(_header)
3185         , inst(_inst)
3186         , options(_options)
3187     {
3188         if (_inst->opcode == ISA_LSC_FENCE) {
3189             subOp = LSC_FENCE;
3190             sfid = getNextEnumU8<LSC_SFID>();
3191         } else if (_inst->opcode == ISA_LSC_TYPED) {
3192             subOp = getNextEnumU8<LSC_OP>();
3193             sfid = LSC_TGM;
3194         } else {
3195             subOp = getNextEnumU8<LSC_OP>();
3196             sfid = getNextEnumU8<LSC_SFID>();
3197         }
3198         (void)LscOpInfoFind(subOp, opInfo);
3199         execSize = 1;
3200         switch (inst->execsize & 0xF) {
3201         case EXEC_SIZE_1:  execSize =  1; break;
3202         case EXEC_SIZE_2:  execSize =  2; break;
3203         case EXEC_SIZE_4:  execSize =  4; break;
3204         case EXEC_SIZE_8:  execSize =  8; break;
3205         case EXEC_SIZE_16: execSize = 16; break;
3206         case EXEC_SIZE_32: execSize = 32; break;
3207         }
3208     }
3209 
3210     ///////////////////////////////////////////////////////////////////////////
3211     template <typename T>
getPrimitiveLscInstVerifier3212     T getPrimitive(int absOpIx) {
3213         return getPrimitiveOperand<T>(inst, absOpIx);
3214     }
3215 
3216     template <typename T>
getNextEnumU8LscInstVerifier3217     T getNextEnumU8() {
3218         return (T)getPrimitive<uint8_t>(currOpIx++);
3219     }
3220     template <typename T>
getNextLscInstVerifier3221     T getNext() {
3222         return getPrimitive<T>(currOpIx++);
3223     }
3224 
3225     // LSC_TYPED and non-block2d LSC_UNTYPED
3226     // "next" because it advances the operand pointer
getNextDataShapeLscInstVerifier3227     LSC_DATA_SHAPE getNextDataShape() {
3228         // chmask only valid on LSC_LOAD_QUAD/LSC_STORE_QUAD
3229         // but retained in the binary format
3230         LSC_DATA_SHAPE dataShape { };
3231         dataShape.size = getNextEnumU8<LSC_DATA_SIZE>();
3232         dataShape.order = getNextEnumU8<LSC_DATA_ORDER>();
3233         // untyped and typed have both data elems and chmask
3234         // (even though the IR only uses one)
3235         auto dataElems = getNextEnumU8<LSC_DATA_ELEMS>();
3236         int chMask = (int)getNextEnumU8<int>();
3237         if (opInfo.hasChMask()) {
3238             dataShape.chmask = chMask;
3239         } else {
3240             (void)chMask; // not used
3241             dataShape.elems = dataElems;
3242         }
3243         return dataShape;
3244     }
getNextDataShape2DLscInstVerifier3245     LSC_DATA_SHAPE_BLOCK2D getNextDataShape2D() {
3246         LSC_DATA_SHAPE_BLOCK2D dataShape2D { };
3247         dataShape2D.size = getNextEnumU8<LSC_DATA_SIZE>();
3248         dataShape2D.order = getNextEnumU8<LSC_DATA_ORDER>();
3249         dataShape2D.blocks = (int)getNext<uint8_t>();
3250         dataShape2D.width = (int)getNext<uint16_t>();
3251         dataShape2D.height = (int)getNext<uint16_t>();
3252         dataShape2D.vnni = getNext<uint8_t>() != 0;
3253         return dataShape2D;
3254     }
3255 
3256     ///////////////////////////////////////////////////////////////////////////
3257 
3258     template <typename T1, typename T2 = const char *, typename T3 = const char *>
verifyLscInstVerifier3259     bool verify(bool z, T1 t1, T2 t2 = "", T3 t3 = "") {
3260         if (!z)
3261             error(t1, t2, t3);
3262         return z;
3263     }
3264     template <typename T1, typename T2 = const char *, typename T3 = const char *>
errorLscInstVerifier3265     void error(T1 t1,  T2 t2 = "", T3 t3 = "") {
3266         std::stringstream ss;
3267         ss << " * ";
3268         ss << t1;
3269         ss << t2;
3270         ss << t3;
3271         ss << "\n";
3272         errorStream << ss.str();
3273     }
badEnumLscInstVerifier3274     void badEnum(const char *which, int value) {
3275         std::stringstream ss;
3276         ss << "0x" << std::hex << std::uppercase << value << ": ";
3277         ss << which;
3278         error(ss.str());
3279     }
3280 
verifyDataSizeLscInstVerifier3281     int verifyDataSize(LSC_DATA_SIZE dataSize) {
3282         int dataSizeBytes = 0;
3283         switch (dataSize) {
3284         case LSC_DATA_SIZE_8b: dataSizeBytes = 1; break;
3285         case LSC_DATA_SIZE_16b: dataSizeBytes = 2; break;
3286         case LSC_DATA_SIZE_32b: dataSizeBytes = 4; break;
3287         case LSC_DATA_SIZE_64b: dataSizeBytes = 8; break;
3288         case LSC_DATA_SIZE_8c32b: dataSizeBytes = 4; break;
3289         case LSC_DATA_SIZE_16c32b: dataSizeBytes = 4; break;
3290         case LSC_DATA_SIZE_16c32bH: dataSizeBytes = 4; break;
3291         default: badEnum("invalid LSC_DATA_SIZE", dataSize);
3292         }
3293         return dataSizeBytes;
3294     }
3295 
verifyDataOrderLscInstVerifier3296     bool verifyDataOrder(LSC_DATA_ORDER dataOrder) {
3297         bool transposed = false;
3298         switch (dataOrder) {
3299         case LSC_DATA_ORDER_NONTRANSPOSE: transposed = false; break;
3300         case LSC_DATA_ORDER_TRANSPOSE:    transposed = true; break;
3301         default: badEnum("invalid LSC_DATA_ORDER", dataOrder);
3302         }
3303         return transposed;
3304     }
3305 
verifyDataElemsLscInstVerifier3306     int verifyDataElems(LSC_DATA_ELEMS dataElems) {
3307         int vecSize = 0;
3308         switch (dataElems) {
3309         case LSC_DATA_ELEMS_1: vecSize = 1; break;
3310         case LSC_DATA_ELEMS_2: vecSize = 2; break;
3311         case LSC_DATA_ELEMS_3: vecSize = 3; break;
3312         case LSC_DATA_ELEMS_4: vecSize = 4; break;
3313         case LSC_DATA_ELEMS_8: vecSize = 8; break;
3314         case LSC_DATA_ELEMS_16: vecSize = 16; break;
3315         case LSC_DATA_ELEMS_32: vecSize = 32; break;
3316         case LSC_DATA_ELEMS_64: vecSize = 64; break;
3317             break;
3318         default: badEnum("LSC_DATA_ELEMS", dataElems);
3319         }
3320         return vecSize;
3321     }
3322 
verifyDataShapeLscInstVerifier3323     void verifyDataShape(LSC_DATA_SHAPE dataShape) {
3324         int dataSizeBytes = verifyDataSize(dataShape.size);
3325         if (dataSizeBytes == 0)
3326             return; // verifyDataSize reported error
3327 
3328 
3329         bool transposed = verifyDataOrder(dataShape.order);
3330         if (transposed) {
3331             verify(!opInfo.hasChMask(),
3332                 "LSC_DATA_ORDER_TRANSPOSE on ", opInfo.mnemonic);
3333             verify(execSize == 1,
3334                 "LSC_DATA_ORDER_TRANSPOSE requires ExecSize of 1");
3335             verify(!opInfo.isAtomic(),
3336                 "LSC atomics do not support transpose mode");
3337         } else if (opInfo.hasChMask()) {
3338             // quad store (store_cmask) can only support X, XY, XYZ, XYZW
3339             if (opInfo.op == LSC_STORE_QUAD) {
3340                 verify(
3341                     dataShape.chmask == LSC_DATA_CHMASK_X ||
3342                     dataShape.chmask ==
3343                        (LSC_DATA_CHMASK_X|LSC_DATA_CHMASK_Y) ||
3344                     dataShape.chmask ==
3345                         (LSC_DATA_CHMASK_X|LSC_DATA_CHMASK_Y|
3346                             LSC_DATA_CHMASK_Z) ||
3347                     dataShape.chmask == (LSC_DATA_CHMASK_X|LSC_DATA_CHMASK_Y
3348                         |LSC_DATA_CHMASK_Z|LSC_DATA_CHMASK_W),
3349                     "lsc_store_quad channel mask must be contiguous "
3350                     "(.x, .xy, .xyz, or .xyzw)");
3351             }
3352         } else if (!opInfo.isBlock2D()) {
3353             // SIMT access not block2d
3354             verify(
3355                 (dataShape.elems == LSC_DATA_ELEMS_1) ||
3356                 (dataShape.size == LSC_DATA_SIZE_32b ||
3357                     dataShape.size == LSC_DATA_SIZE_64b),
3358                 "only D32 and D64 support vector load");
3359             if (sfid == LSC_UGML) {
3360                 verify(
3361                   dataShape.elems == LSC_DATA_ELEMS_1 ||
3362                   dataShape.elems == LSC_DATA_ELEMS_2 ||
3363                   dataShape.elems == LSC_DATA_ELEMS_4,
3364                   "UGML only supports vector sizes 1, 2, and 4");
3365             } else if (sfid == LSC_SLM || sfid == LSC_UGM) {
3366                 verify(
3367                   dataShape.elems == LSC_DATA_ELEMS_1 ||
3368                   dataShape.elems == LSC_DATA_ELEMS_2 ||
3369                   dataShape.elems == LSC_DATA_ELEMS_3 ||
3370                   dataShape.elems == LSC_DATA_ELEMS_4 ||
3371                   dataShape.elems == LSC_DATA_ELEMS_8,
3372                   "SLM/UGM only supports vector sizes 1, 2, 3, 4, and 8");
3373             }
3374             if (opInfo.isAtomic()) {
3375                 verify(
3376                     dataShape.size == LSC_DATA_SIZE_16c32b ||
3377                     dataShape.size == LSC_DATA_SIZE_32b ||
3378                     dataShape.size == LSC_DATA_SIZE_64b,
3379                     "LSC atomics only support D16U32, D32, or D64");
3380                 // TODO: opInfo.op == LSC_ATOMIC_ICAS only in B0+ (none in A0)
3381                 verify(
3382                     sfid != LSC_SLM ||
3383                     dataShape.size != LSC_DATA_SIZE_64b ||
3384                     opInfo.op == LSC_ATOMIC_ICAS,
3385                     "LSC SLM D64 atomics only support icas");
3386                 {
3387                     verify(
3388                         (opInfo.op != LSC_ATOMIC_FADD && opInfo.op != LSC_ATOMIC_FSUB) ||
3389                         (sfid == LSC_UGM || sfid == LSC_UGML),
3390                         "LSC atomic fadd/fsub only support UGM and UGML");
3391                 }
3392             }
3393         }
3394 
3395         int vecSize = 0;
3396         if (!opInfo.hasChMask()) {
3397             vecSize = verifyDataElems(dataShape.elems);
3398             if (vecSize != 1) {
3399                 if (opInfo.isAtomic()) {
3400                     error("LSC_DATA_ELEMS must be 1 for atomic operations");
3401                 }
3402                 switch (dataShape.size) {
3403                 case LSC_DATA_SIZE_8c32b:
3404                 case LSC_DATA_SIZE_16c32b:
3405                 case LSC_DATA_SIZE_16c32bH:
3406                     error("LSC_DATA_SIZE: conversion types may not use vector");
3407                     break;
3408                 default: break;
3409                 }
3410             }
3411         } else if (dataShape.chmask == 0) {
3412             error("LSC_DATA_SHAPE::chmask: must not be 0");
3413         } else if (dataShape.chmask & ~0xF) {
3414             error("LSC_DATA_SHAPE::chmask: has high bits set");
3415         } else {
3416             vecSize = 0;
3417             for (int i = 0; i < 4; i++)
3418                 if (dataShape.chmask & (1<<i))
3419                     vecSize++;
3420         }
3421         if (vecSize == 0)
3422             return;
3423 
3424         // data payloads cannot be more than 8 registers
3425         const uint32_t BYTES_PER_REG = COMMON_ISA_GRF_REG_SIZE;
3426         int dataRegs = 0;
3427         if (transposed) {
3428             // must be SIMD1 (whether they had that right or not, it will be)
3429             // (and we've already complained about it if not)
3430             dataRegs = std::max<int>(1, vecSize*dataSizeBytes/BYTES_PER_REG);
3431         } else {
3432             //
3433             // int execSize = BYTES_PER_REG/2;
3434             // apparently :d32x8 and :d64x4 are permissible if SIMD16, so
3435             // we'll pull the real ExecSize
3436             //
3437             // TODO: we need to recheck with HW that they indeed put this
3438             // optimization in
3439             int regPerVecElem =
3440                 std::max<int>(1,dataSizeBytes*execSize/BYTES_PER_REG);
3441             dataRegs = vecSize*regPerVecElem;
3442         }
3443         if (opInfo.op != LSC_LOAD_BLOCK2D)
3444             verify(dataRegs <= 8, "this message accesses more than 8 registers");
3445     }
3446 
verifyCachingOptsLscInstVerifier3447     void verifyCachingOpts() {
3448         auto l1 = getNextEnumU8<LSC_CACHE_OPT>();
3449         auto l3 = getNextEnumU8<LSC_CACHE_OPT>();
3450         if (sfid == LSC_TGM || sfid == LSC_UGML) {
3451             verify(l1 == LSC_CACHING_DEFAULT && l3 == LSC_CACHING_DEFAULT,
3452                 "Messages to UGML and TGM require default cache settings"
3453                 " (#53561)");
3454             return;
3455         }
3456         uint32_t enc = 0;
3457         LSC_CACHE_OPTS cacheOpts {l1, l3};
3458         // set isBits17_19 to false to check for all cases
3459         if (!LscTryEncodeCacheOpts(opInfo, cacheOpts, enc, false)) {
3460             if (opInfo.isLoad()) {
3461                 error("invalid cache-control options for load (#53560)");
3462             } else if (opInfo.isAtomic()) {
3463                 if (cacheOpts.l1 != LSC_CACHE_OPT::LSC_CACHING_UNCACHED) {
3464                     error("atomics must use options with uncached L1"
3465                         " (#53561 & #53542 [19:17])");
3466                 } else {
3467                     error("invalid cache-control options for atomic (#53561)");
3468                 }
3469             } else {
3470                 error("invalid cache-control options for store (#53561)");
3471             }
3472         }
3473         // TODO: we should proscribe default/default if prefetch
3474     }
3475 
verifyAddrSizeLscInstVerifier3476     void verifyAddrSize(LSC_ADDR_SIZE addrSize) {
3477         // ADDR payloads limited to 4 registers
3478         //
3479         // SIMD32 64b will fit in PVC (as will SIMD16 64b on DG2)
3480         //  ==> nothing to check
3481         switch (addrSize) {
3482         case LSC_ADDR_SIZE_16b:
3483             verify(
3484                 sfid == LSC_SLM,
3485                 ":a16 (LSC_ADDR_SIZE_16b) only allowed on .slm SFID");
3486             break;
3487         case LSC_ADDR_SIZE_32b:
3488             break;
3489         case LSC_ADDR_SIZE_64b:
3490             if (sfid == LSC_TGM || sfid == LSC_SLM)
3491                 error(".tgm not allowed on :a64 (LSC_ADDR_SIZE_64b)");
3492             if (subOp == LSC_LOAD_BLOCK2D || subOp == LSC_STORE_BLOCK2D)
3493                 error("block2d does not allow 64b address types");
3494             break;
3495         default:
3496             break;
3497         }
3498     }
3499 
verifyAddressTypeLscInstVerifier3500     void verifyAddressType(LSC_ADDR_TYPE addrType, int surfIxAbs) {
3501         if (!verifyVectorOperand("Surface", surfIxAbs)) {
3502             return;
3503         }
3504         const auto &vo = getVectorOperand(inst, surfIxAbs);
3505 
3506         switch (addrType) {
3507         case LSC_ADDR_TYPE_FLAT:
3508             verify(sfid != LSC_TGM, ".tgm may not use flat address model");
3509             switch (vo.tag & 0x7) {
3510             case OPERAND_IMMEDIATE:
3511                 verify(
3512                     vo.opnd_val.const_opnd._val.ival == 0,
3513                     "Surface: for LSC_ADDR_TYPE_FLAT only imm 0 or V0 allowed");
3514                 break; // okay
3515             case OPERAND_GENERAL:
3516                 verify(
3517                     vo.opnd_val.gen_opnd.index == 0,
3518                     "Surface: must be null (V0) reg for LSC_ADDR_TYPE_FLAT");
3519                 break;
3520             default:
3521                 error("Surface: invalid operand type");
3522             }
3523             break;
3524         case LSC_ADDR_TYPE_BSS:
3525         case LSC_ADDR_TYPE_SS:
3526         case LSC_ADDR_TYPE_BTI:
3527             verify(sfid != LSC_SLM, "slm must use flat address model");
3528             switch (vo.tag & 0x7) {
3529             case OPERAND_IMMEDIATE:
3530                 break;
3531             case OPERAND_GENERAL:
3532                 verify(vo.opnd_val.gen_opnd.index != 0,
3533                     "Surface: must not be null (V0) reg for non-FLAT AddrType");
3534                 break;
3535             default:
3536                 error("Surface: invalid operand type");
3537             }
3538             break;
3539         default: badEnum("LSC_ADDR_TYPE is invalid", addrType); break;
3540         }
3541     }
3542 
verifyRawOperandLscInstVerifier3543     bool verifyRawOperand(const char *which, int absIx) {
3544         if (getOperandType(inst, absIx) != CISA_OPND_RAW) {
3545             error(which, ": expected vISA RawOperand");
3546             return false;
3547         }
3548         return true;
3549     }
3550 
verifyRawOperandNullLscInstVerifier3551     bool verifyRawOperandNull(const char *which, int absIx) {
3552         if (!verifyRawOperand(which, absIx)) {
3553             return false;
3554         } else {
3555             const raw_opnd &ro = getRawOperand(inst, absIx);
3556             if (ro.index != 0) {
3557                 error(which, "; operand must be null");
3558                 return false;
3559             }
3560             return true;
3561         }
3562     }
3563 
verifyRawOperandNonNullLscInstVerifier3564     bool verifyRawOperandNonNull(const char *which, int absIx) {
3565         if (!verifyRawOperand(which, absIx)) {
3566             return false;
3567         } else {
3568             const raw_opnd &ro = getRawOperand(inst, absIx);
3569             if (ro.index == 0) {
3570                 error(which, ": operand must not be null");
3571                 return false;
3572             }
3573             return true;
3574         }
3575     }
3576 
verifyVectorOperandLscInstVerifier3577     bool verifyVectorOperand(const char *which, int absIx) {
3578         if (getOperandType(inst, absIx) != CISA_OPND_VECTOR) {
3579             error(which, ": expected vISA vector operand");
3580             return false;
3581         }
3582         return true;
3583     }
verifyVectorOperandNotNullLscInstVerifier3584     bool verifyVectorOperandNotNull(const char *which, int absIx) {
3585         if (!verifyVectorOperand(which, absIx)) {
3586             return false;
3587         }
3588         const vector_opnd &vo = getVectorOperand(inst, absIx);
3589         if (!vo.isImmediate() && vo.getOperandIndex() == 0) {
3590             error(which, ": vector operand must not be null");
3591             return false;
3592         }
3593         return true;
3594     }
3595 
3596     // check dst and src1 and src2
verifyDataOperandsLscInstVerifier3597     void verifyDataOperands(int dstOpIx, int src1DataIx) {
3598         if (opInfo.isStore()) {
3599             verifyRawOperandNull("DstData", dstOpIx);
3600         } else {
3601             // atomics and loads can have either null or non-null
3602             verifyRawOperand("DstData", dstOpIx);  // DstData
3603         }
3604 
3605         if (opInfo.isLoad()) {
3606             verifyRawOperandNull("Src1Data", src1DataIx);
3607             if (!opInfo.isStrided() && !opInfo.isBlock2D())
3608                 verifyRawOperandNull("Src2Data", src1DataIx+1);
3609         } else if (opInfo.isStore()) {
3610             verifyRawOperandNonNull("Src1Data", src1DataIx);
3611             if (!opInfo.isStrided() && !opInfo.isBlock2D())
3612                 verifyRawOperandNull("Src2Data", src1DataIx+1);
3613         } else if (opInfo.isAtomic()) {
3614             if (opInfo.extraOperands > 0) {
3615                 verifyRawOperandNonNull(
3616                     "Src1Data (in binary atomic)", src1DataIx);
3617             } else {
3618                 verifyRawOperandNull(
3619                     "Src1Data (in binary atomic)", src1DataIx);
3620             }
3621             if (opInfo.extraOperands == 2) {
3622                 verifyRawOperandNonNull(
3623                     "Src2Data (in ternary atomic)", src1DataIx+1);
3624             } else {
3625                 verifyRawOperandNull(
3626                     "Src2Data (in ternary atomic)", src1DataIx+1);
3627             }
3628         }
3629     }
3630 
3631     ///////////////////////////////////////////////////////////////////////////
verifyFenceLscInstVerifier3632     void verifyFence() {
3633         // SLM only gets .group and .none
3634         // c.f. ASpec 5.4.1.12.9 "Fence Message Handling" (pg 62)
3635         auto fenceOp = getNextEnumU8<LSC_FENCE_OP>();
3636         auto scope = getNextEnumU8<LSC_SCOPE>();
3637         switch (fenceOp) {
3638         case LSC_FENCE_OP_NONE:
3639             break;
3640         case LSC_FENCE_OP_EVICT:
3641         case LSC_FENCE_OP_INVALIDATE:
3642         case LSC_FENCE_OP_DISCARD:
3643         case LSC_FENCE_OP_CLEAN:
3644         case LSC_FENCE_OP_FLUSHL3:
3645           verify(sfid != LSC_SLM, "lsc_fence.slm fence op must be .none");
3646           break;
3647         default:
3648             badEnum("invalid LSC_FENCE",fenceOp);
3649             break;
3650         }
3651         switch (scope) {
3652         case LSC_SCOPE_GROUP:
3653             break;
3654         case LSC_SCOPE_LOCAL:
3655         case LSC_SCOPE_TILE:
3656         case LSC_SCOPE_GPU:
3657         case LSC_SCOPE_GPUS:
3658         case LSC_SCOPE_SYSREL:
3659         case LSC_SCOPE_SYSACQ:
3660             verify(sfid != LSC_SLM, "lsc_fence.slm must use .group scope");
3661             break;
3662         default:
3663             badEnum("invalid LSC_SCOPE",scope);
3664             break;
3665         }
3666     }
3667 
3668     ///////////////////////////////////////////////////////////////////////////
verifyUntypedBlock2DLscInstVerifier3669     void verifyUntypedBlock2D() {
3670         bool valid = true;
3671 
3672         verifyCachingOpts();
3673         //
3674         const auto dataShape2D = getNextDataShape2D();
3675         int dataSizeBytes = verifyDataSize(dataShape2D.size);
3676         verifyDataOrder(dataShape2D.order);
3677         valid &= verify(dataShape2D.blocks > 0,
3678             "block2d blocks (vec_len) must be >= 1");
3679         valid &= verify(dataShape2D.height > 0, "blocks2d height must be > 0");
3680         valid &= verify(dataShape2D.width > 0, "blocks2d width must be > 0");
3681         valid &= verify(
3682             opInfo.op != LSC_STORE_BLOCK2D || !dataShape2D.vnni,
3683             "block2d stores may not use VNNI transform");
3684         valid &= verify(
3685             opInfo.op != LSC_STORE_BLOCK2D || dataShape2D.blocks == 1,
3686             "block2d stores must have block count==1");
3687 
3688         if (!valid)
3689             return;
3690 
3691         bool transpose = dataShape2D.order == LSC_DATA_ORDER_TRANSPOSE;
3692         bool transform = dataShape2D.vnni;
3693         int cols = !transpose ?  dataShape2D.width : dataShape2D.height;
3694         valid &= verify(cols*dataSizeBytes <= 64,
3695             cols*dataSizeBytes, ": block2d cols * data size must be <= 64");
3696         int rows = !transpose ?  dataShape2D.height : dataShape2D.width;
3697         valid &= verify(rows <= 32,
3698             rows, ": block2d row count must be less than <= 32");
3699         //
3700         // HAS constraints on valid block dimensions
3701         //   c.f. HAS 5.1.2.1 Allowed Sizes (pg 6)  - NN
3702         //   c.f. HAS 5.1.3.1 Allowed Sizes (pg 9)  - TN
3703         //   c.f. HAS 5.1.1.1 Allowed Sizes (pg 12) - TN
3704         //   c.f. HAS 5.2.1.1 Allowed Sizes (pg 15) - TT
3705         //
3706         // in general all but (TN) can use block counts as follows
3707         //    data size    block count (vec_len)
3708         //    u8/u16:      1, 2, and 4
3709         //    u32:         1 and 2
3710         //    u64:         1
3711         //
3712         // TN must use a block size of vec len of 1
3713         if (!transpose || transform) {
3714             switch (dataShape2D.size) {
3715             case LSC_DATA_SIZE_8b:
3716                 valid &= verify(
3717                     dataShape2D.blocks == 1 || dataShape2D.blocks == 2 ||
3718                         dataShape2D.blocks == 4,
3719                     dataShape2D.blocks,
3720                     ": block2d count (vec_len) must be 1, 2, or 4 for u8");
3721                 break;
3722             case LSC_DATA_SIZE_16b:
3723                 valid &= verify(
3724                     dataShape2D.blocks == 1 || dataShape2D.blocks == 2 ||
3725                         dataShape2D.blocks == 4,
3726                     dataShape2D.blocks,
3727                     ": block2d count (vec_len) must be 1, 2, or 4 for u16");
3728                 break;
3729             case LSC_DATA_SIZE_32b:
3730                 valid &= verify(
3731                     dataShape2D.blocks == 1 || dataShape2D.blocks == 2,
3732                     dataShape2D.blocks,
3733                     ": block2d count (vec_len) must be 1 or 2 for u32");
3734                 break;
3735             case LSC_DATA_SIZE_64b:
3736                 valid &= verify(
3737                     dataShape2D.blocks == 1,
3738                     dataShape2D.blocks,
3739                     ": block2d count (vec_len) must be 1 for u64");
3740                 break;
3741             default:
3742                 error("invalid data type size for block2d load");
3743                 return;
3744             }
3745         } else {
3746             valid &= verify(
3747                 dataShape2D.blocks == 1,
3748                 "block2d count (vec_len) must be 1 for block2d transposed");
3749         }
3750         if (!valid)
3751             return;
3752 
3753         //
3754         if (dataShape2D.blocks > 16) {
3755             // this constrains us to the encoding space; specific hardware
3756             // may have additional constraints (e.g. only 1, 2, and 4)
3757             error("block2d data shape block count (array/vec len) > 16");
3758         }
3759 
3760         //
3761         /////////////////////////////////////////
3762         // now we're at the register operands
3763         //
3764         verifyVectorOperandNotNull("SurfaceBase", currOpIx+1);
3765         verifyVectorOperandNotNull("SurfaceWidth", currOpIx+2);
3766         verifyVectorOperandNotNull("SurfaceHeight", currOpIx+3);
3767         verifyVectorOperandNotNull("SurfacePitch", currOpIx+4);
3768         verifyVectorOperandNotNull("OffsetX", currOpIx+5);
3769         verifyVectorOperandNotNull("OffsetY", currOpIx+6);
3770         //
3771         verifyDataOperands(currOpIx, currOpIx+1+6);
3772     }
3773 
3774     ///////////////////////////////////////////////////////////////////////////
verifyUntypedBasicLscInstVerifier3775     void verifyUntypedBasic() {
3776         verifyCachingOpts();
3777 
3778         //
3779         auto addrType = getNextEnumU8<LSC_ADDR_TYPE>();
3780         uint16_t immediateScale = getNext<uint16_t>();
3781         if ((immediateScale & (immediateScale-1)) != 0) {
3782             error("immediate scale must be power of two "
3783                 "(someone could enable this though)");
3784         }
3785         int32_t immediateOffset = getNext<int32_t>();
3786 
3787         auto addrSize = getNextEnumU8<LSC_ADDR_SIZE>();
3788         verifyAddrSize(addrSize);
3789         if (addrSize == LSC_ADDR_SIZE_16b) {
3790             if (immediateOffset > 0x7FFF || immediateOffset < -0x7FFF) {
3791                 error("immediate offset overflows A16 address arithmetic");
3792             }
3793         }
3794 
3795         auto dataShape = getNextDataShape();
3796         verifyDataShape(dataShape);
3797 
3798         // now we are at the registers
3799         verifyAddressType(addrType, currOpIx); // Surface
3800 
3801         const char *src0Name = opInfo.isStrided() ? "Src0AddrBase" : "Src0Addr";
3802         int src1DataIx = !opInfo.isStrided() ? currOpIx+3 : currOpIx+4;
3803         verifyRawOperand(src0Name, currOpIx+2);  // Src0Addr
3804         if (opInfo.isStrided()) {
3805             if (verifyVectorOperand("Src0AddrStride", currOpIx+3)) {
3806                 const auto &vo = getVectorOperand(inst, currOpIx+3);
3807                 switch (vo.tag & 0x7) {
3808                 case OPERAND_IMMEDIATE:
3809                     if (vo.opnd_val.const_opnd._val.ival > 0xFFFF) {
3810                         error("Src0AddrStride: pitch exceeds 16 bits");
3811                     }
3812                     break; // okay
3813                 case OPERAND_GENERAL:
3814                     if (vo.opnd_val.gen_opnd.index == 0) {
3815                         error("Src0AddrStride",
3816                             "VectorOperand must be immediate or non-null");
3817                     }
3818                     break;
3819                 default:
3820                     error("Src0AddrStride", "invalid operand type");
3821                 }
3822             }
3823         }
3824 
3825         verifyDataOperands(currOpIx+1, src1DataIx);
3826     }
3827 
3828     ///////////////////////////////////////////////////////////////////////////
verifyTypedLscInstVerifier3829     void verifyTyped() {
3830         verifyCachingOpts();
3831 
3832         auto addrType = getNextEnumU8<LSC_ADDR_TYPE>();
3833         auto addrSize = getNextEnumU8<LSC_ADDR_SIZE>();
3834         verifyAddrSize(addrSize);
3835 
3836         auto dataShape = getNextDataShape();
3837         verifyDataShape(dataShape);
3838 
3839         verifyAddressType(addrType, currOpIx);
3840 
3841         // check all the Src0Addr fields (U, V, R, LOD)
3842         if (opInfo.op == LSC_READ_STATE_INFO) {
3843             verifyRawOperandNull("Src0Addr_Us", currOpIx+2); // U's
3844             verifyRawOperandNull("Src0Addr_Vs", currOpIx+3); // V's
3845             verifyRawOperandNull("Src0Addr_Rs", currOpIx+4); // R's
3846             verifyRawOperandNull("Src0Addr_LODs", currOpIx+5); // LOD's
3847         } else {
3848             verifyRawOperandNonNull("Src0Addr_Us", currOpIx+2); // U's
3849             verifyRawOperand("Src0Addr_Vs", currOpIx+3);        // V's
3850             verifyRawOperand("Src0Addr_Rs", currOpIx+4);        // R's
3851             verifyRawOperand("Src0Addr_LODs", currOpIx+5);      // LOD's
3852         }
3853 
3854         // check Dst, Src1, and Src2
3855         verifyDataOperands(currOpIx+1, currOpIx+6);
3856     }
3857 
verifyLscInstVerifier3858     void verify() {
3859         if (opInfo.mnemonic == nullptr || opInfo.op == LSC_INVALID) {
3860             error("invalid LSC subop");
3861             return;
3862         }
3863         if (inst->opcode == ISA_LSC_FENCE) {
3864             verifyFence();
3865         } else if (inst->opcode == ISA_LSC_UNTYPED) {
3866             if (subOp == LSC_LOAD_BLOCK2D || subOp == LSC_STORE_BLOCK2D) {
3867                 verifyUntypedBlock2D();
3868             } else {
3869                 verifyUntypedBasic();
3870             }
3871         } else if (inst->opcode == ISA_LSC_TYPED) {
3872             verifyTyped();
3873         } else {
3874             badEnum("invalid LSC op code", inst->opcode);
3875         }
3876     }
3877 }; // LscInstVerifier
3878 
verifyInstructionLsc(const CISA_INST * inst)3879 void vISAVerifier::verifyInstructionLsc(const CISA_INST *inst)
3880 {
3881     // This mostly comes from: https://gfxspecs.intel.com/Predator/Home/Index/53578
3882     // But there's also a spreadsheet floating around
3883     LscInstVerifier verifier(isaHeader, header, inst, options);
3884     verifier.verify();
3885     if (verifier.errorStream.tellp() > 0) {
3886         std::stringstream ss;
3887         ss << "in instruction " << printInstruction(header, inst, options) << "\n";
3888         ss << verifier.errorStream.str();
3889         error_list.push_back(ss.str());
3890     }
3891 }
3892 
verifyInstructionSrnd(const CISA_INST * inst)3893 void vISAVerifier::verifyInstructionSrnd(const CISA_INST* inst)
3894 {
3895     const vector_opnd&    dst = getVectorOperand(inst, 0);
3896     VISA_Type         dstType = getVectorOperandType(header, dst);
3897     VISA_Modifier dstModifier = dst.getOperandModifier();
3898 
3899     // dst
3900     REPORT_INSTRUCTION(options, dst.getOperandClass() == OPERAND_GENERAL,
3901         "Destination of this CISA instruction should be general operand.");
3902 
3903     REPORT_INSTRUCTION(options, dstModifier == MODIFIER_NONE,
3904         "Destination modifier for this CISA instruction is not allowed.");
3905 
3906     // src
3907     const vector_opnd& src0    = getVectorOperand(inst, 1);
3908     VISA_Type         src0Type = getVectorOperandType(header, src0);
3909     VISA_Modifier src0Modifier = src0.getOperandModifier();
3910     const vector_opnd& src1 = getVectorOperand(inst, 2);
3911     VISA_Type         src1Type = getVectorOperandType(header, src1);
3912     VISA_Modifier src1Modifier = src1.getOperandModifier();
3913 
3914     REPORT_INSTRUCTION(options, src0Modifier == MODIFIER_NONE && src1Modifier == MODIFIER_NONE,
3915         "Source modifiers for this instruction are not allowed");
3916     REPORT_INSTRUCTION(options,
3917         (src0.getOperandClass() == OPERAND_GENERAL || src0.getOperandClass() == OPERAND_IMMEDIATE) &&
3918             (src1.getOperandClass() == OPERAND_GENERAL || src1.getOperandClass() == OPERAND_IMMEDIATE),
3919         "Sources in this instruction must be general or immediate");
3920 
3921     // Verify types
3922     REPORT_INSTRUCTION(options, src0Type == src1Type,
3923         "Src0 and src1 should have the same type for this instruction");
3924     REPORT_INSTRUCTION(options,
3925         (dstType == ISA_TYPE_UB && src0Type == ISA_TYPE_HF) ||
3926             (dstType == ISA_TYPE_HF && src0Type == ISA_TYPE_F),
3927         "Src and Dst types mismatch. Only (dst=ub, src=hf) or (dst=hf, src=f) supported.");
3928 }
3929 
verifyKernelAttributes()3930 void vISAVerifier::verifyKernelAttributes()
3931 {
3932     /// Verify SLMSize, if present, shows up only once
3933     unsigned int numSLMSize = 0;
3934     unsigned int numNamedBarrierCnt = 0;
3935     for (unsigned int i = 0; i < header->getAttrCount(); i++)
3936     {
3937         auto attr = header->getAttr(i);
3938         const char* attrName = header->getString(attr->nameIndex);
3939         Attributes::ID aID = Attributes::getAttributeID(attrName);
3940         if (aID == Attributes::ATTR_SLMSize)
3941         {
3942             numSLMSize++;
3943         }
3944         else if (aID == Attributes::ATTR_NBarrierCnt)
3945         {
3946             numNamedBarrierCnt++;
3947         }
3948     }
3949 
3950     REPORT_HEADER(options, numSLMSize <= 1,
3951         "More than 1 kernel attribute defined %s",
3952         Attributes::getAttributeName(Attributes::ATTR_SLMSize));
3953 
3954     REPORT_HEADER(options, numNamedBarrierCnt <= 1,
3955         "More than 1 kernel attribute defined %s",
3956         Attributes::getAttributeName(Attributes::ATTR_NBarrierCnt));
3957 }
3958 
verifyKernelHeader()3959 void vISAVerifier::verifyKernelHeader()
3960 {
3961     /// Verify variable decls.
3962     unsigned numPreDefinedVars = Get_CISA_PreDefined_Var_Count();
3963     unsigned numPreDefinedSurfs = Get_CISA_PreDefined_Surf_Count();
3964     for (unsigned i = 0; i < header->getVarCount(); i++)
3965     {
3966         verifyVariableDecl(i);
3967     }
3968 
3969     /// Verify address decls.
3970     for (unsigned i = 0; i < header->getAddrCount(); i++)
3971     {
3972         verifyAddressDecl(i);
3973     }
3974 
3975     /// Verify predicate decls.
3976     for (unsigned i = 0; i < header->getPredCount(); i++)
3977     {
3978         verifyPredicateDecl(i);
3979     }
3980 
3981     /// Verify labels.
3982     for (unsigned i = 0; i < header->getLabelCount(); i++)
3983     {
3984         REPORT_HEADER(options,header->getLabel(i)->name_index < header->getStringCount(),
3985             "label%d's name index(%d) is not valid", i, header->getLabel(i)->name_index);
3986     }
3987 
3988     /// Verify sampler.
3989     for (unsigned i = 0; i < header->getSamplerCount(); i++)
3990     {
3991         REPORT_HEADER(options,header->getSampler(i)->name_index < header->getStringCount(),
3992             "S%d's name index(%d) is not valid", i, header->getSampler(i)->name_index);
3993         REPORT_HEADER(options,header->getSampler(i)->num_elements <= COMMON_ISA_MAX_SAMPLER_SIZE,
3994             "S%d's number of elements(%d) is not vaild", i, header->getSampler(i)->num_elements);
3995     }
3996 
3997     /// Verify surface.
3998     unsigned int numPredSurf = Get_CISA_PreDefined_Surf_Count();
3999     for (unsigned i = numPredSurf; i < header->getSurfaceCount(); i++)
4000     {
4001         REPORT_HEADER(options,header->getSurface(i)->name_index < header->getStringCount(),
4002             "T%d's name index(%d) is not valid", i, header->getSurface(i)->name_index);
4003         REPORT_HEADER(options,header->getSurface(i)->num_elements <= COMMON_ISA_MAX_SURFACE_SIZE,
4004             "T%d's number of elements(%d) is not valid", i, header->getSurface(i)->num_elements);
4005     }
4006 
4007     // Verify inputs.
4008     // v3.3+, kernel may have explicit arguments followed by implicit ones.
4009     // This information is only used by the CM runtime, not by Finalizer.
4010     unsigned implicitIndex = header->getInputCount();
4011     uint32_t versionNum = getVersionAsInt(isaHeader.major_version, isaHeader.minor_version);
4012     if (versionNum >= getVersionAsInt(3, 3))
4013     {
4014         for (unsigned i = 0; i < header->getInputCount(); i++)
4015         {
4016             if (header->getInput(i)->getImplicitKind() != 0)
4017             {
4018                 implicitIndex = i;
4019                 break;
4020             }
4021         }
4022     }
4023 
4024     // [Begin, end) is an interval for each input. We check two things
4025     // - no overlap
4026     // - do not overflow i.e. end < 32 * (256 - 1)
4027     for (unsigned i = 0; i < header->getInputCount(); i++)
4028     {
4029         {
4030             auto pi = header->getInput(i);
4031             unsigned Begin = pi->offset;
4032             unsigned End = Begin + pi->size;
4033             if (End >= (uint32_t) (getGRFSize() * (256 - 1)))
4034             {
4035                 REPORT_HEADER(options, false, "Input V%d is out of bound [%d, %d)", pi->index, Begin, End);
4036             }
4037             for (unsigned j = 0; j < i; ++j)
4038             {
4039                 auto pj = header->getInput(j);
4040                 unsigned Begin1 = pj->offset, End1 = pj->offset + pj->size;
4041                 if ((Begin >= Begin1 && Begin < End1) ||
4042                     (Begin1 >= Begin && Begin1 < End))
4043                 {
4044                     REPORT_HEADER(options, false, "Input V%d = [%d, %d) intersects with V%d = [%d, %d)",
4045                         pi->index, Begin, End, pj->index, Begin1, End1);
4046                 }
4047             }
4048         }
4049 
4050         if (i >= implicitIndex)
4051         {
4052             REPORT_HEADER(
4053                 options, header->getInput(i)->getImplicitKind() != 0,
4054                 "Explicit input %d must not follow an implicit input %d", i,
4055                 implicitIndex);
4056         }
4057         switch (header->getInput(i)->getInputClass())
4058         {
4059             case INPUT_GENERAL:
4060                  if (header->getInput(i)->index < numPreDefinedVars)
4061                  {
4062                      REPORT_HEADER(options,false, "Input %d points to an invalid variable(%d)", i, header->getInput(i)->index);
4063                  }
4064                  else
4065                  {
4066                      int varId   = header->getInput(i)->index - numPreDefinedVars;
4067                      int varSize = header->getVar(varId)->num_elements * CISATypeTable[header->getVar(varId)->getType()].typeSize;
4068                      REPORT_HEADER(options,varSize == header->getInput(i)->size,
4069                          "Input %d's size(%d) does not agree with its variable (V%d)'s", i, header->getInput(i)->size, varId + numPreDefinedVars);
4070                      if (header->getInput(i)->size < getGRFSize())
4071                      {
4072                          // check that input does not straddle GRF boundary
4073                          auto beginGRF = header->getInput(i)->offset / getGRFSize();
4074                          auto endGRF = (header->getInput(i)->offset + header->getInput(i)->size - 1) / getGRFSize();
4075                          REPORT_HEADER(options, beginGRF == endGRF, "Input %s is <1 GRF but straddles GRF boundary", header->getInput(i)->dcl->getName());
4076                      }
4077                  }
4078                  break;
4079             case INPUT_SAMPLER:
4080                  REPORT_HEADER(options,header->getInput(i)->index < header->getSamplerCount(),
4081                      "Input%d points to an invalid sampler index(%d)", i, header->getInput(i)->index);
4082                  break;
4083             case INPUT_SURFACE:
4084                  if (header->getInput(i)->index-numPredSurf >= header->getSurfaceCount() || header->getInput(i)->index < numPredSurf)
4085                  {
4086                      REPORT_HEADER(options,false, "Input%d points to an invalid/predefined surface index(%d)", i, header->getInput(i)->index);
4087                  }
4088                  else
4089                  {
4090                      int surfaceSize;
4091                      surfaceSize = header->getSurface(header->getInput(i)->index-numPreDefinedSurfs)->num_elements * CISATypeTable[ISA_TYPE_UD].typeSize;
4092 
4093                      REPORT_HEADER(options,surfaceSize == header->getInput(i)->size, "Input%d's size(%d) does not agree with its surface's", i, header->getInput(i)->size);
4094                  }
4095                  break;
4096             default:
4097                  REPORT_HEADER(options,false, "Input%d has invalid operand class(%d)", i, header->getInput(i)->getInputClass());
4098         }
4099         /// TODO: Consider adding offset checks here.
4100     }
4101 
4102     verifyKernelAttributes();
4103 }
4104 
finalize()4105 void vISAVerifier::finalize()
4106 {
4107     for (auto iter : labelDefs)
4108     {
4109         if (!(iter.second))
4110         {
4111             const label_info_t* lblInfo = header->getLabel(iter.first);
4112             if (lblInfo->kind != LABEL_FC)
4113             {
4114                 REPORT_HEADER(options, false, "undefined label: %s", header->getString(lblInfo->name_index));
4115             }
4116         }
4117     }
4118 }
4119 
verifyInstruction(const CISA_INST * inst)4120 void vISAVerifier::verifyInstruction(
4121     const CISA_INST* inst)
4122 {
4123     ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
4124 
4125     if (!(ISA_RESERVED_0 < opcode && opcode < ISA_NUM_OPCODE))
4126     {
4127         REPORT_INSTRUCTION(options, false, "Invalid vISA opcode: %d", opcode);
4128         return;
4129     }
4130 
4131     TARGET_PLATFORM instPlatform = CISA_INST_table[opcode].platf;
4132     if (instPlatform != ALL)
4133     {
4134         // We assume instructions are backward compatible
4135         // instructions that are not should have their own checks elsewhere
4136         REPORT_INSTRUCTION(options, getGenxPlatform() >= instPlatform, "vISA instruction not supported on this platform");
4137     }
4138 
4139     for (unsigned i = 0; i < inst->opnd_count; i++)
4140         verifyOperand(inst, i);
4141 
4142     if (hasExecSize(opcode))
4143     {
4144         auto execSize = inst->getExecSize();
4145         REPORT_INSTRUCTION(options, execSize < EXEC_SIZE_ILLEGAL, "vISA instruction uses an illegal execution size.");
4146         // check for illegal combinations of emask and execution size
4147         REPORT_INSTRUCTION(options, Get_VISA_Exec_Size(execSize) + getvISAMaskOffset(inst->getExecMask()) <= 32,
4148             "vISA instruction has illegal combination of execution size and mask");
4149     }
4150 
4151     if (hasPredicate(opcode))
4152     {
4153         uint16_t predicateNum = inst->pred.getId();
4154         REPORT_INSTRUCTION(options,predicateNum < header->getPredCount() + COMMON_ISA_NUM_PREDEFINED_PRED, "CISA instruction uses an illegal predicate value.");
4155     }
4156 
4157     switch (ISA_Inst_Table[opcode].type)
4158     {
4159         case ISA_Inst_SVM:       verifyInstructionSVM         (inst); break;
4160         case ISA_Inst_Mov:       verifyInstructionMove        (inst); break;
4161         case ISA_Inst_Sync:      verifyInstructionSync        (inst); break;
4162         case ISA_Inst_Flow:      verifyInstructionControlFlow (inst); break;
4163         case ISA_Inst_Misc:      verifyInstructionMisc        (inst); break;
4164         case ISA_Inst_Arith:     verifyInstructionArith       (inst); break;
4165         case ISA_Inst_Logic:     verifyInstructionLogic       (inst); break;
4166         case ISA_Inst_Compare:   verifyInstructionCompare     (inst); break;
4167         case ISA_Inst_Address:   verifyInstructionAddress     (inst); break;
4168         case ISA_Inst_Sampler:   verifyInstructionSampler     (inst); break;
4169         case ISA_Inst_SIMD_Flow: verifyInstructionSIMDFlow    (inst); break;
4170         case ISA_Inst_Data_Port: verifyInstructionDataport    (inst); break;
4171         case ISA_Inst_LSC:       verifyInstructionLsc         (inst); break;
4172         default:
4173         {
4174             std::stringstream sstr;
4175             sstr << "Illegal or unimplemented CISA instruction (opcode, type): (" <<
4176                 opcode << ", " << ISA_Inst_Table[opcode].type << ").";
4177             ASSERT_USER(false, sstr.str());
4178         }
4179     }
4180 
4181     // Verify particular features
4182     verifyBFMixedMode(inst);
4183 }
4184 
4185 #endif // IS_RELEASE_DLL
4186 
4187