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 /*
10  * ISA IR Disassembler
11  *
12  * This library is designed to be extremely reusable and general in nature, and as a result
13  * the following ISA IR disassembly code primarily uses the following IR and data types:
14  *
15  * - common_isa_header
16  * - kernel_format_t
17  * - attribute_info_t
18  * - VISA_opnd
19  * - vector_opnd
20  * - raw_opnd
21  * - CISA_INST
22  * - std::list<CISA_INST*>
23  *
24  * and prints them as human readable text to an isaasm file.
25  *
26  * Use of any other data types should be discussed by several members of the CM jitter team before hand.
27  *
28  */
29 
30 #include "IGC/common/StringMacros.hpp"
31 #include <algorithm>
32 #include <cstdint>
33 #include <cctype>
34 #include <list>
35 #include <sstream>
36 #include <string>
37 
38 #include "visa_igc_common_header.h"
39 #include "common.h"
40 #include "Mem_Manager.h"
41 #include "Common_ISA.h"
42 #include "Common_ISA_framework.h"
43 #include "Common_ISA_util.h"
44 #include "VISADefines.h"
45 #include "IsaDisassembly.h"
46 #include "Option.h"
47 #include "JitterDataStruct.h"
48 #include "VISABuilderAPIDefinition.h"
49 #include "PreDefinedVars.h"
50 #include "VISAKernel.h"
51 
52 using namespace vISA;
53 
54 /// Output flags.
55 _THREAD bool g_shortRegionPrint  = false; /// Use shorthand names for common regions.
56 _THREAD bool g_inlineTypePrint   = false; /// Print the type information with operands.
57 _THREAD bool g_prettyPrint       = true ; /// Line up the comments.
58 _THREAD bool g_ignorelocs        = false; /// Ignore printing LOCs.
59 _THREAD bool g_noinstid          = false; /// Ignore printing instruction id comments.
60 
printAsmName(const print_format_provider_t * header)61 const char *printAsmName(const print_format_provider_t* header)
62 {
63     for (unsigned i = 0; i < header->getAttrCount(); i++)
64     {
65         const char* attrName = header->getString(header->getAttr(i)->nameIndex);
66         if (Attributes::isAttribute(Attributes::ATTR_OutputAsmPath, attrName))
67             return header->getAttr(i)->value.stringVal;
68     }
69 
70     return "";
71 }
72 
getGenVarName(int id,const print_format_provider_t & header)73 const char *getGenVarName(int id, const print_format_provider_t& header)
74 {
75     int numPredefined = Get_CISA_PreDefined_Var_Count();
76     if (id < numPredefined)
77     {
78         return getPredefinedVarString(mapExternalToInternalPreDefVar(id));
79     }
80     else
81     {
82         MUST_BE_TRUE((id - numPredefined) < (int) header.getVarCount(),
83             "invalid vISA general variable id");
84         return header.getString(header.getVar(id - numPredefined)->name_index);
85     }
86 }
87 
printSurfaceName(uint32_t declID)88 static std::string printSurfaceName(uint32_t declID)
89 {
90     std::stringstream sstr;
91     unsigned numPreDefinedSurf = Get_CISA_PreDefined_Surf_Count();
92     if (declID < numPreDefinedSurf)
93     {
94         sstr << vISAPreDefSurf[declID].name;
95     }
96     else
97     {
98         sstr << "T" << declID;
99     }
100 
101     return sstr.str();
102 }
103 
printVariableDeclName(const print_format_provider_t * header,unsigned declID,const Options * options,Common_ISA_State_Opnd_Class operand_prefix_kind=NOT_A_STATE_OPND)104 std::string printVariableDeclName(
105     const print_format_provider_t* header,
106     unsigned declID,
107     const Options *options,
108     Common_ISA_State_Opnd_Class operand_prefix_kind = NOT_A_STATE_OPND)
109 {
110     MUST_BE_TRUE(header, "Argument Exception: argument header is NULL.");
111     std::stringstream sstr;
112 
113     unsigned numPreDefinedVars = Get_CISA_PreDefined_Var_Count();
114     if (operand_prefix_kind == NOT_A_STATE_OPND)
115     {
116         sstr << getGenVarName(declID, *header);
117     }
118     else
119     {
120         switch (operand_prefix_kind)
121         {   case STATE_OPND_SURFACE : sstr << printSurfaceName(declID); break;
122             case STATE_OPND_SAMPLER : sstr << "S"   << declID; break;
123             default                 :
124                 if (!options->getOption(vISA_PlatformIsSet))
125                 {
126                     // If platform is not set then dcl instances are
127                     // not created causing a crash. So print dcl name
128                     // the old way.
129                     if (declID < numPreDefinedVars)
130                     {
131                         sstr << "V" << declID;
132                     }
133                     else
134                     {
135                         declID -= numPreDefinedVars;
136                         const var_info_t *var = header->getVar(declID);
137                         std::string name = header->getString(var->name_index);
138                         sstr << name;
139                     }
140                 }
141                 else
142                 {
143 
144                     if (declID < numPreDefinedVars)
145                     {
146                         sstr << "V" << declID;
147                     }
148                     else
149                     {
150                         G4_Declare* aliasDcl = header->getVar(declID - numPreDefinedVars)->dcl;
151                         unsigned int aliasOff = 0;
152                         std::string type = TypeSymbol(aliasDcl->getElemType());
153 
154                         while (aliasDcl->getAliasDeclare() != NULL)
155                         {
156                             aliasOff += aliasDcl->getAliasOffset();
157                             aliasDcl = aliasDcl->getAliasDeclare();
158                         }
159 
160                         // aliasDcl is top most dcl with aliasOff
161                         // Lets find out declID of aliasDcl
162                         for (unsigned int i = 0; i < header->getVarCount(); i++)
163                         {
164                             if (header->getVar(i)->dcl == aliasDcl)
165                             {
166                                 declID = i + numPreDefinedVars;
167                                 break;
168                             }
169                         }
170 
171                         sstr << "V"   << declID << "_" << type;
172                         if (aliasOff != 0)
173                         {
174                             sstr << "_" << aliasOff;
175                         }
176                     }
177                 }
178 
179                 break;
180         }
181     }
182     return sstr.str();
183 }
184 
printRegion(uint16_t region)185 static std::string printRegion(uint16_t region)
186 {
187     std::stringstream sstr;
188     Common_ISA_Region_Val v_stride = (Common_ISA_Region_Val)(region & 0xF);
189     Common_ISA_Region_Val width = (Common_ISA_Region_Val)((region >> 4) & 0xF);
190     Common_ISA_Region_Val h_stride = (Common_ISA_Region_Val)((region >> 8) & 0xF);
191 
192     if (width == REGION_NULL)
193     {
194         //dst operand, only have horizontal stride
195         sstr << "<" << Common_ISA_Get_Region_Value(h_stride) << ">";
196     }
197     else if (v_stride == REGION_NULL)
198     {
199         // VxH mode for indirect operand
200         sstr << "<" << Common_ISA_Get_Region_Value(width) << "," << Common_ISA_Get_Region_Value(h_stride) << ">";
201     }
202     else
203     {
204         if (g_shortRegionPrint                         &&
205             0 == Common_ISA_Get_Region_Value(v_stride) &&
206             1 == Common_ISA_Get_Region_Value(width)    &&
207             0 == Common_ISA_Get_Region_Value(h_stride))
208         {
209             sstr << ".s";
210         }
211         else if (g_shortRegionPrint &&
212                 Common_ISA_Get_Region_Value(v_stride) ==
213                 Common_ISA_Get_Region_Value(width) &&
214                 1 == Common_ISA_Get_Region_Value(h_stride))
215         {
216             sstr << ".v";
217         }
218         else
219         {
220             sstr << "<" << Common_ISA_Get_Region_Value(v_stride) << ";" << Common_ISA_Get_Region_Value(width) << "," << Common_ISA_Get_Region_Value(h_stride) << ">";
221         }
222     }
223 
224     return sstr.str();
225 }
226 
printVectorOperand(const print_format_provider_t * header,const VISA_opnd * parentOpnd,const Options * opt,bool showRegion)227 std::string printVectorOperand(
228     const print_format_provider_t* header,
229     const VISA_opnd* parentOpnd,
230     const Options *opt,
231     bool showRegion)
232 {
233     std::stringstream sstr;
234 
235     auto opnd = parentOpnd->_opnd.v_opnd;
236     MUST_BE_TRUE(header, "Argument Exception: argument header is NULL.");
237 
238     VISA_Modifier modifier = (VISA_Modifier)((opnd.tag >> 3) & 0x7);
239 
240     /// .sat is dumped with the opcode
241     if (modifier == MODIFIER_SAT)
242         modifier =  MODIFIER_NONE;
243 
244     sstr << " ";
245     switch (opnd.tag & 0x7)
246     {
247         case OPERAND_GENERAL:
248         {
249             sstr << Common_ISA_Get_Modifier_Name(modifier)
250                 << printVariableDeclName(header, opnd.getOperandIndex(), opt, NOT_A_STATE_OPND);
251 
252             if ((!g_shortRegionPrint)                      ||
253                 (!(opnd.opnd_val.gen_opnd.row_offset == 0 &&
254                 (((opnd.opnd_val.gen_opnd.col_offset == 0))))))
255             {
256                 sstr << "("
257                      << (unsigned)opnd.opnd_val.gen_opnd.row_offset << ","
258                      << (unsigned)opnd.opnd_val.gen_opnd.col_offset << ")";
259             }
260 
261             if (showRegion)
262             {
263                 sstr << printRegion(opnd.opnd_val.gen_opnd.region);
264             }
265 
266             break;
267         }
268         case OPERAND_ADDRESS:
269         {
270             sstr << Common_ISA_Get_Modifier_Name(modifier) << "A" << opnd.opnd_val.addr_opnd.index
271                  << "(" << (unsigned)opnd.opnd_val.addr_opnd.offset << ")<"
272                  << Get_VISA_Exec_Size((VISA_Exec_Size)(opnd.opnd_val.addr_opnd.width & 0xF)) << ">";
273             break;
274         }
275         case OPERAND_PREDICATE:
276         {
277             sstr << Common_ISA_Get_Modifier_Name(modifier) << "P" << parentOpnd->convertToPred().getId();
278             break;
279         }
280         case OPERAND_INDIRECT:
281         {
282             sstr << Common_ISA_Get_Modifier_Name(modifier) << "r[A" << opnd.opnd_val.indirect_opnd.index
283                  << "("
284                  << (unsigned)opnd.opnd_val.indirect_opnd.addr_offset     << "),"
285                  << (short)   opnd.opnd_val.indirect_opnd.indirect_offset << "]" ;
286             sstr << printRegion(opnd.opnd_val.indirect_opnd.region);
287             VISA_Type type = (VISA_Type)(opnd.opnd_val.indirect_opnd.bit_property & 0xf);
288             sstr << ":" << CISATypeTable[type].typeName;
289             break;
290         }
291         case OPERAND_ADDRESSOF:
292         {
293             sstr << "&" << printVariableDeclName(header, opnd.getOperandIndex(), opt, NOT_A_STATE_OPND);
294             if (opnd.opnd_val.addressof_opnd.addr_offset >= 0) {
295                 sstr << "[" << (((short)opnd.opnd_val.addressof_opnd.addr_offset)) << "]";
296             }
297             break;
298         }
299         case OPERAND_IMMEDIATE:
300         {
301             VISA_Type type = (VISA_Type)(opnd.opnd_val.const_opnd.type & 0xF);
302             if (type == ISA_TYPE_DF)
303                 sstr << "0x" << std::hex <<
304                     *((uint64_t*) &opnd.opnd_val.const_opnd._val.dval) <<
305                     ":" << CISATypeTable[type].typeName << std::dec;
306             else if (type == ISA_TYPE_Q || type == ISA_TYPE_UQ)
307                 sstr << "0x" << std::hex << opnd.opnd_val.const_opnd._val.lval <<
308                         ":" << CISATypeTable[type].typeName << std::dec;
309             else
310                 sstr << "0x" << std::hex << opnd.opnd_val.const_opnd._val.ival <<
311                     ":" << CISATypeTable[type].typeName << std::dec;
312             break;
313         }
314         case OPERAND_STATE:
315         {
316             sstr << printVariableDeclName(header, opnd.getOperandIndex(), opt, (Common_ISA_State_Opnd_Class)opnd.opnd_val.state_opnd.opnd_class)
317                  << "(" << (unsigned)opnd.opnd_val.state_opnd.offset << ")";
318             break;
319         }
320         default: ASSERT_USER(false, "Attempted to dump an invalid or unimplemented vector operand type.");
321     }
322 
323     return sstr.str();
324 }
325 
printRawOperand(const print_format_provider_t * header,const raw_opnd & opnd,const Options * opt)326 std::string printRawOperand(
327     const print_format_provider_t* header,
328     const raw_opnd& opnd,
329     const Options *opt)
330 {
331     MUST_BE_TRUE(header, "Argument Exception: argument header is NULL.");
332     std::stringstream sstr;
333     sstr << " " << printVariableDeclName(header, opnd.index, opt, NOT_A_STATE_OPND) << "." << opnd.offset;
334     return sstr.str();
335 }
336 
printOperand(const print_format_provider_t * header,const CISA_INST * inst,unsigned i,const Options * opt)337 static std::string printOperand(
338     const print_format_provider_t* header,
339     const CISA_INST* inst,
340     unsigned i,
341     const Options *opt)
342 {
343     MUST_BE_TRUE(header, "Argument Exception: argument header is NULL.");
344     MUST_BE_TRUE(inst  , "Argument Exception: argument inst   is NULL.");
345     MUST_BE_TRUE(inst->opnd_count > i, "No such operand, i, for instruction inst.");
346     std::stringstream sstr;
347     switch (getOperandType(inst, i))
348     {
349         case CISA_OPND_OTHER:  sstr << (getPrimitiveOperand<unsigned>             (inst, i)); break;
350         case CISA_OPND_VECTOR: sstr << printVectorOperand(header, inst->opnd_array[i], opt, true); break;
351         case CISA_OPND_RAW:    sstr << printRawOperand   (header, getRawOperand   (inst, i), opt); break;
352         default:               MUST_BE_TRUE(false, "Invalid operand type.");
353     }
354     return sstr.str();
355 }
356 
encodeStringLiteral(std::stringstream & ss,const char * str)357 static void encodeStringLiteral(std::stringstream &ss, const char *str) {
358   ss << '"';
359   for (size_t i = 0, slen = strlen(str); i < slen; i++) {
360       switch (str[i]) { // unsigned so >0x7F doesn't sign ext.
361       case '\a': ss << '\\'; ss << 'a'; break;
362       case '\b': ss << '\\'; ss << 'b'; break;
363       case 0x1B: ss << '\\'; ss << 'e'; break;
364       case '\f': ss << '\\'; ss << 'f'; break;
365       case '\n': ss << '\\'; ss << 'n'; break;
366       case '\r': ss << '\\'; ss << 'r'; break;
367       case '\t': ss << '\\'; ss << 't'; break;
368       case '\v': ss << '\\'; ss << 'v'; break;
369       //
370       case '\'': ss << '\\'; ss << '\''; break;
371       case '"':  ss << '\\'; ss << '"'; break;
372       //
373       case '\\': ss << '\\'; ss << '\\'; break;
374       default:
375           if (std::isprint((unsigned char)str[i])) {
376               ss << str[i];
377           } else {
378               ss << "\\x" << std::setw(2) << std::setfill('0') << std::hex <<
379                   (unsigned)((unsigned char)str[i]);
380           }
381       }
382   }
383   ss << '"';
384 }
385 
printAttributes(const print_format_provider_t * header,const int attr_count,const attribute_info_t * attrs)386 std::string printAttributes(
387     const print_format_provider_t* header,
388     const int attr_count,
389     const attribute_info_t* attrs)
390 {
391     std::stringstream sstr;
392 
393     if (attr_count > 0)
394     {
395         // decl's attr in the form: attr=<attr0, attr1, ...>
396         sstr << " attrs={" << printOneAttribute(header, &attrs[0]);
397         for (int j = 1; j < attr_count; j++)
398         {
399             sstr << ", " << printOneAttribute(header, &attrs[j]);
400         }
401         sstr << "}";
402     }
403 
404     return sstr.str();
405 }
406 
printOneAttribute(const print_format_provider_t * kernel,const attribute_info_t * attr)407 std::string printOneAttribute(
408     const print_format_provider_t* kernel,
409     const attribute_info_t* attr)
410 {
411     std::stringstream sstr;
412     const char* attrName = kernel->getString(attr->nameIndex);
413     Attributes::ID aID = Attributes::getAttributeID(attrName);
414     MUST_BE_TRUE(aID != Attributes::ATTR_INVALID, "Invalid Attribute names!");
415 
416     sstr << attrName;
417     if (attr->isInt && Attributes::isInt32(aID)) {
418         sstr << "=";
419         if (Attributes::isAttribute(Attributes::ATTR_Target, attrName)) {
420             switch (attr->value.intVal) {
421             case VISA_CM: sstr << "\"cm\""; break;
422             case VISA_3D: sstr << "\"3d\""; break;
423             default:
424               sstr << attr->value.intVal;
425             }
426         } else {
427             sstr << attr->value.intVal;
428         }
429     } else if (Attributes::isCStr(aID) && attr->size > 0) {
430         sstr << "=";
431         encodeStringLiteral(sstr, attr->value.stringVal);
432     }
433 
434     return sstr.str();
435 }
436 
printPredicateDecl(const print_format_provider_t * header,unsigned declID)437 std::string printPredicateDecl(
438     const print_format_provider_t* header, unsigned declID)
439 {
440     MUST_BE_TRUE(header, "Argument Exception: argument header is NULL.");
441     std::stringstream sstr;
442 
443     const pred_info_t* pred = header->getPred(declID);
444     sstr << ".decl P"
445          << declID + COMMON_ISA_NUM_PREDEFINED_PRED
446          << " "
447          << "v_type=P "
448          << "num_elts=" << pred->num_elements;
449 
450     sstr << printAttributes(header, pred->attribute_count, pred->attributes);
451     return sstr.str();
452 }
453 
printAddressDecl(const common_isa_header & isaHeader,const print_format_provider_t * header,unsigned declID)454 std::string printAddressDecl(
455     const common_isa_header& isaHeader,
456     const print_format_provider_t* header,
457     unsigned declID)
458 {
459     MUST_BE_TRUE(header, "Argument Exception: argument header is NULL.");
460     std::stringstream sstr;
461 
462     const addr_info_t* addr = header->getAddr(declID);
463     sstr << ".decl A"
464          << declID
465          << " "
466          << "v_type=A "
467          << "num_elts=" << addr->num_elements;
468 
469     sstr << printAttributes(header, addr->attribute_count, addr->attributes);
470 
471     return sstr.str();
472 }
473 
printSamplerDecl(const print_format_provider_t * header,unsigned declID)474 std::string printSamplerDecl(
475     const print_format_provider_t* header, unsigned declID)
476 {
477     MUST_BE_TRUE(header, "Argument Exception: argument header is NULL.");
478     std::stringstream sstr;
479     const state_info_t* info = header->getSampler(declID);
480 
481     sstr << ".decl S" << declID << " v_type=S";
482     sstr << " num_elts=" << info->num_elements;
483     sstr << " v_name=" << header->getString(info->name_index);
484     sstr << printAttributes(header, info->attribute_count, info->attributes);
485     return sstr.str();
486 }
487 
printSurfaceDecl(const print_format_provider_t * header,unsigned declID,unsigned numPredefinedSurfaces)488 std::string printSurfaceDecl(
489     const print_format_provider_t* header,
490     unsigned declID,
491     unsigned numPredefinedSurfaces)
492 {
493     MUST_BE_TRUE(header, "Argument Exception: argument header is NULL.");
494     std::stringstream sstr;
495     const state_info_t* info = header->getSurface(declID);
496 
497     sstr << ".decl T" << declID + numPredefinedSurfaces << " v_type=T";
498     sstr << " num_elts=" << info->num_elements;
499     sstr << " v_name=" << header->getString(info->name_index);
500     sstr << printAttributes(header, info->attribute_count, info->attributes);
501     return sstr.str();
502 }
503 
printFuncInput(const print_format_provider_t * header,unsigned declID,bool isKernel,const Options * options)504 std::string printFuncInput(
505     const print_format_provider_t* header,
506     unsigned declID,
507     bool isKernel,
508     const Options* options)
509 {
510     MUST_BE_TRUE(header, "Argument Exception: argument header is NULL.");
511     std::stringstream sstr;
512 
513     const input_info_t* input = header->getInput(declID);
514     if (!isKernel)
515     {
516         sstr << ".parameter " /* function */;
517     }
518     else if (!input->getImplicitKind())
519     {
520         sstr << ".input " /* kernel */;
521     }
522     else
523     {
524         sstr << input->getImplicitKindString() << " ";
525     }
526 
527     if (INPUT_GENERAL == input->getInputClass())
528     {
529         sstr << printVariableDeclName(header, input->index, options);
530     }
531     else
532     {
533         const char* Input_Class_String[] = { "V", "S", "T" };
534         sstr << Input_Class_String[input->getInputClass()] << input->index;
535     }
536 
537     if (isKernel)
538         sstr << " offset=" << input->offset;
539 
540     sstr << " size=" << input->size;
541 
542     return sstr.str();
543 }
544 
545 // declID is in the range of [0..#user-var], pre-defnied are not included
printVariableDecl(const print_format_provider_t * header,unsigned declID,const Options * options)546 std::string printVariableDecl(
547     const print_format_provider_t* header,
548     unsigned declID,
549     const Options *options)
550 {
551     MUST_BE_TRUE(header, "Argument Exception: argument header is NULL.");
552     std::stringstream sstr;
553 
554     const var_info_t* var = header->getVar(declID);
555     VISA_Type  isa_type = (VISA_Type)((var->bit_properties) & 0xF);
556     VISA_Align align = var->getAlignment();
557 
558     unsigned numPreDefinedVars = Get_CISA_PreDefined_Var_Count();
559     sstr << ".decl " << printVariableDeclName(header, declID + numPreDefinedVars, options)
560         << " v_type=G"
561         << " type=" << CISATypeTable[isa_type].typeName
562         << " num_elts=" << var->num_elements;
563 
564     if (align != ALIGN_UNDEF)
565         sstr << " align=" << Common_ISA_Get_Align_Name(align);
566 
567     if (var->alias_index)
568     {
569         sstr << " alias=<";
570         sstr << printVariableDeclName(header, var->alias_index, options);
571         sstr << ", " << var->alias_offset << ">";
572     }
573 
574     sstr << printAttributes(header, var->attribute_count, var->attributes);
575 
576     return sstr.str();
577 }
578 
printExecutionSize(uint8_t opcode,uint8_t execSize,uint8_t subOp=0)579 static std::string printExecutionSize(
580     uint8_t opcode, uint8_t execSize, uint8_t subOp = 0)
581 {
582     std::stringstream sstr;
583 
584     if (hasExecSize((ISA_Opcode)opcode, subOp))
585     {
586         sstr << "(";
587         uint8_t emsk = ((execSize >> 0x4) & 0xF);
588         sstr << emask_str[emsk] << ", ";
589         sstr << (unsigned) Get_VISA_Exec_Size((VISA_Exec_Size)(execSize & 0xF));
590         sstr << ")";
591     }
592 
593     if (g_shortRegionPrint && !strcmp("(1)", sstr.str().c_str()))
594         return "   ";
595 
596     return sstr.str();
597 }
598 
599 // execution size is formatted differently for scatter/gather/scatter4/gather4/scatter4_typed/gather4_typed
printExecutionSizeForScatterGather(uint8_t sizeAndMask)600 static std::string printExecutionSizeForScatterGather(uint8_t sizeAndMask)
601 {
602     std::stringstream sstr;
603     sstr << "(";
604     VISA_EMask_Ctrl emask =
605         (VISA_EMask_Ctrl)((sizeAndMask >> 0x4) & 0xF);
606     sstr << emask_str[emask] << ", ";
607 
608     unsigned execSize = 0;
609     switch (sizeAndMask & 0x3)
610     {
611     case 0:
612         execSize = 8;
613         break;
614     case 1:
615         execSize = 16;
616         break;
617     case 2:
618         execSize = 1;
619         break;
620     default:
621         ASSERT_USER(false, "illegal execution size for scatter/gather message");
622     }
623     sstr << execSize;
624     sstr << ")";
625 
626     return sstr.str();
627 }
628 
printPredicate(uint8_t opcode,PredicateOpnd predOpnd)629 static std::string printPredicate(uint8_t opcode, PredicateOpnd predOpnd)
630 {
631     std::stringstream sstr;
632 
633     if (hasPredicate((ISA_Opcode)opcode) && !predOpnd.isNullPred())
634     {
635         sstr << "(";
636         if (predOpnd.isInverse()) sstr << "!";
637         sstr << "P" << predOpnd.getId();
638 
639         VISA_PREDICATE_CONTROL control = predOpnd.getControl();
640         switch (control)
641         {
642             case PRED_CTRL_ANY:
643                 sstr << ".any";
644                 break;
645             case PRED_CTRL_ALL:
646                 sstr << ".all";
647                 break;
648             default:
649                 break;
650         }
651 
652         sstr << ") ";
653     }
654 
655     return sstr.str();
656 }
657 
printAtomicSubOpc(std::stringstream & sstr,uint8_t value)658 static void printAtomicSubOpc(std::stringstream &sstr, uint8_t value)
659 {
660     VISAAtomicOps op = static_cast<VISAAtomicOps>(value & 0x1F);
661     sstr << "." << CISAAtomicOpNames[op];
662 
663     if ((value >> 5) == 1)
664     {
665         sstr << ".16";
666     }
667     else if ((value >> 6) == 1)
668     {
669         sstr << ".64";
670     }
671 }
672 
printInstructionSVM(const print_format_provider_t * header,const CISA_INST * inst,const Options * opt)673 static std::string printInstructionSVM(
674     const print_format_provider_t* header,
675     const CISA_INST* inst,
676     const Options *opt)
677 {
678     unsigned i = 0;
679     std::stringstream sstr;
680 
681     SVMSubOpcode subOpcode = (SVMSubOpcode)getPrimitiveOperand<uint8_t>(inst, i++);
682 
683     /// TODO: Print out the predicate here
684     sstr << "svm_";
685     switch (subOpcode)
686     {
687         case SVM_BLOCK_ST:
688         case SVM_BLOCK_LD:
689             {
690              sstr << "block_" << (subOpcode == SVM_BLOCK_ST ? "st" : "ld");
691              uint8_t properties = getPrimitiveOperand<uint8_t>(inst, i++);
692              if (properties & 8)
693                  sstr << ".unaligned";
694              VISA_Oword_Num numOwords = (VISA_Oword_Num) (properties & 0x7);
695              sstr << " (" << Get_VISA_Oword_Num(numOwords) << ")";
696              break;
697             }
698         case SVM_GATHER:
699         case SVM_SCATTER:
700         {
701              sstr << (subOpcode == SVM_GATHER ? "gather" : "scatter");
702              uint8_t block_size = getPrimitiveOperand<uint8_t>(inst, i++);
703              uint8_t num_blocks = getPrimitiveOperand<uint8_t>(inst, i++);
704              sstr << "." << Get_Common_ISA_SVM_Block_Size((VISA_SVM_Block_Type)block_size);
705              sstr << "." << Get_Common_ISA_SVM_Block_Num((VISA_SVM_Block_Num)num_blocks);
706              sstr << " " << printExecutionSize(inst->opcode, inst->execsize, subOpcode);
707              break;
708         }
709         case SVM_ATOMIC:
710         {
711             sstr << "atomic";
712             /// TODO: Need platform information for this to work.
713 
714             printAtomicSubOpc(sstr, getPrimitiveOperand<uint8_t>(inst, i++));
715             sstr << " " << printExecutionSize(inst->opcode, inst->execsize, subOpcode);
716             /// element offset
717             sstr << printOperand(header, inst, i++, opt);
718             /// DWORD_ATOMIC is weird and has the text version
719             /// putting the dst operand before the src operands.
720             std::stringstream sstr1;
721             /// src0
722             sstr1 << printOperand(header, inst, i++, opt);
723             /// src1
724             sstr1 << printOperand(header, inst, i++, opt);
725             /// message operand (src or dst)
726             sstr << printOperand(header, inst, i++, opt);
727             sstr << sstr1.str();
728             break;
729         }
730         case SVM_GATHER4SCALED:
731         case SVM_SCATTER4SCALED:
732         {
733             sstr << (subOpcode == SVM_GATHER4SCALED ? "gather4scaled" : "scatter4scaled");
734             unsigned chMask = getPrimitiveOperand<uint8_t>(inst, i++);
735             // scale is ignored (MBZ)
736             (void) getPrimitiveOperand<uint16_t>(inst, i++);
737             sstr << "." << channel_mask_str[chMask];
738             sstr << " " << printExecutionSize(inst->opcode, inst->execsize, subOpcode);
739             sstr << printOperand(header, inst, i++, opt);
740             sstr << printOperand(header, inst, i++, opt);
741             sstr << printOperand(header, inst, i++, opt);
742             break;
743         }
744         default:
745              ASSERT_USER(false, "Unimplemented or Illegal SVM Sub Opcode.");
746     }
747 
748     for (; i < inst->opnd_count; i++)
749         sstr << printOperand(header, inst, i, opt);
750 
751     return sstr.str();
752 }
753 
printInstructionCommon(const print_format_provider_t * header,const CISA_INST * inst,const Options * opt)754 static std::string printInstructionCommon(
755     const print_format_provider_t* header,
756     const CISA_INST* inst,
757     const Options *opt)
758 {
759     ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
760 
761     std::stringstream sstr;
762     sstr << printPredicate(inst->opcode, inst->pred);
763 
764     unsigned i = 0;
765 
766     /// Print opcode
767     if (opcode == ISA_FMINMAX)
768     {
769         CISA_MIN_MAX_SUB_OPCODE sub_opcode = (CISA_MIN_MAX_SUB_OPCODE)getPrimitiveOperand<uint8_t>(inst, i++);
770         sstr << (sub_opcode == CISA_DM_FMIN ? "min" : "max");
771     }
772     else
773     {
774         sstr << ISA_Inst_Table[opcode].str;
775     }
776 
777     if (ISA_Inst_Sync != ISA_Inst_Table[opcode].type)
778     {
779         unsigned int Count = inst->opnd_count;
780 
781         if (ISA_Inst_Compare == ISA_Inst_Table[opcode].type)
782         {
783             uint8_t relOp = getPrimitiveOperand<uint8_t>(inst, i++);
784             sstr << (((relOp >> 7) & 0x1) ? "n" : ""); /// INFO: cmpn opcode print support here.
785             sstr << "." << Rel_op_str[(unsigned)(relOp & 0x7)];
786         }
787         else if (opcode == ISA_BFN)
788         {
789             // print BooleanFuncCtrl right after op name
790             sstr << ".x" << std::hex << (uint32_t)(getPrimitiveOperand<uint8_t>(inst, Count-1)) << std::dec;
791             // The following shall skip booleanFuncCtrl opnd
792             --Count;
793         }
794 
795         if (ISA_Inst_Arith   == ISA_Inst_Table[opcode].type ||
796             ISA_Inst_Mov     == ISA_Inst_Table[opcode].type ||
797             ISA_Inst_Logic   == ISA_Inst_Table[opcode].type ||
798             ISA_Inst_Address == ISA_Inst_Table[opcode].type ||
799             ISA_Inst_Compare == ISA_Inst_Table[opcode].type)
800         {
801             bool saturate = (((VISA_Modifier)((getVectorOperand(inst, i).tag >> 3) & 0x7)) == MODIFIER_SAT);
802             sstr << (saturate ? ".sat" : "");
803         }
804 
805         sstr << " " << printExecutionSize(inst->opcode, inst->execsize);
806 
807         if (opcode == ISA_GOTO)
808         {
809             uint16_t label_id = getPrimitiveOperand<uint16_t>(inst, i++);
810             sstr << " " << header->getString(header->getLabel(label_id)->name_index);
811         }
812 
813         for (; i < Count; i++)
814         {
815 
816             if (opcode == ISA_ADDR_ADD && i == 1) /// Only for src0 of addr_add
817             {
818                 const vector_opnd& curOpnd = getVectorOperand(inst, i);
819 
820                 if (curOpnd.getOperandClass() == OPERAND_ADDRESS)
821                 {
822                     sstr << printVectorOperand(header, inst->opnd_array[i], opt, true);
823                 }
824                 else
825                 {
826                     sstr << " " << Common_ISA_Get_Modifier_Name((VISA_Modifier)((curOpnd.tag >> 3) & 0x7));
827 
828                     unsigned opnd_index = curOpnd.getOperandIndex();
829 
830                     if (curOpnd.getOperandClass() == OPERAND_GENERAL)
831                     {
832                         uint32_t numPredefined = Get_CISA_PreDefined_Var_Count();
833                         VISA_Type type = opnd_index < numPredefined ?
834                             getPredefinedVarType(mapExternalToInternalPreDefVar(opnd_index)) :
835                             header->getVar(opnd_index - numPredefined)->getType();
836                         sstr << "&" << printVariableDeclName(header, opnd_index, opt);
837                         int offset =
838                             curOpnd.opnd_val.gen_opnd.col_offset * CISATypeTable[type].typeSize +
839                             curOpnd.opnd_val.gen_opnd.row_offset * numEltPerGRF<Type_UB>();
840                         if (offset) {
841                             sstr << "[" << offset << "]";
842                         }
843                     }
844                     else if (curOpnd.getOperandClass() == OPERAND_STATE)
845                     {
846                         auto OpClass = curOpnd.getStateOpClass();
847                         sstr << "&" << printVariableDeclName(header, opnd_index, opt, OpClass);
848                         int offset =
849                             curOpnd.opnd_val.state_opnd.offset * CISATypeTable[ISA_TYPE_D].typeSize;
850                         if (offset) {
851                             sstr << "[" << offset << "]";
852                         }
853                     }
854                     else
855                     {
856                         /// TODO: Should we just assert here? Is this allowed?
857                         sstr << printOperand(header, inst, i, opt);
858                     }
859                 }
860             }
861             else
862             {
863                 sstr << printOperand(header, inst, i, opt);
864             }
865         }
866     }
867     else
868     {
869         if (opcode == ISA_FENCE)
870         {
871             uint8_t mask = getPrimitiveOperand<uint8_t>(inst, i);
872 
873             const int SWFenceMask = 0x80;
874             if (mask & SWFenceMask)
875             {
876                 sstr << "_sw";
877             }
878             else
879             {
880 
881 #define BTI_MASK 0x20 // bit 5
882                 sstr << ((mask & BTI_MASK) ? "_local" : "_global");
883                 if (mask != 0)
884                 {
885                     sstr << ".";
886                     if (mask & 1) sstr << "E";
887                     if (mask & (1 << 1)) sstr << "I";
888                     if (mask & (1 << 2)) sstr << "S";
889                     if (mask & (1 << 3)) sstr << "C";
890                     if (mask & (1 << 4)) sstr << "R";
891                     if (mask & (1 << 6)) sstr << "L1";
892                 }
893             }
894         }
895         else if (opcode == ISA_WAIT)
896         {
897             sstr << printOperand(header, inst, 0, opt);
898         }
899         else if (opcode == ISA_SBARRIER)
900         {
901             uint8_t mode = getPrimitiveOperand<uint8_t>(inst, i);
902             sstr << (mode ? ".signal" : ".wait");
903         }
904         else if (opcode == ISA_NBARRIER)
905         {
906             uint8_t mode = getPrimitiveOperand<uint8_t>(inst, i);
907             bool isSignal = mode & 1;
908             sstr << (isSignal ? ".signal" : ".wait");
909             sstr << printOperand(header, inst, 1, opt);
910             if (isSignal)
911             {
912                 sstr << printOperand(header, inst, 2, opt);
913             }
914         }
915     }
916 
917     return sstr.str();
918 }
919 
printInstructionControlFlow(const print_format_provider_t * header,const CISA_INST * inst,const Options * opt)920 static std::string printInstructionControlFlow(
921     const print_format_provider_t* header,
922     const CISA_INST* inst,
923     const Options *opt)
924 {
925     const ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
926     unsigned i = 0;
927     uint16_t label_id  = 0;
928 
929     std::stringstream sstr;
930 
931     // Subroutine function name may contains "." or "$" generated by llvm when cloning
932     // functions. Replace those to underline in visaasm so that it can be accepted by
933     // visaasm reader.
934     auto replaceInvalidCharToUnderline = [](std::string str) {
935         std::replace(str.begin(), str.end(), '.', '_');
936         std::replace(str.begin(), str.end(), '$', '_');
937         return str;
938     };
939 
940     if (ISA_SUBROUTINE == opcode || ISA_LABEL == opcode)
941     {
942         label_id = getPrimitiveOperand<uint16_t>(inst, i++);
943 
944         sstr << "\n";
945         switch (opcode)
946         {
947             case ISA_SUBROUTINE:
948             {
949                  std::stringstream uniqueSuffixSstr; uniqueSuffixSstr << '_' << label_id;
950                  std::string       uniqueSuffixStr = uniqueSuffixSstr.str();
951 
952                  std::string labelName(header->getString(header->getLabel(label_id)->name_index));
953 
954                  auto replacedName = replaceInvalidCharToUnderline(labelName);
955 
956                  sstr << ".function ";
957                  encodeStringLiteral(sstr, (replacedName + uniqueSuffixStr).c_str());
958                  // add a comment to specify the original name if the name change
959                  if (replacedName != labelName) {
960                      sstr << " /// Original Name: ";
961                      encodeStringLiteral(sstr, (labelName + uniqueSuffixStr).c_str());
962                  }
963                  sstr << "\n\n" << replaceInvalidCharToUnderline(labelName) << uniqueSuffixStr;
964                  break;
965             }
966             case ISA_LABEL:
967             {
968                  sstr << replaceInvalidCharToUnderline(header->getString(header->getLabel(label_id)->name_index));
969                  break;
970             }
971             default:
972                  break;
973         }
974 
975         sstr << ":";
976     }
977     else if (opcode == ISA_CALL)
978     {
979         // Special handlling of CALL to distinguish fc_call from subroutine call
980         label_id = getPrimitiveOperand<uint16_t>(inst, i++);
981 
982         const label_info_t* lblinfo = header->getLabel(label_id);
983         const char* instName = (lblinfo->kind == LABEL_FC ? "fccall" : ISA_Inst_Table[opcode].str);
984         sstr << printPredicate(opcode, inst->pred)
985              << instName
986              << " "
987              << printExecutionSize(opcode, inst->execsize)
988              << " "
989              << replaceInvalidCharToUnderline(header->getString(lblinfo->name_index))
990              << "_"
991              << label_id;
992     }
993     else
994     {
995         sstr << printPredicate(inst->opcode, inst->pred)
996              << ISA_Inst_Table[opcode].str
997              << " "
998              << printExecutionSize(inst->opcode, inst->execsize);
999 
1000         switch (opcode)
1001         {
1002             case ISA_JMP:
1003             case ISA_GOTO:
1004             case ISA_FCALL:
1005             {
1006                 /// label / function id to jump / call to.
1007                 label_id = getPrimitiveOperand<uint16_t>(inst, i++);
1008 
1009                 if (opcode == ISA_FCALL)
1010                 {
1011                     /// function name in string
1012                     sstr << " " << replaceInvalidCharToUnderline(header->getString(label_id));
1013                 }
1014                 else
1015                 {
1016                     sstr << " " << replaceInvalidCharToUnderline(header->getString(header->getLabel(label_id)->name_index));
1017                     if (header->getLabel(label_id)->kind == LABEL_SUBROUTINE)
1018                         sstr << "_" << label_id;
1019                 }
1020 
1021                 if (opcode == ISA_FCALL)
1022                 {
1023                     /// arg size
1024                     sstr << " " << getPrimitiveOperand<unsigned>(inst, i++);
1025 
1026                     /// return size
1027                     sstr << " " << getPrimitiveOperand<unsigned>(inst, i++);
1028                 }
1029 
1030                 break;
1031             }
1032             case ISA_IFCALL:
1033             {
1034                 sstr << printOperand(header, inst, i++, opt);
1035                 /// arg size
1036                 sstr << " " << getPrimitiveOperand<unsigned>(inst, i++);
1037                 /// return size
1038                 sstr << " " << getPrimitiveOperand<unsigned>(inst, i++);
1039                 break;
1040             }
1041             case ISA_FADDR:
1042             {
1043                 /// symbol name in string
1044                 sstr << header->getString(getPrimitiveOperand<uint16_t>(inst, i++));
1045                 /// dst
1046                 sstr << printOperand(header, inst, i++, opt);
1047                 break;
1048             }
1049             case ISA_SWITCHJMP:
1050             {
1051                 /// skip num_labels
1052                 i++;
1053                 /// index
1054                 sstr << printOperand(header, inst, i++, opt);
1055                 sstr << " (";
1056                 for (bool first = true; i < inst->opnd_count; i++)
1057                 {
1058                     if (!first) { sstr << ", "; }
1059                     label_id = getPrimitiveOperand<uint16_t>(inst, i);
1060                     sstr << header->getString(header->getLabel(label_id)->name_index);
1061                     if (first) { first = false; }
1062                 }
1063                 sstr << ")";
1064                 break;
1065             }
1066             default:
1067                 break; // Prevent gcc warning
1068         }
1069     }
1070 
1071     return sstr.str();
1072 }
1073 
printInstructionMisc(const print_format_provider_t * header,const CISA_INST * inst,const Options * opt)1074 static std::string printInstructionMisc(
1075     const print_format_provider_t* header,
1076     const CISA_INST* inst,
1077     const Options *opt)
1078 {
1079     ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
1080     unsigned i = 0;
1081 
1082     std::stringstream sstr;
1083 
1084     if (opcode == ISA_3D_URB_WRITE)
1085     {
1086         sstr << printPredicate(inst->opcode, inst->pred);
1087     }
1088 
1089     switch (opcode)
1090     {
1091         case ISA_FILE:
1092         {
1093             uint32_t filename_index = getPrimitiveOperand<uint32_t>(inst, i++);
1094             sstr << "FILE ";
1095             encodeStringLiteral(sstr, header->getString(filename_index));
1096             break;
1097         }
1098         case ISA_LOC:
1099         {
1100             unsigned line_number = getPrimitiveOperand<unsigned>(inst, i++);
1101             sstr << "LOC " << line_number;
1102             break;
1103         }
1104         case ISA_RAW_SEND:
1105         {
1106             uint8_t modifiers = inst->modifier;
1107             i++; // skip the modifier
1108             uint32_t exMsgDesc = getPrimitiveOperand<uint32_t>(inst, i++); //32b
1109             uint8_t numSrc    = getPrimitiveOperand<uint8_t>(inst, i++);
1110             uint8_t numDst    = getPrimitiveOperand<uint8_t>(inst, i++);
1111             std::string opstring = modifiers == 1? "raw_sendc " : "raw_send ";
1112 
1113             sstr << printPredicate(inst->opcode, inst->pred)
1114                  << opstring.c_str()
1115                  << printExecutionSize(inst->opcode, inst->execsize)
1116                  << " "
1117                  << "0x" << std::hex << (uint32_t)exMsgDesc << std::dec
1118                  << " "
1119                  << (unsigned)numSrc
1120                  << " "
1121                  << (unsigned)numDst
1122                  << " ";
1123 
1124             /// desc
1125             sstr << printOperand(header, inst, i++, opt);
1126 
1127             /// src
1128             sstr << printOperand(header, inst, i++, opt);
1129 
1130             /// dst
1131             sstr << printOperand(header, inst, i++, opt);
1132 
1133             break;
1134         }
1135         case ISA_RAW_SENDS:
1136         {
1137             uint8_t modifiers = inst->modifier;
1138             i++; // skip the modifier
1139             uint8_t numSrc0    = getPrimitiveOperand<uint8_t>(inst, i++);
1140             uint8_t numSrc1    = getPrimitiveOperand<uint8_t>(inst, i++);
1141             uint8_t numDst     = getPrimitiveOperand<uint8_t>(inst, i++);
1142             std::string opstring = (modifiers & 0x1) == 1? "raw_sendsc." : "raw_sends.";
1143 
1144             sstr << printPredicate(inst->opcode, inst->pred)
1145                  << opstring.c_str();
1146 
1147             uint8_t ffid = getPrimitiveOperand<uint8_t>(inst, i++);
1148             sstr << (unsigned)ffid
1149                 << ".";
1150 
1151             if (modifiers & 0x2)
1152             {
1153                 sstr << "eot.";
1154             }
1155 
1156             sstr << (unsigned)numSrc0
1157                  << "."
1158                  << (unsigned)numSrc1
1159                  << "."
1160                  << (unsigned)numDst
1161                  << " "
1162                  << printExecutionSize(inst->opcode, inst->execsize)
1163                  << " ";
1164 
1165             /// exMsgDesc: could be imm or vector
1166             sstr << printOperand(header, inst, i++, opt);
1167 
1168             /// desc
1169             sstr << printOperand(header, inst, i++, opt);
1170 
1171             /// src0
1172             sstr << printOperand(header, inst, i++, opt);
1173 
1174             /// src1
1175             sstr << printOperand(header, inst, i++, opt);
1176 
1177             /// dst
1178             sstr << printOperand(header, inst, i++, opt);
1179 
1180             break;
1181         }
1182         case ISA_VME_FBR:
1183         {
1184              /// My typical pattern of printing these things doesn't work here since
1185              /// these VME instructions weirdly put the surface as the third operand.
1186              std::stringstream sstr1;
1187 
1188              /// uni input
1189              sstr1 << printOperand(header, inst, i++, opt);
1190 
1191              /// fbr input
1192              sstr1 << printOperand(header, inst, i++, opt);
1193 
1194              uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1195 
1196              std::stringstream sstr2;
1197 
1198              sstr2 << " T"
1199                    << (unsigned)surface
1200                    << " "
1201                    << sstr1.str();
1202 
1203              sstr << ISA_Inst_Table[opcode].str << " (";
1204 
1205              /// FBRMbMode
1206              sstr << printOperand(header, inst, i++, opt); sstr << ",";
1207 
1208              /// FBRSubMbShape
1209              sstr << printOperand(header, inst, i++, opt); sstr << ",";
1210 
1211              /// FBRSubPredMode
1212              sstr << printOperand(header, inst, i++, opt);
1213 
1214              sstr << ")";
1215 
1216              /// vme output
1217              sstr2 << printOperand(header, inst, i++, opt);
1218 
1219              sstr << sstr2.str();
1220 
1221              break;
1222         }
1223         case ISA_VME_IME:
1224         {
1225              uint8_t streamMode = getPrimitiveOperand<uint8_t>(inst, i++);
1226              uint8_t searchCtrl = getPrimitiveOperand<uint8_t>(inst, i++);
1227 
1228              sstr << ISA_Inst_Table[opcode].str
1229                   << "(" << (unsigned)streamMode
1230                   << "," << (unsigned)searchCtrl
1231                   << ")";
1232 
1233              std::stringstream sstr1;
1234 
1235              /// uni imput
1236              sstr1 << printOperand(header, inst, i++, opt);
1237 
1238              /// ime input
1239              sstr1 << printOperand(header, inst, i++, opt);
1240 
1241              uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1242 
1243              sstr << " T" << (unsigned)surface << " " << sstr1.str();
1244 
1245              /// ref0
1246              sstr << printOperand(header, inst, i++, opt);
1247 
1248              /// ref1
1249              sstr << printOperand(header, inst, i++, opt);
1250 
1251              /// cost center
1252              sstr << printOperand(header, inst, i++, opt);
1253 
1254              /// vme output
1255              sstr << printOperand(header, inst, i++, opt);
1256 
1257              break;
1258         }
1259         case ISA_VME_SIC:
1260         {
1261              /// My typical pattern of printing these things doesn't work here since
1262              /// these VME instructions weirdly put the surface as the third operand.
1263              std::stringstream sstr1;
1264 
1265              /// uni input
1266              sstr1 << printOperand(header, inst, i++, opt);
1267 
1268              /// sic input
1269              sstr1 << printOperand(header, inst, i++, opt);
1270 
1271              uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1272 
1273              sstr << ISA_Inst_Table[opcode].str
1274                   << " T"
1275                   << (unsigned)surface
1276                   << " "
1277                   << sstr1.str();
1278 
1279              /// vme output
1280              sstr << printOperand(header, inst, i++, opt);
1281 
1282              break;
1283         }
1284         case ISA_VME_IDM:
1285         {
1286              /// My typical pattern of printing these things doesn't work here since
1287              /// these VME instructions weirdly put the surface as the third operand.
1288              std::stringstream sstr1;
1289 
1290              /// uni input
1291              sstr1 << printOperand(header, inst, i++, opt);
1292 
1293              /// sic input
1294              sstr1 << printOperand(header, inst, i++, opt);
1295 
1296              uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1297 
1298              sstr << ISA_Inst_Table[opcode].str
1299                   << " T"
1300                   << (unsigned)surface
1301                   << " "
1302                   << sstr1.str();
1303 
1304              /// vme output
1305              sstr << printOperand(header, inst, i++, opt);
1306 
1307              break;
1308         }
1309         case ISA_3D_URB_WRITE:
1310         {
1311 
1312             sstr << ISA_Inst_Table[opcode].str;
1313 
1314             sstr << " " << printExecutionSize(inst->opcode, inst->execsize);
1315 
1316             // num out
1317             sstr << " " << printOperand(header, inst, i++, opt);
1318 
1319             // channel mask
1320             // FIXME: change the order of channel mask and global offset in vISA binary
1321             std::string channelMask = printOperand(header, inst, i++, opt);
1322 
1323             // global offset
1324             sstr << " " << printOperand(header, inst, i++, opt);
1325             sstr << channelMask;
1326 
1327             // urb handle
1328             sstr << printOperand(header, inst, i++, opt);
1329 
1330             // per slot offset
1331             sstr << printOperand(header, inst, i++, opt);
1332 
1333             // vertex data
1334             sstr << printOperand(header, inst, i++, opt);
1335 
1336             break;
1337         }
1338         case ISA_DPAS:
1339         case ISA_DPASW:
1340         {
1341             const VISA_opnd* dpasOpnd = inst->opnd_array[inst->opnd_count-1];
1342             GenPrecision A, W;
1343             uint8_t D, C;
1344             UI32ToDpasInfo(dpasOpnd->_opnd.other_opnd, A, W, D, C);
1345 
1346             sstr << ISA_Inst_Table[opcode].str
1347                  << "." << toString(W) << "." << toString(A) << "."
1348                  << (int)D << "." << (int)C;
1349 
1350             sstr << " " << printExecutionSize(inst->opcode, inst->execsize);
1351 
1352             // dst
1353             sstr << printRawOperand(header, getRawOperand(inst, i++), opt);
1354 
1355             // src0
1356             sstr << printRawOperand(header, getRawOperand(inst, i++), opt);
1357 
1358             // src1
1359             sstr << printRawOperand(header, getRawOperand(inst, i++), opt);
1360 
1361             // src2
1362             sstr << printVectorOperand(header, inst->opnd_array[i++], opt, false);
1363 
1364             break;
1365         }
1366         case ISA_LIFETIME:
1367         {
1368             uint8_t properties = getPrimitiveOperand<uint8_t>(inst, i++);
1369             uint32_t varId = getPrimitiveOperand<uint32_t>(inst, i++);
1370 
1371             sstr << ISA_Inst_Table[opcode].str;
1372 
1373             sstr << ".";
1374 
1375             if ((VISAVarLifetime)(properties & 1) == LIFETIME_START)
1376             {
1377                 sstr << "start ";
1378             }
1379             else
1380             {
1381                 sstr << "end ";
1382             }
1383 
1384             // Since variable id is in non-standard form, we cannot invoke
1385             // printOperand directly on it
1386             unsigned char type = (properties >> 4) & 0x3;
1387             if (type == OPERAND_GENERAL)
1388             {
1389                 // General variable
1390                 sstr << printVariableDeclName(header, varId, opt, NOT_A_STATE_OPND);
1391             }
1392             else if (type == OPERAND_ADDRESS)
1393             {
1394                 // Address variable
1395                 sstr << "A" << varId;
1396             }
1397             else if (type == OPERAND_PREDICATE)
1398             {
1399                 // Predicate variable
1400                 sstr << "P" << varId;
1401             }
1402 
1403             break;
1404         }
1405         default:
1406         {
1407             ASSERT_USER(0, "Unimplemented or Illegal Misc Opcode.");
1408         }
1409     }
1410 
1411     return sstr.str();
1412 }
1413 
1414 // For 3D sampler instructions, subOpcode, pixel null mask and CPS LOD
1415 // compensation enable share the same byte:
1416 //
1417 // Bit 0-4: subOpcode
1418 // Bit   5: pixelNullMask
1419 // Bit   6: cpsEnable
1420 //
getSubOpcodeByte(const CISA_INST * inst,unsigned i)1421 static VISA3DSamplerOp getSubOpcodeByte(
1422     const CISA_INST* inst, unsigned i)
1423 {
1424     uint8_t val = getPrimitiveOperand<uint8_t>(inst, i);
1425     return VISA3DSamplerOp::extractSamplerOp(val);
1426 }
1427 
printInstructionSampler(const print_format_provider_t * header,const CISA_INST * inst,const Options * opt)1428 static std::string printInstructionSampler(
1429     const print_format_provider_t* header,
1430     const CISA_INST* inst,
1431     const Options *opt)
1432 {
1433     std::stringstream sstr;
1434 
1435     ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
1436 
1437     if (opcode == ISA_3D_SAMPLE || opcode == ISA_3D_LOAD || opcode == ISA_3D_GATHER4)
1438     {
1439         sstr << printPredicate(inst->opcode, inst->pred);
1440     }
1441 
1442     unsigned i = 0;
1443 
1444     switch (opcode)
1445     {
1446         case ISA_LOAD:
1447         case ISA_SAMPLE:
1448         {
1449             uint8_t mod     = getPrimitiveOperand<uint8_t>(inst, i++);
1450             uint8_t sampler = 0;
1451 
1452             if (opcode == ISA_SAMPLE)
1453                 sampler = getPrimitiveOperand<uint8_t>(inst, i++);
1454 
1455             uint8_t surface   = getPrimitiveOperand<uint8_t>(inst, i++);
1456             uint8_t channel   = (mod    ) & 0xF;
1457             uint8_t SIMD_mode = (mod >> 4) & 0x3;
1458 
1459             if ((unsigned)SIMD_mode == 0)
1460             {
1461                 SIMD_mode = 8;
1462             }
1463             else if ((unsigned)SIMD_mode == 1)
1464             {
1465                 SIMD_mode = 16;
1466             }
1467 
1468             sstr << ISA_Inst_Table[opcode].str
1469                  << "."
1470                  << channel_mask_str[channel]
1471                  << " ("
1472                  << (unsigned)SIMD_mode
1473                  << ")";
1474 
1475             if (opcode == ISA_SAMPLE)
1476                 sstr << " S" << (unsigned)sampler;
1477 
1478             sstr << " " << printSurfaceName(surface);
1479 
1480             /// u offset
1481             sstr << printOperand(header, inst, i++, opt);
1482 
1483             /// v offset
1484             sstr << printOperand(header, inst, i++, opt);
1485 
1486             /// r offset
1487             sstr << printOperand(header, inst, i++, opt);
1488 
1489             /// dst
1490             sstr << printOperand(header, inst, i++, opt);
1491 
1492             break;
1493         }
1494         case ISA_3D_SAMPLE:
1495         {
1496             // [(P)] SAMPLE_3d[.pixel_null_mask][.cps][.divS].<channels> (exec_size)
1497             //   [(u_aoffimmi, v_aoffimii, r_aoffimmi)] <sampler> <surface>
1498             //   <dst> <u> <v> <r> <ai>
1499             auto subop = getSubOpcodeByte(inst, i++);
1500 
1501             sstr << getSampleOp3DName(subop.opcode) << ".";
1502             // Print the pixel null mask if it is enabled.
1503             if (subop.pixelNullMask)
1504             {
1505                 sstr << "pixel_null_mask.";
1506             }
1507             // Print CPS LOD compensation if it is enabled.
1508             // The last '.' is for the channels.
1509             if (subop.cpsEnable)
1510             {
1511                 sstr << "cps.";
1512             }
1513             if (subop.nonUniformSampler)
1514             {
1515                 sstr << "divS.";
1516             }
1517 
1518             uint8_t channels = getPrimitiveOperand<uint8_t>(inst, i++);
1519             if (channels & 0x1) sstr << "R";
1520             if (channels & 0x2) sstr << "G";
1521             if (channels & 0x4) sstr << "B";
1522             if (channels & 0x8) sstr << "A";
1523 
1524             sstr << " " << printExecutionSize(inst->opcode, inst->execsize) << " ";
1525 
1526             sstr << printOperand(header, inst, i++, opt);
1527 
1528             // sampler
1529             sstr << " S" << printOperand(header, inst, i++, opt);
1530 
1531             // surface
1532             uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1533             sstr << " " << printSurfaceName(surface);
1534 
1535             // dst
1536             sstr << printOperand(header, inst, i++, opt);
1537 
1538             // skip the param count
1539             i++;
1540 
1541             while (i < inst->opnd_count)
1542             {
1543                 sstr << printOperand(header, inst, i++, opt);
1544             }
1545 
1546             break;
1547         }
1548         case ISA_3D_LOAD:
1549         {
1550             auto subop = getSubOpcodeByte(inst, i++);
1551 
1552             sstr << getSampleOp3DName(subop.opcode) << ".";
1553             // Print the pixel null mask if it is enabled.
1554             // The last '.' is for the channels.
1555             if (subop.pixelNullMask)
1556             {
1557                 sstr << "pixel_null_mask.";
1558             }
1559 
1560             uint8_t channels = getPrimitiveOperand<uint8_t>(inst, i++);
1561             if (channels & 0x1) sstr << "R";
1562             if (channels & 0x2) sstr << "G";
1563             if (channels & 0x4) sstr << "B";
1564             if (channels & 0x8) sstr << "A";
1565 
1566             sstr << " " << printExecutionSize(inst->opcode, inst->execsize) << " ";
1567 
1568             sstr << printOperand(header, inst, i++, opt);
1569 
1570             // surface
1571             uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1572             sstr << " " << printSurfaceName(surface);
1573 
1574             // dst
1575             sstr << printOperand(header, inst, i++, opt);
1576 
1577             // skip the param count
1578             i++;
1579 
1580             while (i < inst->opnd_count)
1581             {
1582                 sstr << printOperand(header, inst, i++, opt);
1583             }
1584 
1585             break;
1586         }
1587         case ISA_3D_GATHER4:
1588         {
1589             auto subop = getSubOpcodeByte(inst, i++);
1590 
1591             sstr << getSampleOp3DName(subop.opcode) << ".";
1592             // Print the pixel null mask if it is enabled.
1593             // The last '.' is for the channels.
1594             if (subop.pixelNullMask)
1595             {
1596                 sstr << "pixel_null_mask.";
1597             }
1598 
1599             uint8_t channels = getPrimitiveOperand<uint8_t>(inst, i++);
1600             if (channels == 0x0)
1601             {
1602                 sstr << "R";
1603             }
1604             else if (channels == 0x1)
1605             {
1606                 sstr << "G";
1607             }
1608             else if (channels == 0x2)
1609             {
1610                 sstr << "B";
1611             }
1612             else if (channels == 0x3)
1613             {
1614                 sstr << "A";
1615             }
1616             else
1617             {
1618                 sstr << "illegal";
1619             }
1620 
1621             sstr << " " << printExecutionSize(inst->opcode, inst->execsize);
1622 
1623             sstr << printOperand(header, inst, i++, opt);
1624 
1625             // sampler
1626             sstr << " S" << printOperand(header, inst, i++, opt);
1627 
1628             // surface
1629             uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1630             sstr << " " << printSurfaceName(surface);
1631 
1632             // dst
1633             sstr << printOperand(header, inst, i++, opt);
1634 
1635             // skip the param count
1636             i++;
1637 
1638             while (i < inst->opnd_count)
1639             {
1640                 sstr << printOperand(header, inst, i++, opt);
1641             }
1642 
1643             break;
1644         }
1645         case ISA_3D_INFO:
1646         {
1647             VISASampler3DSubOpCode subop = (VISASampler3DSubOpCode)getPrimitiveOperand<uint8_t>(inst, i++);
1648             sstr << getSampleOp3DName(subop);
1649             if (subop == VISA_3D_RESINFO || subop == VISA_3D_SAMPLEINFO)
1650             {
1651                 // channelMask
1652                 uint8_t channels = getPrimitiveOperand<uint8_t>(inst, i++);
1653                 ChannelMask chMask = ChannelMask::createFromBinary(ISA_3D_INFO, channels);
1654                 sstr << "." << chMask.getString();
1655             }
1656 
1657             sstr << " " << printExecutionSize(inst->opcode, inst->execsize) << " ";
1658 
1659             // surface
1660             uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1661             sstr << " " << printSurfaceName(surface);
1662 
1663             if (subop == VISA_3D_RESINFO)
1664             {
1665                 // lod
1666                 sstr << printOperand(header, inst, i++, opt);
1667             }
1668 
1669             // dst
1670             sstr << printOperand(header, inst, i++, opt);
1671 
1672             break;
1673         }
1674         case ISA_SAMPLE_UNORM:
1675         {
1676             uint8_t channel = getPrimitiveOperand<uint8_t>(inst, i++);
1677             uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
1678             uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1679             sstr << ISA_Inst_Table[opcode].str
1680                 << "."
1681                 << channel_mask_str[(channel & 0xf)]
1682                 << "."
1683                 << sampler_channel_output_str[ChannelMask::getChannelOutputFormat(channel)]
1684                 << " S"
1685                 << (unsigned)sampler
1686                 << " " << printSurfaceName(surface);
1687 
1688             /// u offset
1689             sstr << printOperand(header, inst, i++, opt);
1690 
1691             /// v offset
1692             sstr << printOperand(header, inst, i++, opt);
1693 
1694             /// deltaU
1695             sstr << printOperand(header, inst, i++, opt);
1696 
1697             /// deltaV
1698             sstr << printOperand(header, inst, i++, opt);
1699 
1700             /// dst
1701             sstr << printOperand(header, inst, i++, opt);
1702 
1703             break;
1704         }
1705         case ISA_AVS:
1706         {
1707             uint8_t channel = getPrimitiveOperand<uint8_t>(inst, i++);
1708             uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
1709             uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1710 
1711             sstr << ISA_Inst_Table[opcode].str
1712                 << "."
1713                 << channel_mask_str[channel]
1714                 << " " << printSurfaceName(surface)
1715                 << " S"
1716                 << (unsigned)sampler;
1717 
1718             /// u offset
1719             sstr << printOperand(header, inst, i++, opt);
1720 
1721             /// v offset
1722             sstr << printOperand(header, inst, i++, opt);
1723 
1724             /// delta u
1725             sstr << printOperand(header, inst, i++, opt);
1726 
1727             /// delta v
1728             sstr << printOperand(header, inst, i++, opt);
1729 
1730             /// u2d
1731             sstr << printOperand(header, inst, i++, opt);
1732 
1733             /// groupID
1734             sstr << printOperand(header, inst, i++, opt);
1735 
1736             /// verticalBlockNumber
1737             sstr << printOperand(header, inst, i++, opt);
1738 
1739             uint8_t cntrl = ((getPrimitiveOperand<uint8_t>(inst, i++)) & 0xF);
1740 
1741             sstr << " "
1742                  << avs_control_str[cntrl];
1743 
1744             /// v2d
1745             sstr << printOperand(header, inst, i++, opt);
1746 
1747             uint8_t execMode  =       (getPrimitiveOperand<uint8_t>(inst, i++) & 0xF);
1748 
1749             sstr << " "
1750                  << avs_exec_mode[execMode];
1751 
1752             // eifbypass
1753             sstr << printOperand(header, inst, i++, opt);
1754 
1755             /// dst
1756             sstr << printOperand(header, inst, i++, opt);
1757 
1758             break;
1759         }
1760         case ISA_VA:
1761         {
1762             ISA_VA_Sub_Opcode subOpcode = (ISA_VA_Sub_Opcode)getPrimitiveOperand<uint8_t>(inst, i++);
1763             switch (subOpcode)
1764             {
1765                 case MINMAX_FOPCODE:
1766                 {
1767                      uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1768 
1769                      sstr << ISA_Inst_Table[opcode].str
1770                           << "."
1771                           << va_sub_names[subOpcode]
1772                           << " " << printSurfaceName(surface);
1773 
1774                      /// u offset
1775                      sstr << printOperand(header, inst, i++, opt);
1776 
1777                      /// v offset
1778                      sstr << printOperand(header, inst, i++, opt);
1779 
1780                      /// mmf mode
1781                      if (getVectorOperand(inst, i).getOperandClass() == OPERAND_IMMEDIATE)
1782                      {
1783                          unsigned val = getVectorOperand(inst, i++).opnd_val.const_opnd._val.ival;
1784                          sstr << " " << mmf_enable_mode[val];
1785                      }
1786                      else
1787                      {
1788                         sstr << printOperand(header, inst, i++, opt);
1789                      }
1790 
1791                      /// dst
1792                      sstr << printOperand(header, inst, i++, opt);
1793 
1794                      break;
1795                 }
1796                 case MINMAXFILTER_FOPCODE:
1797                 {
1798                      uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
1799                      uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1800 
1801                      sstr << ISA_Inst_Table[opcode].str
1802                           << "."
1803                           << va_sub_names[subOpcode]
1804                           << " " << printSurfaceName(surface)
1805                           << " S" << (unsigned)sampler;
1806 
1807                      /// u offset
1808                      sstr << printOperand(header, inst, i++, opt);
1809 
1810                      /// v offset
1811                      sstr << printOperand(header, inst, i++, opt);
1812 
1813                      uint8_t cntrl    = ((getPrimitiveOperand<uint8_t>(inst, i++)) & 0xF);
1814                      uint8_t execMode = ((getPrimitiveOperand<uint8_t>(inst, i++)) & 0xF);
1815 
1816                      sstr << " "
1817                           << avs_control_str [ cntrl     ]
1818                           << " "
1819                           << mmf_exec_mode   [ execMode ];
1820 
1821                      /// mmf mode
1822                      sstr << printOperand(header, inst, i++, opt);
1823 
1824                      /// dst
1825                      sstr << printOperand(header, inst, i++, opt);
1826 
1827                      break;
1828                 }
1829                 case BoolCentroid_FOPCODE:
1830                 case Centroid_FOPCODE:
1831                 {
1832                     uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1833 
1834                     sstr << ISA_Inst_Table[opcode].str
1835                         << "."
1836                         << va_sub_names[subOpcode]
1837                         << " " << printSurfaceName(surface);
1838 
1839                      /// u offset
1840                      sstr << printOperand(header, inst, i++, opt);
1841 
1842                      /// v offset
1843                      sstr << printOperand(header, inst, i++, opt);
1844 
1845                      /// v size
1846                      sstr << printOperand(header, inst, i++, opt);
1847 
1848                      /// h size
1849                      if (subOpcode == BoolCentroid_FOPCODE)
1850                         sstr << printOperand(header, inst, i++, opt);
1851 
1852                      /// dst
1853                      sstr << printOperand(header, inst, i++, opt);
1854 
1855                      break;
1856                 }
1857                 case Convolve_FOPCODE:
1858                 case Dilate_FOPCODE:
1859                 case ERODE_FOPCODE:
1860                 {
1861                      uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
1862                      uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1863 
1864                      sstr << ISA_Inst_Table[opcode].str
1865                           << "."
1866                           << va_sub_names[subOpcode]
1867                           << " " << printSurfaceName(surface)
1868                           << " S" << (unsigned)sampler;
1869 
1870                      /// u offset
1871                      sstr << printOperand(header, inst, i++, opt);
1872 
1873                      /// v offset
1874                      sstr << printOperand(header, inst, i++, opt);
1875 
1876                      uint8_t execMode   =  getPrimitiveOperand<uint8_t>(inst, i ) & 0x3;
1877                      uint8_t regionSize = (getPrimitiveOperand<uint8_t>(inst, i++) & 0xC) >> 0x2;
1878 
1879                      sstr << " "
1880                           << (Convolve_FOPCODE == subOpcode ?
1881                               conv_exec_mode [execMode]     :
1882                               ed_exec_mode   [execMode]   );
1883 
1884                      if (Convolve_FOPCODE == subOpcode)
1885                          sstr << " " << (regionSize & 0x1 ? "31x31" : "15x15");
1886 
1887                      /// dst
1888                      sstr << printOperand(header, inst, i++, opt);
1889 
1890                      break;
1891                 }
1892                 default:
1893                      ASSERT_USER(false, "Invalid VA sub-opcode");
1894             }
1895 
1896             break;
1897         }
1898         case ISA_VA_SKL_PLUS:
1899         {
1900             ISA_VA_Sub_Opcode subOpcode = (ISA_VA_Sub_Opcode)getPrimitiveOperand<uint8_t>(inst, i++);
1901             switch (subOpcode)
1902             {
1903                 case VA_OP_CODE_LBP_CORRELATION:
1904                 {
1905                      uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1906 
1907                      sstr << ISA_Inst_Table[opcode].str
1908                          << "."
1909                          << va_sub_names[subOpcode]
1910                          << " " << printSurfaceName(surface);
1911 
1912                      /// u offset
1913                      sstr << printOperand(header, inst, i++, opt);
1914 
1915                      /// v offset
1916                      sstr << printOperand(header, inst, i++, opt);
1917 
1918                      /// disparity
1919                      sstr << printOperand(header, inst, i++, opt);
1920 
1921                      /// dst
1922                      sstr << printOperand(header, inst, i++, opt);
1923 
1924                      break;
1925                 }
1926                 case VA_OP_CODE_1PIXEL_CONVOLVE:
1927                 case VA_OP_CODE_1D_CONVOLVE_VERTICAL:
1928                 case VA_OP_CODE_1D_CONVOLVE_HORIZONTAL:
1929                 {
1930                      uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
1931                      uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1932 
1933                      sstr << ISA_Inst_Table[opcode].str
1934                          << "."
1935                          << va_sub_names[subOpcode]
1936                          << " " << printSurfaceName(surface)
1937                          << " S" << (unsigned)sampler;
1938 
1939                      /// u offset
1940                      sstr << printOperand(header, inst, i++, opt);
1941 
1942                      /// v offset
1943                      sstr << printOperand(header, inst, i++, opt);
1944 
1945                      uint8_t mode = ((getPrimitiveOperand<uint8_t>(inst, i++)) & 0xF);
1946 
1947                      switch (mode & 0x3)
1948                      {
1949                          case 0: sstr << " 4x16"; break;
1950                          case 2: sstr << " 1x16"; break;
1951                          case 3: sstr << " 1x1";  break;
1952                      }
1953 
1954                      /// offsets
1955                      if (subOpcode == VA_OP_CODE_1PIXEL_CONVOLVE)
1956                          sstr << printOperand(header, inst, i++, opt);
1957 
1958                      /// dst
1959                      sstr << printOperand(header, inst, i++, opt);
1960 
1961                      break;
1962                 }
1963                 case VA_OP_CODE_LBP_CREATION:
1964                 {
1965                      uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1966 
1967                      sstr << ISA_Inst_Table[opcode].str
1968                          << "."
1969                          << va_sub_names[subOpcode]
1970                          << " " << printSurfaceName(surface);
1971 
1972                      /// u offset
1973                      sstr << printOperand(header, inst, i++, opt);
1974 
1975                      /// v offset
1976                      sstr << printOperand(header, inst, i++, opt);
1977 
1978                      uint8_t mode = ((getPrimitiveOperand<uint8_t>(inst, i++)) & 0xF);
1979 
1980                      sstr << " " << lbp_creation_mode[(int)mode];
1981 
1982                      /// dst
1983                      sstr << printOperand(header, inst, i++, opt);
1984 
1985                      break;
1986                 }
1987                 case VA_OP_CODE_FLOOD_FILL:
1988                 {
1989                      uint8_t is8Connect = getPrimitiveOperand<uint8_t>(inst, i++);
1990 
1991                      sstr << ISA_Inst_Table[opcode].str
1992                           << "."
1993                           << va_sub_names[subOpcode]
1994                           << " " << (is8Connect & 0x1 ? "8_connect" : "4_connect");
1995 
1996                      /// pixel mask h direction
1997                      sstr << printOperand(header, inst, i++, opt);
1998 
1999                      /// pixel mask v left direction
2000                      sstr << printOperand(header, inst, i++, opt);
2001 
2002                      /// pixel mask v right direction
2003                      sstr << printOperand(header, inst, i++, opt);
2004 
2005                      /// loop count
2006                      sstr << printOperand(header, inst, i++, opt);
2007 
2008                      /// dst
2009                      sstr << printOperand(header, inst, i++, opt);
2010 
2011                      break;
2012                 }
2013                 case VA_OP_CODE_CORRELATION_SEARCH:
2014                 {
2015                      uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2016 
2017                      sstr << ISA_Inst_Table[opcode].str
2018                          << "."
2019                          << va_sub_names[subOpcode]
2020                          << " " << printSurfaceName(surface);
2021 
2022                      /// u offset
2023                      sstr << printOperand(header, inst, i++, opt);
2024 
2025                      /// v offset
2026                      sstr << printOperand(header, inst, i++, opt);
2027 
2028                      /// vertical origin
2029                      sstr << printOperand(header, inst, i++, opt);
2030 
2031                      /// horizontal origin
2032                      sstr << printOperand(header, inst, i++, opt);
2033 
2034                      /// x direction size
2035                      sstr << printOperand(header, inst, i++, opt);
2036 
2037                      /// y direction size
2038                      sstr << printOperand(header, inst, i++, opt);
2039 
2040                      /// x direction search size
2041                      sstr << printOperand(header, inst, i++, opt);
2042 
2043                      /// y direction search size
2044                      sstr << printOperand(header, inst, i++, opt);
2045 
2046                      /// dst
2047                      sstr << printOperand(header, inst, i++, opt);
2048 
2049                      break;
2050                 }
2051                 case ISA_HDC_CONV:
2052                 case ISA_HDC_ERODE:
2053                 case ISA_HDC_DILATE:
2054                 case ISA_HDC_LBPCORRELATION:
2055                 case ISA_HDC_LBPCREATION:
2056                 case ISA_HDC_MMF:
2057                 case ISA_HDC_1PIXELCONV:
2058                 case ISA_HDC_1DCONV_H:
2059                 case ISA_HDC_1DCONV_V:
2060                 {
2061                         sstr << ISA_Inst_Table[opcode].str
2062                              << "."
2063                              << va_sub_names[subOpcode];
2064 
2065                         if (subOpcode != ISA_HDC_LBPCORRELATION &&
2066                             subOpcode != ISA_HDC_LBPCREATION)
2067                         {
2068                             uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
2069                             uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2070 
2071                             sstr << " " << printSurfaceName(surface)
2072                                  << " S" << (unsigned)sampler;
2073                         }
2074                         else
2075                         {
2076                             /// surface
2077                             uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2078                             sstr << " " << printSurfaceName(surface);
2079                         }
2080 
2081                         /// u offset
2082                         sstr << printOperand(header, inst, i++, opt);
2083 
2084                         /// v offset
2085                         sstr << printOperand(header, inst, i++, opt);
2086 
2087 
2088                         if (subOpcode == ISA_HDC_CONV ||
2089                             subOpcode == ISA_HDC_MMF ||
2090                             subOpcode == ISA_HDC_1PIXELCONV ||
2091                             subOpcode == ISA_HDC_1DCONV_H ||
2092                             subOpcode == ISA_HDC_1DCONV_V)
2093                         {
2094                             //pixel size
2095                             uint8_t pixel_size = getPrimitiveOperand<uint8_t>(inst, i++);
2096                             int isBigKernel = 0;
2097 
2098                             if (subOpcode == ISA_HDC_CONV)
2099                             {
2100                                 isBigKernel = (pixel_size & (1 << 4));
2101                                 pixel_size = pixel_size & 0xF;
2102                             }
2103                             sstr << " " << pixel_size_str[pixel_size];
2104 
2105                             if (subOpcode == ISA_HDC_CONV  && isBigKernel)
2106                             {
2107                                 sstr << " 31x31";
2108                             }
2109                             else if (subOpcode == ISA_HDC_CONV  && !isBigKernel)
2110                             {
2111                                 sstr << " 15x15";
2112                             }
2113                         }
2114 
2115                         if (subOpcode == ISA_HDC_MMF)
2116                         {
2117                             //mode
2118                             uint8_t mode = getPrimitiveOperand<uint8_t>(inst, i++);
2119                             sstr << " " << mmf_enable_mode[(int)mode];
2120                         }
2121 
2122                         if (subOpcode == ISA_HDC_LBPCREATION)
2123                         {
2124                             //mode
2125                             uint8_t mode = getPrimitiveOperand<uint8_t>(inst, i++);
2126                             sstr << " " << lbp_creation_mode[(int)mode];
2127                         }
2128 
2129                         if (subOpcode == ISA_HDC_LBPCORRELATION)
2130                         {
2131                             /// disparity
2132                             sstr << printOperand(header, inst, i++, opt);
2133                         }
2134 
2135                         if (subOpcode == ISA_HDC_1PIXELCONV)
2136                         {
2137                             /// offsets
2138                             sstr << printOperand(header, inst, i++, opt);
2139                         }
2140 
2141                         /// dst surface
2142                         uint8_t dst_surface = getPrimitiveOperand<uint8_t>(inst, i++);
2143 
2144                         sstr << " " << printSurfaceName(dst_surface);
2145 
2146                         /// x offset
2147                         sstr << printOperand(header, inst, i++, opt);
2148 
2149                         /// y offset
2150                         sstr << printOperand(header, inst, i++, opt);
2151                         break;
2152                 }
2153                 default:
2154                      ASSERT_USER(false, "Invalid VA sub-opcode");
2155             }
2156 
2157             break;
2158         }
2159         default: ASSERT_USER(false, "illegal opcode for sampler instruction");
2160     }
2161 
2162     return sstr.str();
2163 }
2164 
printInstructionDataport(const print_format_provider_t * header,const CISA_INST * inst,const Options * opt)2165 static std::string printInstructionDataport(
2166     const print_format_provider_t* header,
2167     const CISA_INST* inst,
2168     const Options *opt)
2169 {
2170     ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
2171     unsigned i = 0;
2172 
2173     uint8_t surface  = 0;
2174     uint8_t modifier = 0;
2175     std::stringstream sstr;
2176 
2177     switch (opcode) {
2178     default:
2179         break;
2180     case ISA_3D_RT_WRITE:
2181     case ISA_GATHER4_SCALED:
2182     case ISA_SCATTER4_SCALED:
2183     case ISA_GATHER_SCALED:
2184     case ISA_SCATTER_SCALED:
2185     case ISA_DWORD_ATOMIC:
2186     case ISA_3D_TYPED_ATOMIC:
2187     case ISA_QW_GATHER:
2188     case ISA_QW_SCATTER:
2189         sstr << printPredicate(inst->opcode, inst->pred);
2190         break;
2191     }
2192 
2193     sstr << ISA_Inst_Table[opcode].str;
2194 
2195     switch (opcode)
2196     {
2197         case ISA_MEDIA_ST:
2198         case ISA_MEDIA_LD:
2199         {
2200             uint8_t plane        = 0;
2201             uint8_t block_width  = 0;
2202             uint8_t block_height = 0;
2203 
2204             if (ISA_MEDIA_LD == opcode || ISA_MEDIA_ST == opcode)
2205             {
2206                 modifier = getPrimitiveOperand<uint8_t>(inst, i++); //inst->modifier;
2207             }
2208 
2209             surface = getPrimitiveOperand<uint8_t>(inst, i++);
2210 
2211             if (ISA_MEDIA_LD == opcode || ISA_MEDIA_ST == opcode)
2212             {
2213                 plane = getPrimitiveOperand<uint8_t>(inst, i++);
2214             }
2215 
2216             if (opcode == ISA_MEDIA_LD) sstr << "." << media_ld_mod_str[modifier];
2217             if (opcode == ISA_MEDIA_ST) sstr << "." << media_st_mod_str[modifier];
2218 
2219             sstr << " (";
2220             block_width = getPrimitiveOperand<uint8_t>(inst, i++);
2221             sstr << (unsigned)block_width;
2222             sstr << ",";
2223             block_height = getPrimitiveOperand<uint8_t>(inst, i++);
2224             sstr << (unsigned)block_height;
2225             sstr << ")";
2226 
2227             sstr << " " << printSurfaceName(surface);
2228             sstr << " " << (unsigned)plane;
2229 
2230             /// x offset
2231             sstr << printOperand(header, inst, i++, opt);
2232 
2233             /// y offset
2234             sstr << printOperand(header, inst, i++, opt);
2235 
2236             /// message operand (src or dst)
2237             sstr << printOperand(header, inst, i++, opt);
2238 
2239             break;
2240         }
2241         case ISA_OWORD_ST:
2242         case ISA_OWORD_LD:
2243         case ISA_OWORD_LD_UNALIGNED:
2244         {
2245             uint8_t size = getPrimitiveOperand<uint8_t>(inst, i++);
2246             size = size & 0x7;
2247             unsigned num_oword = Get_VISA_Oword_Num((VISA_Oword_Num)size);
2248 
2249             if (ISA_OWORD_ST != opcode)
2250             {
2251                 modifier = getPrimitiveOperand<uint8_t>(inst, i++);
2252                 if (modifier & 0x1) sstr << ".mod";
2253             }
2254 
2255             sstr << " (" << num_oword << ")";
2256 
2257             surface = getPrimitiveOperand<uint8_t>(inst, i++);
2258             sstr << " " << printSurfaceName(surface);
2259 
2260             /// offset
2261             sstr << printOperand(header, inst, i++, opt);
2262 
2263             /// message operand (src or dst)
2264             sstr << printOperand(header, inst, i++, opt);
2265 
2266             break;
2267         }
2268         case ISA_GATHER:
2269         case ISA_SCATTER:
2270         {
2271             uint8_t elt_size = 0;
2272             uint8_t num_elts = 0;
2273 
2274             elt_size = getPrimitiveOperand<uint8_t>(inst, i++);
2275             elt_size = elt_size & 0x3;
2276             switch ((GATHER_SCATTER_ELEMENT_SIZE)elt_size)
2277             {
2278                 case GATHER_SCATTER_BYTE:
2279                     elt_size = 1;
2280                     break;
2281                 case GATHER_SCATTER_WORD:
2282                     elt_size = 2;
2283                     break;
2284                 case GATHER_SCATTER_DWORD:
2285                     elt_size = 4;
2286                     break;
2287                 default:
2288                     ASSERT_USER(0, "Incorrect element size for Gather/Scatter CISA inst.");
2289                     break;
2290             }
2291             if (ISA_GATHER == opcode)
2292             {
2293                 modifier = getPrimitiveOperand<uint8_t>(inst, i++);
2294             }
2295 
2296             num_elts = getPrimitiveOperand<uint8_t>(inst, i++);
2297 
2298             // modifier
2299             if (ISA_GATHER == opcode && modifier & 0x1)
2300             {
2301                 sstr << ".mod";
2302             }
2303 
2304             // num_elts
2305             sstr << "." << (unsigned)elt_size;
2306 
2307             // execution size
2308             sstr << " " << printExecutionSizeForScatterGather(num_elts);
2309 
2310             // modifier
2311             if (ISA_GATHER == opcode && modifier & 0x1)
2312             {
2313                 sstr << ".mod";
2314             }
2315 
2316             //surface
2317             surface = getPrimitiveOperand<uint8_t>(inst, i++);
2318             sstr << " " << printSurfaceName(surface);
2319 
2320             /// global offset
2321             sstr << printOperand(header, inst, i++, opt);
2322 
2323             /// element offset
2324             sstr << printOperand(header, inst, i++, opt);
2325 
2326             /// message operand (src or dst)
2327             sstr << printOperand(header, inst, i++, opt);
2328 
2329             break;
2330         }
2331         case ISA_GATHER4_TYPED:
2332         case ISA_SCATTER4_TYPED:
2333         {
2334             ChannelMask chMask = ChannelMask::createFromBinary(opcode,
2335                     getPrimitiveOperand<uint8_t>(inst, i++));
2336             sstr << "." << chMask.getString();
2337 
2338             sstr << " " << printExecutionSize(inst->opcode, inst->execsize);
2339 
2340             surface = getPrimitiveOperand<uint8_t>(inst, i++);
2341             sstr << " " << printSurfaceName(surface);
2342 
2343             /// u offset
2344             sstr << printOperand(header, inst, i++, opt);
2345 
2346             /// v offset
2347             sstr << printOperand(header, inst, i++, opt);
2348 
2349             /// r offset
2350             sstr << printOperand(header, inst, i++, opt);
2351 
2352             /// lod
2353             sstr << printOperand(header, inst, i++, opt);
2354 
2355             /// message operand (src or dst)
2356             sstr << printOperand(header, inst, i++, opt);
2357 
2358             break;
2359         }
2360         case ISA_GATHER4_SCALED:
2361         case ISA_SCATTER4_SCALED:
2362         {
2363             ChannelMask chMask = ChannelMask::createFromBinary(opcode,
2364                     getPrimitiveOperand<uint8_t>(inst, i++));
2365             sstr << "." << chMask.getString();
2366 
2367             // ignore scale which must be 0
2368             (void) getPrimitiveOperand<uint8_t>(inst, i++);
2369 
2370             sstr << " " << printExecutionSize(inst->opcode, inst->execsize);
2371 
2372             /// surface
2373             surface = getPrimitiveOperand<uint8_t>(inst, i++);
2374             sstr << " " << printSurfaceName(surface);
2375 
2376             /// global offset
2377             sstr << printOperand(header, inst, i++, opt);
2378 
2379             /// offsets
2380             sstr << printOperand(header, inst, i++, opt);
2381 
2382             /// src/dst
2383             sstr << printOperand(header, inst, i++, opt);
2384             break;
2385         }
2386         case ISA_GATHER_SCALED:
2387         case ISA_SCATTER_SCALED:
2388         {
2389             VISA_SVM_Block_Num numBlocks;
2390 
2391             // block size : ignored
2392             (void)getPrimitiveOperand<uint8_t>(inst, i++);
2393 
2394             numBlocks = static_cast<VISA_SVM_Block_Num>(getPrimitiveOperand<uint8_t>(inst, i++));
2395 
2396             sstr << "." << Get_Common_ISA_SVM_Block_Num(numBlocks);
2397 
2398             sstr << " " << printExecutionSize(inst->opcode, inst->execsize);
2399 
2400             // scale (MBZ) : ignored
2401             (void)getPrimitiveOperand<uint8_t>(inst, i++);
2402 
2403             /// surface
2404             surface = getPrimitiveOperand<uint8_t>(inst, i++);
2405             sstr << " " << printSurfaceName(surface);
2406 
2407             /// global offset
2408             sstr << printOperand(header, inst, i++, opt);
2409 
2410             /// offsets
2411             sstr << printOperand(header, inst, i++, opt);
2412 
2413             /// src/dst
2414             sstr << printOperand(header, inst, i++, opt);
2415             break;
2416         }
2417         case ISA_3D_RT_WRITE:
2418         {
2419             // mode
2420             uint16_t mode = getPrimitiveOperand<uint16_t>(inst, i++);
2421             uint8_t surface;
2422 
2423             if ((mode) != 0)
2424             {
2425                 sstr << ".";
2426                 if (mode & (0x1 << 2)) sstr << "<RTI>";
2427                 if (mode & (0x1 << 3)) sstr << "<A>";
2428                 if (mode & (0x1 << 4)) sstr << "<O>";
2429                 if (mode & (0x1 << 5)) sstr << "<Z>";
2430                 if (mode & (0x1 << 6)) sstr << "<ST>";
2431                 if (mode & (0x1 << 7)) sstr << "<LRTW>";
2432                 if (mode & (0x1 << 8)) sstr << "<CPS>";
2433                 if (mode & (0x1 << 9)) sstr << "<PS>";
2434                 if (mode & (0x1 << 10)) sstr << "<CM>";
2435                 if (mode & (0x1 << 11)) sstr << "<SI>";
2436                 if (mode & (0x1 << 12)) sstr << "<NULLRT>";
2437             }
2438 
2439             sstr << " " << printExecutionSize(inst->opcode, inst->execsize);
2440 
2441             // surface
2442             surface = getPrimitiveOperand<uint8_t>(inst, i++);
2443             sstr << " " << printSurfaceName(surface);
2444 
2445             while (i < inst->opnd_count)
2446             {
2447                 sstr << printOperand(header, inst, i++, opt);
2448             }
2449 
2450             break;
2451         }
2452         case ISA_DWORD_ATOMIC: {
2453             printAtomicSubOpc(sstr, getPrimitiveOperand<uint8_t>(inst, i++));
2454             sstr << " " << printExecutionSize(inst->opcode, inst->execsize);
2455 
2456             /// surface
2457             surface = getPrimitiveOperand<uint8_t>(inst, i++);
2458             sstr << " " << printSurfaceName(surface);
2459 
2460             /// offsets
2461             sstr << printOperand(header, inst, i++, opt);
2462 
2463             /// src0
2464             sstr << printOperand(header, inst, i++, opt);
2465 
2466             /// src1
2467             sstr << printOperand(header, inst, i++, opt);
2468 
2469             /// dst
2470             sstr << printOperand(header, inst, i++, opt);
2471             break;
2472         }
2473         case ISA_3D_TYPED_ATOMIC:
2474         {
2475             printAtomicSubOpc(sstr, getPrimitiveOperand<uint8_t>(inst, i++));
2476             sstr << " " << printExecutionSize(inst->opcode, inst->execsize);
2477 
2478             /// surface
2479             surface = getPrimitiveOperand<uint8_t>(inst, i++);
2480             sstr << " " << printSurfaceName(surface);
2481 
2482             /// u
2483             sstr << printOperand(header, inst, i++, opt);
2484 
2485             /// v
2486             sstr << printOperand(header, inst, i++, opt);
2487 
2488             /// r
2489             sstr << printOperand(header, inst, i++, opt);
2490 
2491             /// lod
2492             sstr << printOperand(header, inst, i++, opt);
2493 
2494             /// src0
2495             sstr << printOperand(header, inst, i++, opt);
2496 
2497             /// src1
2498             sstr << printOperand(header, inst, i++, opt);
2499 
2500             /// dst
2501             sstr << printOperand(header, inst, i++, opt);
2502             break;
2503         }
2504         case ISA_QW_GATHER:
2505         case ISA_QW_SCATTER:
2506         {
2507             //QW_GATHER/SCATTER.<num_blocks> (<exec_size>) <surface> <offset> <dst>
2508             VISA_SVM_Block_Num numBlocks;
2509 
2510             numBlocks = static_cast<VISA_SVM_Block_Num>(getPrimitiveOperand<uint8_t>(inst, i++));
2511             sstr << "." << Get_Common_ISA_SVM_Block_Num(numBlocks);
2512 
2513             sstr << " " << printExecutionSize(inst->opcode, inst->execsize);
2514 
2515             /// surface
2516             surface = getPrimitiveOperand<uint8_t>(inst, i++);
2517             sstr << " " << printSurfaceName(surface);
2518 
2519             /// offsets
2520             sstr << printOperand(header, inst, i++, opt);
2521 
2522             /// src/dst
2523             sstr << printOperand(header, inst, i++, opt);
2524             break;
2525         }
2526 
2527         default:
2528         {
2529             ASSERT_USER(false, "Unimplemented or Illegal DataPort Opcode.");
2530         }
2531     }
2532 
2533     return sstr.str();
2534 }
2535 
2536 class LscInstFormatter {
2537     ISA_Opcode                         opcode;
2538     LSC_OP                             subOp;
2539     LscOpInfo                          opInfo;
2540 
2541     std::stringstream                  ss;
2542     const print_format_provider_t     *header;
2543     const CISA_INST                   *inst;
2544     const Options                     *opts;
2545 
2546     int                                currOpIx = 0;
2547     bool                               error = false;
2548 
2549 public:
LscInstFormatter(ISA_Opcode _opcode,const print_format_provider_t * _header,const CISA_INST * _inst,const Options * _opts)2550     LscInstFormatter(
2551         ISA_Opcode                     _opcode,
2552         const print_format_provider_t *_header,
2553         const CISA_INST               *_inst,
2554         const Options                 *_opts)
2555         : opcode(_opcode)
2556         , header(_header)
2557         , inst(_inst)
2558         , opts(_opts)
2559     {
2560         if (_opcode == ISA_LSC_FENCE) {
2561             subOp = LSC_FENCE;
2562         } else {
2563             subOp = getNextEnumU8<LSC_OP>();
2564         }
2565         opInfo = LscOpInfoGet(subOp);
2566     }
2567 
2568 private:
2569     template <typename T>
getNextEnumU8()2570     T getNextEnumU8() {
2571         return (T)getPrimitive<uint8_t>(currOpIx++);
2572     }
2573 
2574     template <typename T>
getNext()2575     T getNext() {
2576         return getPrimitive<T>(currOpIx++);
2577     }
2578     template <typename T>
getPrimitive(int absOpIx)2579     T getPrimitive(int absOpIx) {
2580         return getPrimitiveOperand<T>(inst, absOpIx);
2581     }
2582 
2583     // LSC_TYPED and non-block2d LSC_UNTYPED
2584     // "next" because it advances the operand pointer
getNextDataShape()2585     LSC_DATA_SHAPE getNextDataShape() {
2586         auto dataSize = getNextEnumU8<LSC_DATA_SIZE>();
2587         auto dataOrder = getNextEnumU8<LSC_DATA_ORDER>();
2588         auto dataElems = getNextEnumU8<LSC_DATA_ELEMS>();
2589         // chmask only valid on LSC_LOAD_QUAD/LSC_STORE_QUAD
2590         // but retained in the binary format
2591         int chMask = (int)getNextEnumU8<int>();
2592         LSC_DATA_SHAPE dataShape { };
2593         dataShape.size = dataSize;
2594         dataShape.order = dataOrder;
2595         if (opInfo.hasChMask()) {
2596             dataShape.chmask = chMask;
2597         } else {
2598             dataShape.elems = dataElems;
2599         }
2600         return dataShape;
2601     }
2602 
formatBadEnum(int bits)2603     void formatBadEnum(int bits) {
2604         error = true;
2605         ss << "<<" << std::hex << std::uppercase << bits << "?>>" << std::dec;
2606     }
2607 
formatSfid(LSC_SFID sfid)2608     void formatSfid(LSC_SFID sfid) {
2609         ss << ".";
2610         switch (sfid) {
2611         case LSC_UGM:   ss << "ugm";  break;
2612         case LSC_UGML:  ss << "ugml"; break;
2613         case LSC_SLM:   ss << "slm";  break;
2614         case LSC_TGM:   ss << "tgm";  break;
2615         default: formatBadEnum(sfid); break;
2616         }
2617     }
2618 
2619     // custom so we can conditionally print register operand suffixes
formatVectorOperand(int opIx)2620     void formatVectorOperand(int opIx) {
2621         if (getOperandType(inst, opIx) != CISA_OPND_VECTOR) {
2622             error = true;
2623             ss << "<<BAD_OPERAND_NOT_VECTOR>>";
2624         } else {
2625             const auto &vo = getVectorOperand(inst, opIx);
2626             switch (vo.tag & 0x7) {
2627             case OPERAND_IMMEDIATE:
2628                 ss << "0x" << std::uppercase << std::hex <<
2629                     vo.opnd_val.const_opnd._val.ival << std::dec;
2630                 break;
2631             case OPERAND_GENERAL:
2632                 ss << printVariableDeclName(
2633                     header,
2634                     vo.getOperandIndex(),
2635                     opts,
2636                     NOT_A_STATE_OPND);
2637                 if (vo.opnd_val.gen_opnd.row_offset != 0 ||
2638                   vo.opnd_val.gen_opnd.col_offset != 0)
2639                 {
2640                     ss  << std::dec << "("
2641                          << (unsigned)vo.opnd_val.gen_opnd.row_offset << ","
2642                          << (unsigned)vo.opnd_val.gen_opnd.col_offset << ")";
2643                 }
2644                 break;
2645             default:
2646                 error = true;
2647                 ss << "<<BAD_OPERAND_VECTOR_KIND>>";
2648                 break;
2649           }
2650         }
2651     }
2652 
formatRawOperand(int absIx)2653     void formatRawOperand(int absIx) {
2654         if (getOperandType(inst, absIx) != CISA_OPND_RAW) {
2655             error = true;
2656             ss << "<<BAD_OPERAND_NOT_RAW>>";
2657         } else {
2658             const raw_opnd &ro = getRawOperand(inst, absIx);
2659             ss << printVariableDeclName(header, ro.index, opts, NOT_A_STATE_OPND);
2660             if (ro.offset != 0) // only suffix offset if non-zero
2661                ss << "." << std::dec << (int)ro.offset;
2662         }
2663     }
formatDataOperand(LSC_DATA_SHAPE dataShape,int absIx)2664     void formatDataOperand(LSC_DATA_SHAPE dataShape, int absIx) {
2665         formatRawOperand(absIx);
2666         formatDataShape(dataShape);
2667     }
2668 
formatAddrType(LSC_ADDR_TYPE addrType,int absSurfOpIx)2669     void formatAddrType(LSC_ADDR_TYPE addrType, int absSurfOpIx) {
2670         switch (addrType) {
2671         case LSC_ADDR_TYPE_FLAT:  ss << "flat"; break;
2672         case LSC_ADDR_TYPE_BSS:   ss << "bss"; break;
2673         case LSC_ADDR_TYPE_SS:    ss << "ss"; break;
2674         case LSC_ADDR_TYPE_BTI:   ss << "bti"; break;
2675         default: formatBadEnum(addrType); break;
2676         }
2677         switch (addrType) {
2678         case LSC_ADDR_TYPE_BSS:
2679         case LSC_ADDR_TYPE_SS:
2680         case LSC_ADDR_TYPE_BTI:
2681             ss << "(";
2682             formatVectorOperand(absSurfOpIx);
2683             ss << ")";
2684             break;
2685         default: break;
2686         }
2687     }
2688 
formatAddrSize(LSC_ADDR_SIZE addrSize)2689     void formatAddrSize(LSC_ADDR_SIZE addrSize) {
2690         ss << ":";
2691         switch (addrSize) {
2692         case LSC_ADDR_SIZE_16b: ss << "a16"; break;
2693         case LSC_ADDR_SIZE_32b: ss << "a32"; break;
2694         case LSC_ADDR_SIZE_64b: ss << "a64"; break;
2695         default: formatBadEnum(addrSize); break;
2696         }
2697     }
2698 
formatDataSize(LSC_DATA_SIZE dataSize)2699     void formatDataSize(LSC_DATA_SIZE dataSize) {
2700         ss << ":";
2701         switch (dataSize) {
2702         case LSC_DATA_SIZE_8b:      ss << "d8"; break;
2703         case LSC_DATA_SIZE_16b:     ss << "d16"; break;
2704         case LSC_DATA_SIZE_32b:     ss << "d32"; break;
2705         case LSC_DATA_SIZE_64b:     ss << "d64"; break;
2706         case LSC_DATA_SIZE_8c32b:   ss << "d8c32"; break;
2707         case LSC_DATA_SIZE_16c32b:  ss << "d16c32"; break;
2708         case LSC_DATA_SIZE_16c32bH: ss << "d16c32h"; break;
2709         default: formatBadEnum(dataSize); break;
2710         }
2711     }
2712 
formatChannelMaskSuffix(int chEnMask)2713     void formatChannelMaskSuffix(int chEnMask) {
2714         ss << ".";
2715         auto VALID_MASKS =
2716             LSC_DATA_CHMASK_X |
2717             LSC_DATA_CHMASK_Y |
2718             LSC_DATA_CHMASK_Z |
2719             LSC_DATA_CHMASK_W;
2720         if (chEnMask & ~VALID_MASKS) {
2721             formatBadEnum(chEnMask);
2722         } else {
2723             if (LSC_DATA_CHMASK_X & chEnMask) {
2724                 ss << "x";
2725             }
2726             if (LSC_DATA_CHMASK_Y & chEnMask) {
2727                 ss << "y";
2728             }
2729             if (LSC_DATA_CHMASK_Z & chEnMask) {
2730                 ss << "z";
2731             }
2732             if (LSC_DATA_CHMASK_W & chEnMask) {
2733                 ss << "w";
2734             }
2735         }
2736     }
2737 
formatDataElemsSuffix(LSC_DATA_ELEMS dataElems,LSC_DATA_ORDER dataOrder)2738     void formatDataElemsSuffix(
2739         LSC_DATA_ELEMS dataElems,
2740         LSC_DATA_ORDER dataOrder)
2741     {
2742         switch (dataElems) {
2743         case LSC_DATA_ELEMS_1: break;
2744         case LSC_DATA_ELEMS_2:  ss << "x2"; break;
2745         case LSC_DATA_ELEMS_3:  ss << "x3"; break;
2746         case LSC_DATA_ELEMS_4:  ss << "x4"; break;
2747         case LSC_DATA_ELEMS_8:  ss << "x8"; break;
2748         case LSC_DATA_ELEMS_16: ss << "x16"; break;
2749         case LSC_DATA_ELEMS_32: ss << "x32"; break;
2750         case LSC_DATA_ELEMS_64: ss << "x64"; break;
2751         default: formatBadEnum(dataElems); break;
2752         }
2753         formatDataOrder(dataOrder);
2754     }
2755 
formatDataOrder(LSC_DATA_ORDER dataOrder)2756     void formatDataOrder(LSC_DATA_ORDER dataOrder) {
2757         switch (dataOrder) {
2758         case LSC_DATA_ORDER_NONTRANSPOSE: break;
2759         case LSC_DATA_ORDER_TRANSPOSE: ss << "t"; break;
2760         default: formatBadEnum(dataOrder); break;
2761         }
2762     }
2763 
formatDataShape(LSC_DATA_SHAPE dataShape)2764     void formatDataShape(LSC_DATA_SHAPE dataShape) {
2765         formatDataSize(dataShape.size);
2766         if (opInfo.hasChMask()) {
2767             formatChannelMaskSuffix(dataShape.chmask);
2768         } else {
2769             formatDataElemsSuffix(dataShape.elems, dataShape.order);
2770         }
2771     }
formatDataShape2D(LSC_DATA_SHAPE_BLOCK2D dataShape2D)2772     void formatDataShape2D(LSC_DATA_SHAPE_BLOCK2D dataShape2D) {
2773         formatDataSize(dataShape2D.size);
2774         ss << '.';
2775         if (dataShape2D.blocks != 1) {
2776           ss << std::dec << dataShape2D.blocks << 'x';
2777         }
2778         ss << std::dec << dataShape2D.width << 'x' << dataShape2D.height;
2779         ss << (dataShape2D.order == LSC_DATA_ORDER_TRANSPOSE ? 't' : 'n');
2780         ss << (dataShape2D.vnni ? 't' : 'n');
2781     }
2782 
formatCacheOpt(LSC_CACHE_OPT val)2783     void formatCacheOpt(LSC_CACHE_OPT val) {
2784         switch (val) {
2785         case LSC_CACHING_DEFAULT:        ss << ".df"; break;
2786         case LSC_CACHING_UNCACHED:       ss << ".uc"; break;
2787         case LSC_CACHING_CACHED:         ss << ".ca"; break;
2788         case LSC_CACHING_WRITEBACK:      ss << ".wb"; break;
2789         case LSC_CACHING_WRITETHROUGH:   ss << ".wt"; break;
2790         case LSC_CACHING_STREAMING:      ss << ".st"; break;
2791         case LSC_CACHING_READINVALIDATE: ss << ".ri"; break;
2792         default: formatBadEnum(val); break;
2793         }
2794     }
2795 
formatCachingOpts()2796     void formatCachingOpts() {
2797         auto l1 = getNextEnumU8<LSC_CACHE_OPT>();
2798         auto l3 = getNextEnumU8<LSC_CACHE_OPT>();
2799         bool cachingDefault =
2800             l1 == LSC_CACHE_OPT::LSC_CACHING_DEFAULT &&
2801             l3 == LSC_CACHE_OPT::LSC_CACHING_DEFAULT;
2802         if (!cachingDefault) {
2803             // only format cache control if it's non-default
2804             // NOTE: cache control doesn't have meaning on SLM, but should the
2805             // IR be malformed and accidentally have it, we'll indulge the user
2806             // (for debugging sake)
2807             formatCacheOpt(l1); // L1
2808             formatCacheOpt(l3); // L3
2809         }
2810     }
2811 
2812     /////////////////////////////////////////////////////////
2813     // top-level formatters for each instruction type
2814     /////////////////////////////////////////////////////////
2815 
formatFence()2816     void formatFence() {
2817         //
2818         ss << "lsc_fence";
2819         //
2820         auto lscSfid = getNextEnumU8<LSC_SFID>();
2821         formatSfid(lscSfid);
2822         //
2823         auto fenceOp = getNextEnumU8<LSC_FENCE_OP>();
2824         switch (fenceOp) {
2825         case LSC_FENCE_OP_NONE:       ss << ".none";       break;
2826         case LSC_FENCE_OP_EVICT:      ss << ".evict";      break;
2827         case LSC_FENCE_OP_INVALIDATE: ss << ".invalidate"; break;
2828         case LSC_FENCE_OP_DISCARD:    ss << ".discard";    break;
2829         case LSC_FENCE_OP_CLEAN:      ss << ".clean";      break;
2830         case LSC_FENCE_OP_FLUSHL3:    ss << ".flushl3";    break;
2831         case LSC_FENCE_OP_TYPE6:      ss << ".type6";      break;
2832         default: ss << ".???"; break;
2833         }
2834         //
2835         auto scope = getNextEnumU8<LSC_SCOPE>();
2836         switch (scope) {
2837         case LSC_SCOPE_GROUP:  ss << ".group";  break;
2838         case LSC_SCOPE_LOCAL:  ss << ".local";  break;
2839         case LSC_SCOPE_TILE:   ss << ".tile";   break;
2840         case LSC_SCOPE_GPU:    ss << ".gpu";    break;
2841         case LSC_SCOPE_GPUS:   ss << ".gpus";   break;
2842         case LSC_SCOPE_SYSREL: ss << ".sysrel"; break;
2843         case LSC_SCOPE_SYSACQ: ss << ".sysacq"; break;
2844         default: ss << ".???"; break;
2845         }
2846     } // formatFence
2847 
isVectorOpV0(const vector_opnd & vo) const2848     bool isVectorOpV0(const vector_opnd &vo) const {
2849         return (vo.tag & 0x7) == OPERAND_GENERAL &&
2850             (vo.opnd_val.gen_opnd.index == 0);
2851     }
2852 
2853     ///////////////////////////////////////////////////////////////////////////
2854     // for all but block2d and append counter atomic
formatUntypedSimple()2855     void formatUntypedSimple() {
2856         //
2857         ss << opInfo.mnemonic;
2858 
2859         //////////////////
2860         // sfid (e.g. .ugm, .ugml, or .slm)
2861         auto sfid = getNextEnumU8<LSC_SFID>();
2862         formatSfid(sfid);
2863         //
2864         //////////////////
2865         // caching
2866         formatCachingOpts();
2867 
2868         // execution size and offset
2869         ss << " " << printExecutionSize(inst->opcode, inst->execsize, subOp);
2870         //
2871         auto addrType = getNextEnumU8<LSC_ADDR_TYPE>();
2872         uint16_t immediateScale = getNext<uint16_t>();
2873         int32_t immediateOffset = getNext<int32_t>();
2874         auto addrSize = getNextEnumU8<LSC_ADDR_SIZE>();
2875         //
2876         auto dataShape = getNextDataShape();
2877         //
2878         ss << "  ";
2879 
2880         // see the table below for operand indices
2881         auto fmtAddrOperand = [&] () {
2882             formatAddrType(addrType, currOpIx);
2883             //
2884             ss << "[";
2885             if (immediateScale > 1) {
2886               ss << "0x" << std::hex << immediateScale << "*";
2887             }
2888             formatRawOperand(currOpIx + 2);
2889             if (immediateOffset != 0) {
2890                 if (immediateOffset < 0) {
2891                     immediateOffset = -immediateOffset;
2892                     ss << "-";
2893                 } else {
2894                     ss << "+";
2895                 }
2896                 ss << "0x" << std::hex << immediateOffset;
2897             }
2898             if (opInfo.isStrided()) {
2899                 const vector_opnd &vo = getVectorOperand(inst, currOpIx + 3);
2900                 if (!isVectorOpV0(vo)) {
2901                     // only non-V0 values
2902                     ss << ", ";
2903                     formatVectorOperand(currOpIx + 3);
2904                 }
2905             }
2906             ss << "]";
2907             formatAddrSize(addrSize);
2908         };
2909 
2910         // parameter order (c.f. IsaDescription.cpp)
2911         // =============================+===========================
2912         //  regular                     |  strided
2913         // =============================+===========================
2914         //   0 - surface                |  surface
2915         //   1 - dst       (data read)  |  dst         (data read)
2916         //   2 - src0      (addr)       |  src0        (addr-base)
2917         //   3 - src1      (data sent)  |  src0-stride (data sent)
2918         //   4 - src2      (atomic arg) |  src1        (data sent/atomic)
2919         //                              |  (src2 doesn't exist in strided)
2920         // =============================+===========================
2921         int src1AbsIx = opInfo.isStrided() ? currOpIx + 4 : currOpIx + 3;
2922         if (opInfo.isLoad()) {
2923             formatDataOperand(dataShape, currOpIx + 1); // dst
2924             ss << "  ";
2925             fmtAddrOperand(); // src0
2926         } else if (opInfo.isStore()) {
2927             fmtAddrOperand(); // src0
2928             ss << "  ";
2929             formatDataOperand(dataShape, src1AbsIx); // src1
2930         } else if (opInfo.isAtomic()) {
2931             formatDataOperand(dataShape, currOpIx + 1); // dst
2932             ss << "  ";
2933             fmtAddrOperand(); // src0
2934             ss << "  ";
2935             formatRawOperand(src1AbsIx); // src1
2936             ss << "  ";
2937             formatRawOperand(src1AbsIx + 1); // src2
2938         } else {
2939             MUST_BE_TRUE(false, "must be load or store or atomic");
2940         }
2941     } // formatUntypedSimple
2942 
2943     ///////////////////////////////////////////////////////////////////////////
formatUntypedBlock2D()2944     void formatUntypedBlock2D() {
2945         ss << opInfo.mnemonic;
2946 
2947         auto sfid = getNextEnumU8<LSC_SFID>();
2948         formatSfid(sfid);
2949 
2950         formatCachingOpts();
2951 
2952         // execution size and offset
2953         ss << " " << printExecutionSize(inst->opcode, inst->execsize, subOp);
2954 
2955         //
2956         LSC_DATA_SHAPE_BLOCK2D dataShape { };
2957         dataShape.size = getNextEnumU8<LSC_DATA_SIZE>();
2958         dataShape.order = getNextEnumU8<LSC_DATA_ORDER>();
2959         dataShape.blocks = (int)getNext<uint8_t>();
2960         dataShape.width = (int)getNext<uint16_t>();
2961         dataShape.height = (int)getNext<uint16_t>();
2962         dataShape.vnni = getNext<uint8_t>() != 0;
2963 
2964         auto formatDataOperand = [&] (int absOpIx) {
2965             formatRawOperand(absOpIx);
2966             formatDataShape2D(dataShape);
2967         };
2968         ss << "  ";
2969 
2970         ///////////////////////////////////////////////////////
2971         // The rest of the operands are arranged as follows.
2972         //   0 - SurfaceBase
2973         //   1 - SurfaceWidth
2974         //   2 - SurfaceHeight
2975         //   3 - SurfacePitch
2976         //   4 - SurfaceOffsetX
2977         //   5 - SurfaceOffsetY
2978         //   6 - DataOperand
2979         auto fmtAddrOperand = [&] () {
2980             ss << "flat";
2981             ss << "[";
2982             formatVectorOperand(currOpIx + 1);
2983             ss << ", ";
2984             formatVectorOperand(currOpIx + 2);
2985             ss << ", ";
2986             formatVectorOperand(currOpIx + 3);
2987             ss << ", ";
2988             formatVectorOperand(currOpIx + 4);
2989             ss << ", ";
2990             formatVectorOperand(currOpIx + 5);
2991             ss << ", ";
2992             formatVectorOperand(currOpIx + 6);
2993             ss << "]";
2994         };
2995 
2996         if (opInfo.isLoad()) {
2997             formatDataOperand(currOpIx + 0);
2998             ss << "  ";
2999             fmtAddrOperand();
3000         } else {
3001             fmtAddrOperand();
3002             ss << "  ";
3003             formatDataOperand(currOpIx + 7);
3004         }
3005     } // formatUntypedBlock2D
3006 
3007     ///////////////////////////////////////////////////////////////////////////
formatUntyped()3008     void formatUntyped() {
3009         if (subOp == LSC_LOAD_BLOCK2D || subOp == LSC_STORE_BLOCK2D) {
3010             formatUntypedBlock2D();
3011         } else {
3012             formatUntypedSimple();
3013         }
3014     } // formatUntyped
3015 
3016     ///////////////////////////////////////////////////////////////////////////
formatTyped()3017     void formatTyped() {
3018         ss << opInfo.mnemonic;
3019 
3020         formatSfid(LSC_TGM);
3021         //////////////////
3022         // caching
3023         formatCachingOpts();
3024 
3025         // execution size and offset
3026         ss << " " << printExecutionSize(inst->opcode, inst->execsize, subOp);
3027 
3028         auto addrType = getNextEnumU8<LSC_ADDR_TYPE>();
3029         auto addrSize = getNextEnumU8<LSC_ADDR_SIZE>();
3030         auto dataShape = getNextDataShape();
3031 
3032         auto fmtAddrOperand = [&] () {
3033             // 0 dst, 1-4 u/v/r/lod, 5 src1, 6 src2
3034             formatAddrType(addrType, currOpIx);
3035             ss << "[";
3036             for (int i = 0; i < 4; i++) {
3037                 // +2 skip surface and dst
3038                 const raw_opnd &ro = getRawOperand(inst, currOpIx+2+i);
3039                 auto reg =
3040                     printVariableDeclName(header, ro.index, opts, NOT_A_STATE_OPND);
3041                 if (reg == "V0")
3042                     break;
3043                 if (i > 0)
3044                     ss << ", ";
3045                 ss << reg;
3046             }
3047             ss << "]";
3048             formatAddrSize(addrSize);
3049         };
3050 
3051         ss << "  ";
3052 
3053         // parameter order (cf IsaDescription.cpp)
3054         //   0 - surface
3055         //   1 - dst (data read)
3056         //   2 - src0 U's (addr)
3057         //   3 - src0 V's (addr)
3058         //   4 - src0 R's (addr)
3059         //   5 - src0 LOD's (addr)
3060         //   6 - src1 (data sent)
3061         //   7 - src2 (extra data sent for atomic)
3062         if (opInfo.isLoad()) {
3063             formatDataOperand(dataShape, currOpIx + 1);
3064             ss << "  ";
3065             fmtAddrOperand();
3066         } else if (opInfo.isStore()) {
3067             fmtAddrOperand();
3068             ss << "  ";
3069             formatDataOperand(dataShape, currOpIx + 6);
3070         } else if (opInfo.isAtomic()) {
3071             formatDataOperand(dataShape, currOpIx + 1); // dst write back
3072             ss << "  ";
3073             fmtAddrOperand();
3074             ss << "  ";
3075             formatRawOperand(currOpIx + 6); // iadd, etc
3076             ss << "  ";
3077             formatRawOperand(currOpIx + 7); // for {i,f}cas
3078         } else {
3079             error = true;
3080             MUST_BE_TRUE(false, "printInstructionLscTyped unexpected category");
3081         }
3082     } // formatTyped
3083 
3084     // e.g. lsc_read_state_info.tgm  VDATA  bti(0x4)
formatTypedRSI()3085     void formatTypedRSI() {
3086         ss << opInfo.mnemonic;
3087 
3088         formatSfid(LSC_TGM);
3089 
3090         // will be default/default (and thus suppressed)
3091         formatCachingOpts();
3092 
3093         // exec size is implicit
3094         auto addrType = getNextEnumU8<LSC_ADDR_TYPE>();
3095         (void)getNextEnumU8<LSC_ADDR_SIZE>();
3096         (void)getNextDataShape();
3097 
3098         ss << "  ";
3099         formatRawOperand(currOpIx + 1); // dst
3100         ss << "  ";
3101         formatAddrType(addrType, currOpIx);
3102     }
3103 
3104 public:
3105     // the only public entry point (except the constructor)
format()3106     std::string format() {
3107         ss << printPredicate(inst->opcode, inst->pred);
3108 
3109         if (opcode == ISA_LSC_FENCE) {
3110             formatFence();
3111         } else if (opcode == ISA_LSC_UNTYPED) {
3112             formatUntyped();
3113         } else if (opcode == ISA_LSC_TYPED) {
3114             if (opInfo.op == LSC_READ_STATE_INFO) {
3115                 formatTypedRSI();
3116             } else {
3117                 formatTyped();
3118             }
3119         } else {
3120             MUST_BE_TRUE(false, "invalid LSC op");
3121         }
3122         return ss.str();
3123     }
3124 };
3125 
3126 
printInstructionLsc(ISA_Opcode opcode,const print_format_provider_t * header,const CISA_INST * inst,const Options * opt)3127 static std::string printInstructionLsc(
3128     ISA_Opcode opcode,
3129     const print_format_provider_t* header,
3130     const CISA_INST* inst,
3131     const Options *opt)
3132 {
3133     LscInstFormatter formatter(opcode, header, inst, opt);
3134     return formatter.format();
3135 }
3136 
printKernelHeader(const common_isa_header & isaHeader)3137 std::string VISAKernel_format_provider::printKernelHeader(
3138     const common_isa_header& isaHeader)
3139 {
3140     std::stringstream sstr;
3141 
3142     bool isKernel = m_kernel->getIsKernel();
3143 
3144     sstr << printBuildVersion(isaHeader) << std::endl;
3145     sstr << printFunctionDecl(this, isKernel) << std::endl;
3146 
3147     // Print all functions in the same object
3148     if (isKernel)
3149     {
3150         for (unsigned i = 0; i < isaHeader.num_functions; i++)
3151         {
3152             sstr << ".funcdecl ";
3153             encodeStringLiteral(sstr, isaHeader.functions[i].name);
3154             sstr << "\n";
3155         }
3156     }
3157 
3158     auto options = const_cast<VISAKernelImpl*>(m_kernel)->getOptions();
3159 
3160     // Print the predefined variables as comments
3161     sstr << "\n" << "/// VISA Predefined Variables";
3162     for (unsigned i = 0; i < Get_CISA_PreDefined_Var_Count(); i++)
3163     {
3164         const var_info_t* predefVar = getPredefVar(i);
3165         if (predefVar->name_index != -1)
3166         {
3167             sstr << "\n" << "// .decl V" << i
3168                 << " v_type=G"
3169                 << " v_name=" << getString(predefVar->name_index);
3170         }
3171     }
3172     for (unsigned i = 0; i < Get_CISA_PreDefined_Surf_Count(); i++)
3173     {
3174         const state_info_t* predefSurface = getPredefSurface(i);
3175         if (predefSurface->name_index != -1)
3176         {
3177             sstr << "\n" << "// .decl T" << i
3178                 << " v_type=T"
3179                 << " v_name=" << getString(predefSurface->name_index);
3180         }
3181     }
3182     sstr << "\n";
3183 
3184     // emit var decls
3185     //.decl  V<#> name=<name> type=<type> num_elts=<num_elements> [align=<align>] [alias=(<alias_index>,<alias_offset>)]
3186     for (unsigned i = 0; i < getVarCount(); i++)
3187     {
3188         sstr << "\n" << printVariableDecl(this, i, options);
3189     }
3190     // address decls
3191     for (unsigned i = 0; i < getAddrCount(); i++)
3192     {
3193         sstr << "\n" << printAddressDecl(isaHeader, this, i);
3194     }
3195     // pred decls
3196     for (unsigned i = 0; i < getPredCount(); i++)
3197     {
3198         // P0 is reserved; starting from P1 if there is predicate decl
3199         sstr << "\n" << printPredicateDecl(this, i);
3200     }
3201     // sampler
3202     for (unsigned i = 0; i < getSamplerCount(); i++)
3203     {
3204         sstr << "\n" << printSamplerDecl(this, i);
3205     }
3206     // surface
3207     unsigned numPreDefinedSurfs = Get_CISA_PreDefined_Surf_Count();
3208     for (unsigned i = 0; i < getSurfaceCount(); i++)
3209     {
3210         sstr << "\n" << printSurfaceDecl(this, i, numPreDefinedSurfs);
3211     }
3212     // inputs to kernel
3213     for (unsigned i = 0; i < getInputCount(); i++)
3214     {
3215         sstr << "\n" << printFuncInput(this, i, isKernel, options);
3216     }
3217 
3218     bool isTargetSet = false;
3219     for (unsigned i = 0; i < getAttrCount(); i++)
3220     {
3221         const char* attrName = getString(getAttr(i)->nameIndex);
3222         if (Attributes::isAttribute(Attributes::ATTR_OutputAsmPath, attrName)) {
3223             // treat this as a transient property and skip it
3224             // this simplifies diffs in shader dump debugging
3225             // if you want to set an explicit name from the command line,
3226             // then use the appropriate option to set this attribute
3227             continue;
3228         }
3229         if (Attributes::isAttribute(Attributes::ATTR_Target, attrName)) {
3230             isTargetSet = true;
3231         }
3232         sstr << "\n.kernel_attr " << printOneAttribute(this, getAttr(i));
3233     }
3234     if (!isTargetSet)
3235     {
3236         const char* attrName = Attributes::getAttributeName(Attributes::ATTR_Target);
3237         sstr << "\n" << ".kernel_attr " << attrName << "=";
3238         switch (options->getTarget()) {
3239         case VISA_CM: sstr << "\"cm\""; break;
3240         case VISA_3D: sstr << "\"3d\""; break;
3241         default:
3242             MUST_BE_TRUE(false, "Invalid kernel target attribute.");
3243             break;
3244         }
3245     }
3246 
3247     return sstr.str();
3248 }
3249 
printFunctionDecl(const print_format_provider_t * header,bool isKernel)3250 std::string printFunctionDecl(const print_format_provider_t* header, bool isKernel)
3251 {
3252     std::stringstream sstr;
3253     std::string name = header->getString(header->getNameIndex());
3254     std::replace_if(name.begin(), name.end(), [](char c) { return c == '.'; }, ' ');
3255 
3256     sstr << (!isKernel ? ".global_function " : ".kernel ");
3257     encodeStringLiteral(sstr, name.c_str());
3258     return sstr.str();
3259 }
3260 
printBuildVersion(const common_isa_header & isaHeader)3261 std::string printBuildVersion(const common_isa_header& isaHeader)
3262 {
3263     std::stringstream sstr;
3264     sstr << ".version " << (int)(isaHeader.major_version) << "." << (int)(isaHeader.minor_version);
3265     return sstr.str();
3266 }
3267 
printInstruction(const print_format_provider_t * header,const CISA_INST * instruction,const Options * opt)3268 std::string printInstruction(
3269     const print_format_provider_t* header,
3270     const CISA_INST* instruction,
3271     const Options *opt)
3272 {
3273     std::stringstream sstr;
3274 
3275     ISA_Opcode opcode = (ISA_Opcode)instruction->opcode;
3276     if (opcode != ISA_LOC || !g_ignorelocs)
3277     {
3278         if (opcode != ISA_LABEL)
3279         {
3280             sstr << "    ";
3281         }
3282 
3283         switch (ISA_Inst_Table[opcode].type)
3284         {
3285             case ISA_Inst_Mov:
3286             case ISA_Inst_Sync:
3287             case ISA_Inst_Arith:
3288             case ISA_Inst_Logic:
3289             case ISA_Inst_Compare:
3290             case ISA_Inst_Address:
3291             case ISA_Inst_SIMD_Flow: sstr << printInstructionCommon      (header, instruction, opt); break;
3292             case ISA_Inst_SVM:       sstr << printInstructionSVM         (header, instruction, opt); break;
3293             case ISA_Inst_Flow:      sstr << printInstructionControlFlow (header, instruction, opt); break;
3294             case ISA_Inst_Misc:      sstr << printInstructionMisc        (header, instruction, opt); break;
3295             case ISA_Inst_Sampler:   sstr << printInstructionSampler     (header, instruction, opt); break;
3296             case ISA_Inst_Data_Port: sstr << printInstructionDataport    (header, instruction, opt); break;
3297             case ISA_Inst_LSC:       sstr << printInstructionLsc         (opcode, header, instruction, opt); break;
3298             default:
3299             {
3300                 sstr << "Illegal or unimplemented CISA instruction (opcode, type): ("
3301                      << opcode << ", " << ISA_Inst_Table[opcode].type << ").";
3302                 MUST_BE_TRUE(false, sstr.str());
3303             }
3304         }
3305 
3306         switch (opcode)
3307         {
3308             case ISA_LOC:
3309             case ISA_SUBROUTINE:
3310             case ISA_FILE:
3311             case ISA_LABEL: break;
3312             default:
3313             {
3314                 std::stringstream sstr2;
3315                 if (g_prettyPrint)
3316                 for (int i = 0; i < (int)80 - (int)sstr.str().length(); i++)
3317                     sstr2 << ' ';
3318                 if (!g_noinstid)
3319                     sstr << sstr2.str() << " /// $" << instruction->id;
3320             }
3321         }
3322     }
3323     else
3324     {
3325         sstr << "";
3326     }
3327 
3328     return sstr.str();
3329 }
3330