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