Files
intel-graphics-compiler/visa/IsaDisassembly.cpp
2018-01-30 10:00:45 -08:00

2769 lines
93 KiB
C++

/*===================== begin_copyright_notice ==================================
Copyright (c) 2017 Intel Corporation
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
======================= end_copyright_notice ==================================*/
/*
* ISA IR Disassembler
*
* This library is designed to be extremely reusable and general in nature, and as a result
* the following ISA IR disassembly code primarily uses the following IR and data types:
*
* - common_isa_header
* - kernel_format_t
* - attribute_info_t
* - CISA_opnd
* - vector_opnd
* - raw_opnd
* - CISA_INST
* - std::list<CISA_INST*>
*
* and prints them as human readable text to an isaasm file.
*
* Use of any other data types should be discussed by several members of the CM jitter team before hand.
*
*/
#ifndef IS_RELEASE_DLL
#include <stdint.h>
#include <list>
#include <string>
#include <sstream>
#include "visa_igc_common_header.h"
#include "common.h"
#include "Mem_Manager.h"
#include "Common_ISA.h"
#include "Common_ISA_framework.h"
#include "Common_ISA_util.h"
#include "cm_portability.h"
#include "IsaDisassembly.h"
#include "Option.h"
#include "JitterDataStruct.h"
#include "VISABuilderAPIDefinition.h"
#include "PreDefinedVars.h"
using namespace std;
using namespace vISA;
/// Output flags.
_THREAD bool g_shortRegionPrint = false; /// Use shorthand names for common regions.
_THREAD bool g_inlineTypePrint = false; /// Print the type information with operands.
_THREAD bool g_prettyPrint = true ; /// Line up the comments.
_THREAD bool g_ignorelocs = false; /// Ignore printing LOCs.
_THREAD bool g_noinstid = false; /// Ignore printing instruction id comments.
extern const char* printAsmName(const kernel_format_t* header)
{
for (unsigned i = 0; i < header->attribute_count; i++)
{
if (!strcmp(header->strings[header->attributes[i].nameIndex], "AsmName"))
return header->attributes[i].value.stringVal;
}
return "";
}
static const char* getVarName(int id, const common_isa_header& isaHeader, const kernel_format_t& header)
{
int numPredefined = Get_CISA_PreDefined_Var_Count(isaHeader.major_version, isaHeader.minor_version);
if (id < numPredefined)
{
return getPredefinedVarString(mapExternalToInternalPreDefVar(id, isaHeader.major_version, isaHeader.minor_version));
}
else
{
MUST_BE_TRUE((id - numPredefined) < (int) header.variable_count, "invalid vISA general variable id");
return header.strings[header.variables[id - numPredefined].name_index];
}
}
unsigned int getRelocatedGlobalVarIndex(const common_isa_header& isaHeader, unsigned declID, bool isKernel, unsigned int funcId)
{
// declID is a symbolic index in to file scope variable table. Refer to relocation
// table and return resolved index.
reloc_symtab& var_sym_tab = (isKernel == true) ?
isaHeader.kernels[0].variable_reloc_symtab :
isaHeader.functions[funcId].variable_reloc_symtab;
for( unsigned int i = 0; i < var_sym_tab.num_syms; i++ )
{
reloc_sym& sym = var_sym_tab.reloc_syms[i];
if( sym.symbolic_index == declID )
{
return sym.resolved_index;
}
}
return 0;
}
string printGlobalDeclName(const common_isa_header& isaHeader, const kernel_format_t* header, unsigned declID, bool isKernel, unsigned int funcId, Options *options)
{
MUST_BE_TRUE(header, "Argument Exception: argument header is NULL.");
stringstream sstr;
unsigned int resolvedDclID = getRelocatedGlobalVarIndex(isaHeader, declID, isKernel, funcId);
if (options->getOption(vISA_DumpIsaVarNames) && resolvedDclID < isaHeader.num_filescope_variables &&
isaHeader.filescope_variables && isaHeader.filescope_variables[resolvedDclID].name)
{
sstr << isaHeader.filescope_variables[resolvedDclID].name;
}
else
{
sstr << 'F' << resolvedDclID;
}
return sstr.str();
}
static string printSurfaceName(const common_isa_header& isaHeader, uint32_t declID)
{
stringstream sstr;
uint8_t major_version = isaHeader.major_version;
uint8_t minor_version = isaHeader.minor_version;
unsigned numPreDefinedSurf = Get_CISA_PreDefined_Surf_Count(major_version, minor_version);
if (declID < numPreDefinedSurf)
{
sstr << vISAPreDefSurf[declID].name;
}
else
{
sstr << "T" << declID;
}
return sstr.str();
}
string printVariableDeclName(const common_isa_header& isaHeader, const kernel_format_t* header, unsigned declID, Options *options, Common_ISA_State_Opnd_Class operand_prefix_kind = NOT_A_STATE_OPND)
{
MUST_BE_TRUE(header, "Argument Exception: argument header is NULL.");
stringstream sstr;
uint8_t major_version = isaHeader.major_version;
uint8_t minor_version = isaHeader.minor_version;
unsigned numPreDefinedVars = Get_CISA_PreDefined_Var_Count(major_version, minor_version);
if (options->getOption(vISA_DumpIsaVarNames))
{
sstr << getVarName(declID, isaHeader, *header);
}
else
{
switch (operand_prefix_kind)
{ case STATE_OPND_SURFACE : sstr << printSurfaceName(isaHeader, declID); break;
case STATE_OPND_SAMPLER : sstr << "S" << declID; break;
case STATE_OPND_VME : sstr << "VME" << declID; break;
default :
if(options->getOption(vISA_easyIsaasm) == false ||
options->getOption(vISA_PlatformIsSet) == false)
{
// If platform is not set then dcl instances are
// not created causing a crash. So print dcl name
// the old way.
if (declID < numPreDefinedVars)
{
sstr << "V" << declID;
}
else
{
declID -= numPreDefinedVars;
var_info_t *var = &(header->variables[declID]);
string name = header->strings[var->name_index];
//sstr << "V" << declID << ":";
sstr << name;
}
}
else
{
if(declID < numPreDefinedVars)
{
sstr << "V" << declID;
}
else
{
G4_Declare* aliasDcl = header->variables[declID - numPreDefinedVars].dcl;
unsigned int aliasOff = 0;
std::string type;
type = std::string(G4_Type_Table[aliasDcl->getElemType()].str);
while(aliasDcl->getAliasDeclare() != NULL)
{
aliasOff += aliasDcl->getAliasOffset();
aliasDcl = aliasDcl->getAliasDeclare();
}
// aliasDcl is top most dcl with aliasOff
// Lets find out declID of aliasDcl
for(unsigned int i = 0; i < header->variable_count; i++)
{
if(header->variables[i].dcl == aliasDcl)
{
declID = i + numPreDefinedVars;
break;
}
}
sstr << "V" << declID << "_" << type;
if(aliasOff != 0)
{
sstr << "_" << aliasOff;
}
}
}
break;
}
}
return sstr.str();
}
static string printRegion(uint16_t region)
{
stringstream sstr;
Common_ISA_Region_Val v_stride = (Common_ISA_Region_Val)(region & 0xF);
Common_ISA_Region_Val width = (Common_ISA_Region_Val)((region >> 4 ) & 0xF);
Common_ISA_Region_Val h_stride = (Common_ISA_Region_Val)((region >> 8 ) & 0xF);
if (width == REGION_NULL)
{
//dst operand, only have horizontal stride
sstr << "<" << Common_ISA_Get_Region_Value(h_stride) << ">";
}
else if (v_stride == REGION_NULL)
{
// VxH mode for indirect operand
sstr << "<" << Common_ISA_Get_Region_Value(width) << "," << Common_ISA_Get_Region_Value(h_stride) << ">";
}
else
{
if (g_shortRegionPrint &&
0 == Common_ISA_Get_Region_Value(v_stride) &&
1 == Common_ISA_Get_Region_Value(width) &&
0 == Common_ISA_Get_Region_Value(h_stride))
{
sstr << ".s";
}
else if (g_shortRegionPrint &&
Common_ISA_Get_Region_Value(v_stride) ==
Common_ISA_Get_Region_Value(width) &&
1 == Common_ISA_Get_Region_Value(h_stride))
{
sstr << ".v";
}
else
{
sstr << "<" << Common_ISA_Get_Region_Value(v_stride) << ";" << Common_ISA_Get_Region_Value(width) << "," << Common_ISA_Get_Region_Value(h_stride) << ">";
}
}
return sstr.str();
}
string printVectorOperand(const common_isa_header& isaHeader, const kernel_format_t* header,
const vector_opnd& opnd, Options *opt, bool showRegion)
{
stringstream sstr;
MUST_BE_TRUE(header, "Argument Exception: argument header is NULL.");
VISA_Modifier modifier = (VISA_Modifier)((opnd.tag >> 3) & 0x7);
/// .sat is dumped with the opcode
if (modifier == MODIFIER_SAT)
modifier = MODIFIER_NONE;
sstr << " ";
switch (opnd.tag & 0x7)
{
case OPERAND_GENERAL:
{
sstr << Common_ISA_Get_Modifier_Name(modifier) << printVariableDeclName(isaHeader, header, opnd.getOperandIndex(), opt, NOT_A_STATE_OPND);
if ((!g_shortRegionPrint) ||
(!(opnd.opnd_val.gen_opnd.row_offset == 0 &&
(((opnd.opnd_val.gen_opnd.col_offset == 0))))))
{
sstr << "("
<< (unsigned)opnd.opnd_val.gen_opnd.row_offset << ","
<< (unsigned)opnd.opnd_val.gen_opnd.col_offset << ")";
}
if (showRegion)
{
sstr << printRegion(opnd.opnd_val.gen_opnd.region);
}
break;
}
case OPERAND_ADDRESS:
{
sstr << Common_ISA_Get_Modifier_Name(modifier) << "A" << opnd.opnd_val.addr_opnd.index
<< "(" << (unsigned)opnd.opnd_val.addr_opnd.offset << ")<"
<< Get_Common_ISA_Exec_Size((Common_ISA_Exec_Size)(opnd.opnd_val.addr_opnd.width & 0xF)) << ">";
break;
}
case OPERAND_PREDICATE:
{
sstr << Common_ISA_Get_Modifier_Name(modifier) << "P" << opnd.opnd_val.pred_opnd.index;
break;
}
case OPERAND_INDIRECT:
{
sstr << Common_ISA_Get_Modifier_Name(modifier) << "r[A" << opnd.opnd_val.indirect_opnd.index
<< "("
<< (unsigned)opnd.opnd_val.indirect_opnd.addr_offset << "),"
<< (short) opnd.opnd_val.indirect_opnd.indirect_offset << "]" ;
sstr << printRegion(opnd.opnd_val.indirect_opnd.region);
VISA_Type type = (VISA_Type)(opnd.opnd_val.indirect_opnd.bit_property & 0xf);
sstr << ":" << CISATypeTable[type].typeName;
break;
}
case OPERAND_ADDRESSOF:
{
sstr << "&" << printVariableDeclName(isaHeader, header, opnd.getOperandIndex(), opt, NOT_A_STATE_OPND)
<< (((short)opnd.opnd_val.addressof_opnd.addr_offset >= 0) ? "+" : "")
<< (((short)opnd.opnd_val.addressof_opnd.addr_offset));
break;
}
case OPERAND_IMMEDIATE:
{
VISA_Type type = (VISA_Type)(opnd.opnd_val.const_opnd.type & 0xF);
if (type == ISA_TYPE_DF)
sstr << "0x" << hex
<< *((uint64_t*) &opnd.opnd_val.const_opnd._val.dval) << ":" << CISATypeTable[type].typeName << dec;
else if (type == ISA_TYPE_Q || type == ISA_TYPE_UQ)
sstr << "0x" << hex
<< opnd.opnd_val.const_opnd._val.lval << ":" << CISATypeTable[type].typeName << dec;
else
sstr << "0x" << hex
<< opnd.opnd_val.const_opnd._val.ival << ":" << CISATypeTable[type].typeName << dec;
break;
}
case OPERAND_STATE:
{
sstr << printVariableDeclName(isaHeader, header, opnd.getOperandIndex(), opt, (Common_ISA_State_Opnd_Class)opnd.opnd_val.state_opnd.opnd_class)
<< "(" << (unsigned)opnd.opnd_val.state_opnd.offset << ")";
break;
}
default: ASSERT_USER(false, "Attempted to dump an invalid or unimplemented vector operand type.");
}
return sstr.str();
}
string printRawOperand(const common_isa_header& isaHeader, const kernel_format_t* header, const raw_opnd& opnd, Options *opt)
{
MUST_BE_TRUE(header, "Argument Exception: argument header is NULL.");
stringstream sstr;
sstr << " " << printVariableDeclName(isaHeader, header, opnd.index, opt, NOT_A_STATE_OPND) << "." << opnd.offset;
return sstr.str();
}
static string printOperand(const common_isa_header& isaHeader, const kernel_format_t* header, const CISA_INST* inst, unsigned i, Options *opt)
{
MUST_BE_TRUE(header, "Argument Exception: argument header is NULL.");
MUST_BE_TRUE(inst , "Argument Exception: argument inst is NULL.");
MUST_BE_TRUE(inst->opnd_count > i, "No such operand, i, for instruction inst.");
stringstream sstr;
bool showRegion = true;
switch (getOperandType(inst, i))
{
case CISA_OPND_OTHER : sstr << (getPrimitiveOperand<unsigned> (inst, i)); break;
case CISA_OPND_VECTOR : sstr << printVectorOperand(isaHeader, header, getVectorOperand(inst, i), opt, showRegion); break;
case CISA_OPND_RAW : sstr << printRawOperand (isaHeader, header, getRawOperand (inst, i), opt); break;
default : MUST_BE_TRUE(false, "Invalid operand type.");
}
return sstr.str();
}
static string printAttribute(const attribute_info_t* attr, const kernel_format_t* kernel, bool isKernelAttr = false)
{
stringstream sstr;
sstr <<"";
if (attr->isInt && attr->size == 1 && attr->value.intVal == 0 )
{
return sstr.str();
}
sstr << "." << (isKernelAttr ? "kernel_" : "") << "attr " << kernel->strings[attr->nameIndex] << "=";
if (attr->isInt)
sstr << attr->value.intVal;
else if (attr->size > 0)
{
sstr << attr->value.stringVal;
}
return sstr.str();
}
extern string printPredicateDecl(const common_isa_header& isaHeader, const kernel_format_t* header, unsigned declID)
{
MUST_BE_TRUE(header, "Argument Exception: argument header is NULL.");
stringstream sstr;
pred_info_t* pred = &header->predicates[declID];
sstr << ".decl P"
<< declID + COMMON_ISA_NUM_PREDEFINED_PRED
<< " "
<< "v_type=P "
<< "num_elts=" << pred->num_elements;
for (unsigned j = 0; j < pred->attribute_count; j++)
{
sstr << " " << printAttribute(&pred->attributes[j], header);
}
return sstr.str();
}
extern string printAddressDecl(const common_isa_header& isaHeader, const kernel_format_t* header, unsigned declID)
{
MUST_BE_TRUE(header, "Argument Exception: argument header is NULL.");
stringstream sstr;
addr_info_t* addr = &header->addresses[declID];
sstr << ".decl A"
<< declID
<< " "
<< "v_type=A "
<< "num_elts=" << addr->num_elements;
for (unsigned j = 0; j < addr->attribute_count; j++)
{
sstr << " " << printAttribute(&addr->attributes[j], header);
}
return sstr.str();
}
// declID is in the range of [0..#user-var], pre-defnied are not included
extern string printVariableDecl(const common_isa_header& isaHeader, const kernel_format_t* header, unsigned declID, bool isKernel, unsigned int funcId, Options *options)
{
uint8_t major_version = isaHeader.major_version;
uint8_t minor_version = isaHeader.minor_version;
MUST_BE_TRUE(header, "Argument Exception: argument header is NULL.");
stringstream sstr;
var_info_t *var = &(header->variables[declID]);
VISA_Type isa_type = (VISA_Type) ((var->bit_properties ) & 0xF);
VISA_Align align = (VISA_Align) ((var->bit_properties >> 4) & 0x7);
unsigned numPreDefinedVars = Get_CISA_PreDefined_Var_Count(major_version, minor_version);
sstr << ".decl " << printVariableDeclName(isaHeader, header, declID+numPreDefinedVars, options)
<< " v_type=G"
<< " type=" << CISATypeTable[isa_type].typeName
<< " num_elts=" << var->num_elements;
if(align != ALIGN_UNDEF)
sstr << " align=" << Common_ISA_Get_Align_Name(align);
if (var->alias_index || var->alias_scope_specifier)
{
sstr << " alias=<";
if (options->getOption(vISA_DumpIsaVarNames))
{
sstr << (var->alias_scope_specifier ? printGlobalDeclName(isaHeader, header, var->alias_index, isKernel, funcId, options) : printVariableDeclName(isaHeader, header, var->alias_index, options));
}
else
{
if(options->getOption(vISA_easyIsaasm))
{
sstr << printVariableDeclName(isaHeader, header, var->alias_index, options);
}
else
{
sstr << (var->alias_scope_specifier ? 'F' : 'V') << var->alias_index;
}
}
sstr << ", " << var->alias_offset << ">";
}
for (unsigned j = 0; j < var->attribute_count; j++)
{
sstr << " " << printAttribute(&var->attributes[j], header);
}
return sstr.str();
}
const char* emask_str_3_0[10] =
{
"M1",
"M2",
"M3",
"M4",
"M5",
"M6",
"M7",
"M8",
"NoMask",
""
};
typedef enum {
CISA_EMASK_M0,
CISA_EMASK_M1,
CISA_EMASK_M2,
CISA_EMASK_M3,
CISA_EMASK_M4,
CISA_EMASK_M5,
CISA_EMASK_M6,
CISA_EMASK_M7,
CISA_NO_EMASK,
CISA_DEF_EMASK
} Common_ISA_EMask_Ctrl_3_0;
string printExecutionSize(uint8_t opcode, uint8_t execSize, const common_isa_header& isaHeader, uint8_t subOp = 0)
{
stringstream sstr;
if(hasExecSize((ISA_Opcode)opcode, subOp))
{
sstr << "(";
uint8_t emsk = ((execSize >> 0x4) & 0xF);
sstr << emask_str[emsk] << ", ";
sstr << (unsigned) Get_Common_ISA_Exec_Size((Common_ISA_Exec_Size)(execSize & 0xF));
sstr << ")";
}
if (g_shortRegionPrint && !strcmp("(1)", sstr.str().c_str()))
return " ";
return sstr.str();
}
// execution size is formatted differently for scatter/gather/scatter4/gather4/scatter4_typed/gather4_typed
static string printExecutionSizeForScatterGather(uint8_t sizeAndMask, const common_isa_header& isaHeader)
{
stringstream sstr;
sstr << "(";
Common_VISA_EMask_Ctrl emask = (Common_VISA_EMask_Ctrl)((sizeAndMask >> 0x4) & 0xF);
if (isaHeader.major_version == 3 && isaHeader.minor_version == 0)
{
sstr << emask_str_3_0[emask] << ", ";
}
else
{
sstr << emask_str[emask] << ", ";
}
unsigned execSize = 0;
switch (sizeAndMask & 0x3)
{
case 0:
execSize = 8;
break;
case 1:
execSize = 16;
break;
case 2:
execSize = 1;
break;
default:
ASSERT_USER(false, "illegal execution size for scatter/gather message");
}
sstr << execSize;
sstr << ")";
return sstr.str();
}
string printPredicate(uint8_t opcode, uint16_t predOpnd)
{
stringstream sstr;
if (hasPredicate((ISA_Opcode)opcode) && predOpnd != 0)
{
sstr << "(";
if (predOpnd & 0x8000) sstr << "!";
sstr << "P" << (predOpnd & 0xfff);
VISA_PREDICATE_CONTROL control = (VISA_PREDICATE_CONTROL)((predOpnd & 0x6000) >> 13);
switch (control)
{
case PRED_CTRL_ANY:
sstr << ".any";
break;
case PRED_CTRL_ALL:
sstr << ".all";
default:
break;
}
sstr << ") ";
}
return sstr.str();
}
static void printAtomicSubOpc(stringstream &sstr, uint8_t value)
{
CMAtomicOperations op = static_cast<CMAtomicOperations>(value & 0x1F);
sstr << "." << CISAAtomicOpNames[op];
bool is16Bit = (value >> 5) == 1;
if (is16Bit)
{
sstr << ".16";
}
}
static string printInstructionSVM(const common_isa_header& isaHeader, const kernel_format_t* header, const CISA_INST* inst, Options *opt)
{
unsigned i = 0;
stringstream sstr;
SVMSubOpcode subOpcode = (SVMSubOpcode)getPrimitiveOperand<uint8_t>(inst, i++);
/// TODO: Print out the predicate here
sstr << "svm_";
switch (subOpcode)
{
case SVM_BLOCK_ST:
case SVM_BLOCK_LD:
{
sstr << "block_" << (subOpcode == SVM_BLOCK_ST ? "st" : "ld");
uint8_t properties = getPrimitiveOperand<uint8_t>(inst, i++);
if (properties & 8)
sstr << ".unaligned";
Common_ISA_Oword_Num numOwords = (Common_ISA_Oword_Num) (properties & 0x7);
sstr << " (" << Get_Common_ISA_Oword_Num(numOwords) << ")";
break;
}
case SVM_GATHER:
case SVM_SCATTER:
{
sstr << (subOpcode == SVM_GATHER ? "gather" : "scatter");
uint8_t block_size = getPrimitiveOperand<uint8_t>(inst, i++);
uint8_t num_blocks = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << "." << Get_Common_ISA_SVM_Block_Size((Common_ISA_SVM_Block_Type)block_size);
sstr << "." << Get_Common_ISA_SVM_Block_Num((Common_ISA_SVM_Block_Num)num_blocks);
sstr << " " << printExecutionSize(inst->opcode, inst->execsize, isaHeader, subOpcode);
break;
}
case SVM_ATOMIC:
{
sstr << "atomic";
/// TODO: Need platform information for this to work.
printAtomicSubOpc(sstr, getPrimitiveOperand<uint8_t>(inst, i++));
sstr << " " << printExecutionSize(inst->opcode, inst->execsize, isaHeader, subOpcode);
/// element offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// DWORD_ATOMIC is weird and has the text version
/// putting the dst operand before the src operands.
stringstream sstr1;
/// src0
sstr1 << printOperand(isaHeader, header, inst, i++, opt);
/// src1
sstr1 << printOperand(isaHeader, header, inst, i++, opt);
/// message operand (src or dst)
sstr << printOperand(isaHeader, header, inst, i++, opt);
sstr << sstr1.str();
break;
}
case SVM_GATHER4SCALED:
case SVM_SCATTER4SCALED:
{
sstr << (subOpcode == SVM_GATHER4SCALED ? "gather4scaled" : "scatter4scaled");
unsigned chMask = getPrimitiveOperand<uint8_t>(inst, i++);
// scale is ignored (MBZ)
(void) getPrimitiveOperand<uint16_t>(inst, i++);
sstr << "." << channel_mask_str[chMask];
sstr << " " << printExecutionSize(inst->opcode, inst->execsize, isaHeader, subOpcode);
sstr << printOperand(isaHeader, header, inst, i++, opt);
sstr << printOperand(isaHeader, header, inst, i++, opt);
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
default:
ASSERT_USER(false, "Unimplemented or Illegal SVM Sub Opcode.");
}
for (; i < inst->opnd_count; i++)
sstr << printOperand(isaHeader, header, inst, i, opt);
return sstr.str();
}
static string printInstructionCommon(const common_isa_header& isaHeader, const kernel_format_t* header, const CISA_INST* inst, Options *opt)
{
ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
stringstream sstr;
sstr << printPredicate(inst->opcode, inst->pred);
unsigned i = 0;
/// Print opcode
if (opcode == ISA_FMINMAX)
{
CISA_MIN_MAX_SUB_OPCODE sub_opcode = (CISA_MIN_MAX_SUB_OPCODE)getPrimitiveOperand<uint8_t>(inst, i++);
sstr << (sub_opcode == CISA_DM_FMIN ? "min" : "max");
}
else
{
sstr << ISA_Inst_Table[opcode].str;
}
if (ISA_Inst_Sync != ISA_Inst_Table[opcode].type)
{
unsigned int Count = inst->opnd_count;
if (ISA_Inst_Compare == ISA_Inst_Table[opcode].type)
{
uint8_t relOp = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << (((relOp >> 7) & 0x1) ? "n" : ""); /// INFO: cmpn opcode print support here.
sstr << "." << Rel_op_str[(unsigned)(relOp & 0x7)];
}
bool showRegion = true;
if (ISA_Inst_Arith == ISA_Inst_Table[opcode].type ||
ISA_Inst_Mov == ISA_Inst_Table[opcode].type ||
ISA_Inst_Logic == ISA_Inst_Table[opcode].type ||
ISA_Inst_Address == ISA_Inst_Table[opcode].type ||
ISA_Inst_Compare == ISA_Inst_Table[opcode].type)
{
bool saturate = (((VISA_Modifier)((getVectorOperand(inst, i).tag >> 3 ) & 0x7)) == MODIFIER_SAT);
sstr << (saturate ? ".sat" : "");
}
sstr << " " << printExecutionSize(inst->opcode, inst->execsize, isaHeader);
if (opcode == ISA_GOTO)
{
uint16_t label_id = getPrimitiveOperand<uint16_t>(inst, i++);
sstr << " " << header->strings[header->labels[label_id].name_index];
}
for (; i < Count; i++)
{
if (opcode == ISA_ADDR_ADD && i == 1) /// Only for src0 of addr_add
{
const vector_opnd& curOpnd = getVectorOperand(inst, i);
if(curOpnd.getOperandClass() == OPERAND_ADDRESS)
{
sstr << printVectorOperand(isaHeader, header, curOpnd, opt, showRegion);
}
else
{
sstr << " " << Common_ISA_Get_Modifier_Name((VISA_Modifier)((curOpnd.tag >> 3) & 0x7));
unsigned opnd_index = curOpnd.getOperandIndex();
if(curOpnd.getOperandClass() == OPERAND_GENERAL)
{
uint32_t numPredefined = Get_CISA_PreDefined_Var_Count(isaHeader.major_version, isaHeader.minor_version);
VISA_Type type = opnd_index < numPredefined ? getPredefinedVarType(mapExternalToInternalPreDefVar(opnd_index, isaHeader.major_version, isaHeader.minor_version)) :
header->variables[opnd_index - numPredefined].getType();
int offset = curOpnd.opnd_val.gen_opnd.col_offset *
CISATypeTable[type].typeSize +
curOpnd.opnd_val.gen_opnd.row_offset * G4_GRF_REG_NBYTES;
sstr << "&" << printVariableDeclName(isaHeader, header, opnd_index, opt) << "+"
<< offset;
}
else if (curOpnd.getOperandClass() == OPERAND_STATE)
{
auto OpClass = curOpnd.getStateOpClass();
sstr << "&" << printVariableDeclName(isaHeader, header, opnd_index, opt, OpClass) << "+"
<< curOpnd.opnd_val.state_opnd.offset *
CISATypeTable[ISA_TYPE_D].typeSize;
}
else
{
/// TODO: Should we just assert here? Is this allowed?
sstr << printOperand(isaHeader, header, inst, i, opt);
}
}
}
else
{
sstr << printOperand(isaHeader, header, inst, i, opt);
}
}
}
else if (ISA_Inst_Sync == ISA_Inst_Table[opcode].type)
{
if (opcode == ISA_FENCE)
{
uint8_t mask = getPrimitiveOperand<uint8_t>(inst, i);
#define BTI_MASK 0x20 // bit 5
sstr << ((mask & BTI_MASK) ? "_local" : "_global");
if (mask != 0)
{
sstr << ".";
if (mask & 1) sstr << "E";
if (mask & (1 << 1)) sstr << "I";
if (mask & (1 << 2)) sstr << "S";
if (mask & (1 << 3)) sstr << "C";
if (mask & (1 << 4)) sstr << "R";
if (mask & (1 << 6)) sstr << "L1";
}
}
else if (opcode == ISA_WAIT)
{
sstr << printOperand(isaHeader, header, inst, 0, opt);
}
else if (opcode == ISA_PBARRIER) {
// mask operand
sstr << printOperand(isaHeader, header, inst, i++, opt);
// dst operand
sstr << printOperand(isaHeader, header, inst, i++, opt);
}
}
return sstr.str();
}
static string printInstructionControlFlow(const common_isa_header& isaHeader, const kernel_format_t* header, const CISA_INST* inst, Options *opt)
{
ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
unsigned i = 0;
uint16_t label_id = 0;
stringstream sstr;
if (ISA_SUBROUTINE == opcode || ISA_LABEL == opcode)
{
label_id = getPrimitiveOperand<uint16_t>(inst, i++);
sstr << endl;
switch (opcode)
{
case ISA_SUBROUTINE:
{
stringstream uniqueSuffixSstr; uniqueSuffixSstr << '_' << label_id;
string uniqueSuffixStr = uniqueSuffixSstr.str();
string labelName(header->strings[header->labels[label_id].name_index]);
sstr << ".function " << labelName << uniqueSuffixStr
<< "\n\n" << labelName << uniqueSuffixStr;
break;
}
case ISA_LABEL:
{
sstr << header->strings[header->labels[label_id].name_index];
break;
}
default:
break; // Prevent gcc warning
}
sstr << ":";
}
else
{
sstr << printPredicate(inst->opcode, inst->pred)
<< ISA_Inst_Table[opcode].str
<< " "
<< printExecutionSize(inst->opcode, inst->execsize, isaHeader);
switch (opcode)
{
case ISA_JMP:
case ISA_CALL:
case ISA_GOTO:
case ISA_FCALL:
{
if (opcode == ISA_JMP ||
opcode == ISA_CALL ||
opcode == ISA_GOTO ||
opcode == ISA_FCALL)
{
/// label / function id to jump / call to.
label_id = getPrimitiveOperand<uint16_t>(inst, i++);
if (opcode == ISA_FCALL)
{
sstr << " " << (unsigned) label_id;
}
else
{
sstr << " " << header->strings[header->labels[label_id].name_index];
if (header->labels[label_id].kind == LABEL_SUBROUTINE) sstr << "_" << label_id;
}
}
if (opcode == ISA_FCALL)
{
/// arg size
sstr << " " << getPrimitiveOperand<unsigned>(inst, i++);
/// return size
sstr << " " << getPrimitiveOperand<unsigned>(inst, i++);
}
break;
}
case ISA_SWITCHJMP:
{
/// skip num_labels
i++;
/// index
sstr << printOperand(isaHeader, header, inst, i++, opt);
sstr << " (";
for (bool first = true; i < inst->opnd_count; i++)
{
if (!first) { sstr << ", "; }
label_id = getPrimitiveOperand<uint16_t>(inst, i);
sstr << header->strings[header->labels[label_id].name_index];
if (first) { first = false; }
}
sstr << ")";
break;
}
default:
break; // Prevent gcc warning
}
}
return sstr.str();
}
static string printInstructionMisc(const common_isa_header& isaHeader, const kernel_format_t* header, const CISA_INST* inst, Options *opt)
{
ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
unsigned i = 0;
stringstream sstr;
if (opcode == ISA_3D_URB_WRITE)
{
sstr << printPredicate(inst->opcode, inst->pred);
}
switch (opcode)
{
case ISA_FILE:
{
uint32_t filename_index = getPrimitiveOperand<uint32_t>(inst, i++);
sstr << "FILE " << header->strings[filename_index];
break;
}
case ISA_LOC:
{
unsigned line_number = getPrimitiveOperand<unsigned>(inst, i++);
sstr << "LOC " << line_number;
break;
}
case ISA_RAW_SEND:
{
uint8_t modifiers = inst->modifier;
i++; // skip the modifier
uint32_t exMsgDesc = getPrimitiveOperand<uint32_t>(inst, i++); //32b
uint8_t numSrc = getPrimitiveOperand<uint8_t>(inst, i++);
uint8_t numDst = getPrimitiveOperand<uint8_t>(inst, i++);
string opstring = modifiers == 1? "raw_sendc " : "raw_send ";
sstr << printPredicate(inst->opcode, inst->pred)
<< opstring.c_str()
<< printExecutionSize(inst->opcode, inst->execsize, isaHeader)
<< " "
<< "0x" << std::hex << (uint32_t)exMsgDesc << std::dec
<< " "
<< (unsigned)numSrc
<< " "
<< (unsigned)numDst
<< " ";
/// desc
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// src
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case ISA_RAW_SENDS:
{
uint8_t modifiers = inst->modifier;
i++; // skip the modifier
uint8_t numSrc0 = getPrimitiveOperand<uint8_t>(inst, i++);
uint8_t numSrc1 = getPrimitiveOperand<uint8_t>(inst, i++);
uint8_t numDst = getPrimitiveOperand<uint8_t>(inst, i++);
string opstring = modifiers == 1? "raw_sendsc." : "raw_sends.";
sstr << printPredicate(inst->opcode, inst->pred)
<< opstring.c_str();
if (getVersionAsInt(isaHeader.major_version, isaHeader.minor_version) >
getVersionAsInt(3, 5))
{
uint8_t ffid = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << (unsigned)ffid
<< ".";
}
sstr << (unsigned)numSrc0
<< "."
<< (unsigned)numSrc1
<< "."
<< (unsigned)numDst
<< " "
<< printExecutionSize(inst->opcode, inst->execsize, isaHeader)
<< " ";
/// exMsgDesc: could be imm or vector
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// desc
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// src0
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// src1
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case ISA_VME_FBR:
{
/// My typical pattern of printing these things doesn't work here since
/// these VME instructions weirdly put the surface as the third operand.
stringstream sstr1;
/// uni input
sstr1 << printOperand(isaHeader, header, inst, i++, opt);
/// fbr input
sstr1 << printOperand(isaHeader, header, inst, i++, opt);
uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
stringstream sstr2;
sstr2 << " T"
<< (unsigned)surface
<< " "
<< sstr1.str();
sstr << ISA_Inst_Table[opcode].str << " (";
/// FBRMbMode
sstr << printOperand(isaHeader, header, inst, i++, opt); sstr << ",";
/// FBRSubMbShape
sstr << printOperand(isaHeader, header, inst, i++, opt); sstr << ",";
/// FBRSubPredMode
sstr << printOperand(isaHeader, header, inst, i++, opt);
sstr << ")";
/// vme output
sstr2 << printOperand(isaHeader, header, inst, i++, opt);
sstr << sstr2.str();
break;
}
case ISA_VME_IME:
{
uint8_t streamMode = getPrimitiveOperand<uint8_t>(inst, i++);
uint8_t searchCtrl = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << ISA_Inst_Table[opcode].str
<< "(" << (unsigned)streamMode
<< "," << (unsigned)searchCtrl
<< ")";
stringstream sstr1;
/// uni imput
sstr1 << printOperand(isaHeader, header, inst, i++, opt);
/// ime input
sstr1 << printOperand(isaHeader, header, inst, i++, opt);
uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << " T" << (unsigned)surface << " " << sstr1.str();
/// ref0
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// ref1
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// cost center
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// vme output
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case ISA_VME_SIC:
{
/// My typical pattern of printing these things doesn't work here since
/// these VME instructions weirdly put the surface as the third operand.
stringstream sstr1;
/// uni input
sstr1 << printOperand(isaHeader, header, inst, i++, opt);
/// sic input
sstr1 << printOperand(isaHeader, header, inst, i++, opt);
uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << ISA_Inst_Table[opcode].str
<< " T"
<< (unsigned)surface
<< " "
<< sstr1.str();
/// vme output
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case ISA_VME_IDM:
{
/// My typical pattern of printing these things doesn't work here since
/// these VME instructions weirdly put the surface as the third operand.
stringstream sstr1;
/// uni input
sstr1 << printOperand(isaHeader, header, inst, i++, opt);
/// sic input
sstr1 << printOperand(isaHeader, header, inst, i++, opt);
uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << ISA_Inst_Table[opcode].str
<< " T"
<< (unsigned)surface
<< " "
<< sstr1.str();
/// vme output
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case ISA_3D_URB_WRITE:
{
sstr << ISA_Inst_Table[opcode].str;
sstr << " " << printExecutionSize(inst->opcode, inst->execsize, isaHeader);
// num out
sstr << " " << printOperand(isaHeader, header, inst, i++, opt);
// channel mask
// FIXME: change the order of channel mask and global offset in vISA binary
std::string channelMask = printOperand(isaHeader, header, inst, i++, opt);
// global offset
sstr << " " << printOperand(isaHeader, header, inst, i++, opt);
sstr << channelMask;
// urb handle
sstr << printOperand(isaHeader, header, inst, i++, opt);
// per slot offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
// vertex data
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case ISA_LIFETIME:
{
uint8_t properties = getPrimitiveOperand<uint8_t>(inst, i++);
uint32_t varId = getPrimitiveOperand<uint32_t>(inst, i++);
sstr << ISA_Inst_Table[opcode].str;
sstr << ".";
if((VISAVarLifetime)(properties & 1) == LIFETIME_START)
{
sstr << "start ";
}
else
{
sstr << "end ";
}
// Since variable id is in non-standard form, we cannot invoke
// printOperand directly on it
unsigned char type = (properties >> 4) & 0x3;
if(type == OPERAND_GENERAL)
{
// General variable
sstr << printVariableDeclName(isaHeader, header, varId, opt, NOT_A_STATE_OPND);
}
else if(type == OPERAND_ADDRESS)
{
// Address variable
sstr << "A" << varId;
}
else if(type == OPERAND_PREDICATE)
{
// Predicate variable
sstr << "P" << varId;
}
break;
}
default:
{
ASSERT_USER(0, "Unimplemented or Illegal Misc Opcode.");
}
}
return sstr.str();
}
// For 3D sampler instructions, subOpcode, pixel null mask and CPS LOD
// compensation enable share the same byte:
//
// Bit 0-4: subOpcode
// Bit 5: pixelNullMask
// Bit 6: cpsEnable
//
static VISA3DSamplerOp
getSubOpcodeByte(const CISA_INST* inst, unsigned i)
{
uint8_t val = getPrimitiveOperand<uint8_t>(inst, i);
return VISA3DSamplerOp::extractSamplerOp(val);
}
static string printInstructionSampler(const common_isa_header& isaHeader, const kernel_format_t* header, const CISA_INST* inst, Options *opt)
{
stringstream sstr;
ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
if (opcode == ISA_3D_SAMPLE || opcode == ISA_3D_LOAD || opcode == ISA_3D_GATHER4)
{
sstr << printPredicate(inst->opcode, inst->pred);
}
unsigned i = 0;
switch (opcode)
{
case ISA_LOAD:
case ISA_SAMPLE:
{
uint8_t mod = getPrimitiveOperand<uint8_t>(inst, i++);
uint8_t sampler = 0;
if (opcode == ISA_SAMPLE)
sampler = getPrimitiveOperand<uint8_t>(inst, i++);
uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
uint8_t channel = (mod ) & 0xF;
uint8_t SIMD_mode = (mod >> 4) & 0x3;
if((unsigned)SIMD_mode == 0)
{
SIMD_mode = 8;
}
else if((unsigned)SIMD_mode == 1)
{
SIMD_mode = 16;
}
sstr << ISA_Inst_Table[opcode].str
<< "."
<< channel_mask_str[channel]
<< " ("
<< (unsigned)SIMD_mode
<< ")";
if (opcode == ISA_SAMPLE)
sstr << " S" << (unsigned)sampler;
sstr << " T"
<< (unsigned)surface;
/// u offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// v offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// r offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case ISA_3D_SAMPLE:
{
// [(P)] SAMPLE_3d[.pixel_null_mask][.cps][.divS].<channels> (exec_size)
// [(u_aoffimmi, v_aoffimii, r_aoffimmi)] <sampler> <surface>
// <dst> <u> <v> <r> <ai>
auto subop = getSubOpcodeByte(inst, i++);
sstr << SAMPLE_OP_3D_NAME[subop.opcode] << ".";
// Print the pixel null mask if it is enabled.
if (subop.pixelNullMask)
{
sstr << "pixel_null_mask.";
}
// Print CPS LOD compensation if it is enabled.
// The last '.' is for the channels.
if (subop.cpsEnable)
{
sstr << "cps.";
}
if (subop.nonUniformSampler)
{
sstr << "divS.";
}
uint8_t channels = getPrimitiveOperand<uint8_t>(inst, i++);
if( channels & 0x1) sstr << "R";
if( channels & 0x2) sstr << "G";
if( channels & 0x4) sstr << "B";
if( channels & 0x8) sstr << "A";
sstr << " " << printExecutionSize(inst->opcode, inst->execsize, isaHeader) << " ";
sstr << printOperand(isaHeader, header, inst, i++, opt);
// sampler
sstr << " S" << printOperand(isaHeader, header, inst, i++, opt);
// surface
sstr << " T" << printOperand(isaHeader, header, inst, i++, opt);
// dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
// skip the param count
i++;
while (i < inst->opnd_count)
{
sstr << printOperand(isaHeader, header, inst, i++, opt);
}
break;
}
case ISA_3D_LOAD:
{
auto subop = getSubOpcodeByte(inst, i++);
sstr << SAMPLE_OP_3D_NAME[subop.opcode] << ".";
// Print the pixel null mask if it is enabled.
// The last '.' is for the channels.
if (subop.pixelNullMask)
{
sstr << "pixel_null_mask.";
}
uint8_t channels = getPrimitiveOperand<uint8_t>(inst, i++);
if( channels & 0x1) sstr << "R";
if( channels & 0x2) sstr << "G";
if( channels & 0x4) sstr << "B";
if( channels & 0x8) sstr << "A";
sstr << " " << printExecutionSize(inst->opcode, inst->execsize, isaHeader) << " ";
sstr << printOperand(isaHeader, header, inst, i++, opt);
// surface
sstr << " T" << printOperand(isaHeader, header, inst, i++, opt);
// dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
// skip the param count
i++;
while (i < inst->opnd_count)
{
sstr << printOperand(isaHeader, header, inst, i++, opt);
}
break;
}
case ISA_3D_GATHER4:
{
auto subop = getSubOpcodeByte(inst, i++);
sstr << SAMPLE_OP_3D_NAME[subop.opcode] << ".";
// Print the pixel null mask if it is enabled.
// The last '.' is for the channels.
if (subop.pixelNullMask)
{
sstr << "pixel_null_mask.";
}
uint8_t channels = getPrimitiveOperand<uint8_t>(inst, i++);
if (channels == 0x0)
{
sstr << "R";
}
else if (channels == 0x1)
{
sstr << "G";
}
else if (channels == 0x2)
{
sstr << "B";
}
else if (channels == 0x3)
{
sstr << "A";
}
else
{
sstr << "illegal";
}
sstr << " " << printExecutionSize(inst->opcode, inst->execsize, isaHeader);
sstr << printOperand(isaHeader, header, inst, i++, opt);
// sampler
sstr << " S" << printOperand(isaHeader, header, inst, i++, opt);
// surface
sstr << " T" << printOperand(isaHeader, header, inst, i++, opt);
// dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
// skip the param count
i++;
while (i < inst->opnd_count)
{
sstr << printOperand(isaHeader, header, inst, i++, opt);
}
break;
}
case ISA_3D_INFO:
{
VISASampler3DSubOpCode subop = (VISASampler3DSubOpCode)getPrimitiveOperand<uint8_t>(inst, i++);
sstr << SAMPLE_OP_3D_NAME[subop];
sstr << " " << printExecutionSize(inst->opcode, inst->execsize, isaHeader) << " ";
if (subop == VISA_3D_RESINFO)
{
// channelMask
uint8_t channels = getPrimitiveOperand<uint8_t>(inst, i++);
ChannelMask chMask = ChannelMask::createFromBinary(ISA_3D_INFO, channels);
sstr << chMask.getString();
}
// surface
sstr << " T" << printOperand(isaHeader, header, inst, i++, opt);
if (subop == VISA_3D_RESINFO)
{
// lod
sstr << printOperand(isaHeader, header, inst, i++, opt);
}
// dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case ISA_SAMPLE_UNORM:
{
uint8_t channel = getPrimitiveOperand<uint8_t>(inst, i++);
uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << ISA_Inst_Table[opcode].str
<< "."
<< channel_mask_str[(channel & 0xf)]
<< "."
<< sampler_channel_output_str[ChannelMask::getChannelOutputFormat(channel)]
<< " S"
<< (unsigned)sampler
<< " T"
<< (unsigned)surface;
/// u offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// v offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// deltaU
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// deltaV
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case ISA_AVS:
{
uint8_t channel = getPrimitiveOperand<uint8_t>(inst, i++);
uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << ISA_Inst_Table[opcode].str
<< "."
<< channel_mask_str[channel]
<< " T"
<< (unsigned)surface
<< " S"
<< (unsigned)sampler;
/// u offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// v offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// delta u
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// delta v
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// u2d
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// groupID
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// verticalBlockNumber
sstr << printOperand(isaHeader, header, inst, i++, opt);
uint8_t cntrl = ((getPrimitiveOperand<uint8_t>(inst, i++)) & 0xF);
sstr << " "
<< avs_control_str[cntrl];
/// v2d
sstr << printOperand(isaHeader, header, inst, i++, opt);
uint8_t execMode = (getPrimitiveOperand<uint8_t>(inst, i++) & 0xF);
sstr << " "
<< avs_exec_mode[execMode];
// eifbypass
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case ISA_VA:
{
ISA_VA_Sub_Opcode subOpcode = (ISA_VA_Sub_Opcode)getPrimitiveOperand<uint8_t>(inst, i++);
switch (subOpcode)
{
case MINMAX_FOPCODE:
{
uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << ISA_Inst_Table[opcode].str
<< "."
<< va_sub_names[subOpcode]
<< " T" << (unsigned)surface;
/// u offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// v offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// mmf mode
if (getVectorOperand(inst, i).getOperandClass() == OPERAND_IMMEDIATE)
{
unsigned val = getVectorOperand(inst, i++).opnd_val.const_opnd._val.ival;
sstr << " " << mmf_enable_mode[val];
}
else
{
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// User "CM_VAR_ENABLE" instead ???
}
/// dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case MINMAXFILTER_FOPCODE:
{
uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << ISA_Inst_Table[opcode].str
<< "."
<< va_sub_names[subOpcode]
<< " T" << (unsigned)surface
<< " S" << (unsigned)sampler;
/// u offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// v offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
uint8_t cntrl = ((getPrimitiveOperand<uint8_t>(inst, i++)) & 0xF);
uint8_t execMode = ((getPrimitiveOperand<uint8_t>(inst, i++)) & 0xF);
sstr << " "
<< avs_control_str [ cntrl ]
<< " "
<< mmf_exec_mode [ execMode ];
/// mmf mode
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case BoolCentroid_FOPCODE:
case Centroid_FOPCODE:
{
uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << ISA_Inst_Table[opcode].str
<< "."
<< va_sub_names[subOpcode]
<< " T" << (unsigned)surface;
/// u offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// v offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// v size
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// h size
if (subOpcode == BoolCentroid_FOPCODE)
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case Convolve_FOPCODE:
case Dilate_FOPCODE:
case ERODE_FOPCODE:
{
uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << ISA_Inst_Table[opcode].str
<< "."
<< va_sub_names[subOpcode]
<< " T" << (unsigned)surface
<< " S" << (unsigned)sampler;
/// u offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// v offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
uint8_t execMode = getPrimitiveOperand<uint8_t>(inst, i ) & 0x3;
uint8_t regionSize = (getPrimitiveOperand<uint8_t>(inst, i++) & 0xC) >> 0x2;
sstr << " "
<< (Convolve_FOPCODE == subOpcode ?
conv_exec_mode [execMode] :
ed_exec_mode [execMode] );
if (Convolve_FOPCODE == subOpcode)
sstr << " " << (regionSize & 0x1 ? "31x31" : "15x15");
/// dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
default:
ASSERT_USER(false, "Invalid VA sub-opcode");
}
break;
}
case ISA_VA_SKL_PLUS:
{
ISA_VA_Sub_Opcode subOpcode = (ISA_VA_Sub_Opcode)getPrimitiveOperand<uint8_t>(inst, i++);
switch (subOpcode)
{
case VA_OP_CODE_LBP_CORRELATION:
{
uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << ISA_Inst_Table[opcode].str
<< "."
<< va_sub_names[subOpcode]
<< " T" << (unsigned)surface;
/// u offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// v offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// disparity
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case VA_OP_CODE_1PIXEL_CONVOLVE:
case VA_OP_CODE_1D_CONVOLVE_VERTICAL:
case VA_OP_CODE_1D_CONVOLVE_HORIZONTAL:
{
uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << ISA_Inst_Table[opcode].str
<< "."
<< va_sub_names[subOpcode]
<< " T" << (unsigned)surface
<< " S" << (unsigned)sampler;
/// u offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// v offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
uint8_t mode = ((getPrimitiveOperand<uint8_t>(inst, i++)) & 0xF);
switch (mode & 0x3)
{
case 0: sstr << " 4x16"; break;
case 2: sstr << " 1x16"; break;
case 3: sstr << " 1x1"; break;
}
/// offsets
if (subOpcode == VA_OP_CODE_1PIXEL_CONVOLVE)
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case VA_OP_CODE_LBP_CREATION:
{
uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << ISA_Inst_Table[opcode].str
<< "."
<< va_sub_names[subOpcode]
<< " T" << (unsigned)surface;
/// u offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// v offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
uint8_t mode = ((getPrimitiveOperand<uint8_t>(inst, i++)) & 0xF);
sstr << " " << lbp_creation_mode[(int)mode];
/// dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case VA_OP_CODE_FLOOD_FILL:
{
uint8_t is8Connect = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << ISA_Inst_Table[opcode].str
<< "."
<< va_sub_names[subOpcode]
<< " " << (is8Connect & 0x1 ? "8_connect" : "4_connect");
/// pixel mask h direction
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// pixel mask v left direction
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// pixel mask v right direction
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// loop count
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case VA_OP_CODE_CORRELATION_SEARCH:
{
uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << ISA_Inst_Table[opcode].str
<< "."
<< va_sub_names[subOpcode]
<< " T" << (unsigned)surface;
/// u offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// v offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// vertical origin
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// horizontal origin
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// x direction size
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// y direction size
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// x direction search size
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// y direction search size
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case ISA_HDC_CONV:
case ISA_HDC_ERODE:
case ISA_HDC_DILATE:
case ISA_HDC_LBPCORRELATION:
case ISA_HDC_LBPCREATION:
case ISA_HDC_MMF:
case ISA_HDC_1PIXELCONV:
case ISA_HDC_1DCONV_H:
case ISA_HDC_1DCONV_V:
{
sstr << ISA_Inst_Table[opcode].str
<< "."
<< va_sub_names[subOpcode];
if (subOpcode != ISA_HDC_LBPCORRELATION &&
subOpcode != ISA_HDC_LBPCREATION)
{
uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << " T" << (unsigned)surface
<< " S" << (unsigned)sampler;
}
else
{
/// surface
uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << " T" << (unsigned)surface;
}
/// u offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// v offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
if (subOpcode == ISA_HDC_CONV ||
subOpcode == ISA_HDC_MMF ||
subOpcode == ISA_HDC_1PIXELCONV ||
subOpcode == ISA_HDC_1DCONV_H ||
subOpcode == ISA_HDC_1DCONV_V)
{
//pixel size
uint8_t pixel_size = getPrimitiveOperand<uint8_t>(inst, i++);
int isBigKernel = 0;
if (subOpcode == ISA_HDC_CONV)
{
isBigKernel = (pixel_size & ( 1 << 4 ));
pixel_size = pixel_size & 0xF;
}
sstr << " " << pixel_size_str[pixel_size];
if (subOpcode == ISA_HDC_CONV && isBigKernel)
{
sstr << " 31x31";
}
else if (subOpcode == ISA_HDC_CONV && !isBigKernel)
{
sstr << " 15x15";
}
}
if (subOpcode == ISA_HDC_MMF)
{
//mode
uint8_t mode = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << " " << mmf_enable_mode[(int)mode];
}
if (subOpcode == ISA_HDC_LBPCREATION)
{
//mode
uint8_t mode = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << " " << lbp_creation_mode[(int)mode];
}
if (subOpcode == ISA_HDC_LBPCORRELATION)
{
/// disparity
sstr << printOperand(isaHeader, header, inst, i++, opt);
}
if (subOpcode == ISA_HDC_1PIXELCONV)
{
/// offsets
sstr << printOperand(isaHeader, header, inst, i++, opt);
}
/// dst surface
uint8_t dst_surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << " T" << (unsigned)dst_surface;
/// x offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// y offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
default:
ASSERT_USER(false, "Invalid VA sub-opcode");
}
break;
}
default: ASSERT_USER( false, "illegal opcode for sampler instruction");
}
return sstr.str();
}
static string printSurfaceIndex(const common_isa_header & isaHeader, uint8_t surface)
{
stringstream sstr;
unsigned numPreDefinedSurfs = Get_CISA_PreDefined_Surf_Count(isaHeader.major_version, isaHeader.minor_version);
if (surface < numPreDefinedSurfs)
{
sstr << " " << vISAPreDefSurf[surface].name;
}
else
{
sstr << " " << "T" << (unsigned)surface;
}
return sstr.str();
}
static string printInstructionDataport(const common_isa_header& isaHeader, const kernel_format_t* header, const CISA_INST* inst, Options *opt)
{
ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
unsigned i = 0;
uint8_t surface = 0;
uint8_t modifier = 0;
stringstream sstr;
switch (opcode) {
default:
break;
case ISA_3D_RT_WRITE:
case ISA_GATHER4_SCALED:
case ISA_SCATTER4_SCALED:
case ISA_STRBUFLD_SCALED:
case ISA_STRBUFST_SCALED:
case ISA_GATHER_SCALED:
case ISA_SCATTER_SCALED:
case ISA_DWORD_ATOMIC:
case ISA_3D_TYPED_ATOMIC:
sstr << printPredicate(inst->opcode, inst->pred);
break;
}
sstr << ISA_Inst_Table[opcode].str;
switch (opcode)
{
case ISA_MEDIA_ST:
case ISA_MEDIA_LD:
case ISA_TRANSPOSE_LD:
{
uint8_t plane = 0;
uint8_t block_width = 0;
uint8_t block_height = 0;
if (ISA_MEDIA_LD == opcode || ISA_MEDIA_ST == opcode)
{
modifier = getPrimitiveOperand<uint8_t>(inst, i++); //inst->modifier;
}
surface = getPrimitiveOperand<uint8_t>(inst, i++);
if (ISA_MEDIA_LD == opcode || ISA_MEDIA_ST == opcode)
{
plane = getPrimitiveOperand<uint8_t>(inst, i++);
}
if (opcode == ISA_MEDIA_LD) sstr << "." << media_ld_mod_str[modifier];
if (opcode == ISA_MEDIA_ST) sstr << "." << media_st_mod_str[modifier];
if (opcode != ISA_TRANSPOSE_LD)
{
sstr << " (";
block_width = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << (unsigned)block_width;
sstr << ",";
block_height = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << (unsigned)block_height;
sstr << ")";
}
else
{
sstr << " (";
block_width = Transpose_Read_Block_size[getPrimitiveOperand<uint8_t>(inst, i++)];
sstr << (unsigned)block_width;
sstr << ",";
block_height = Transpose_Read_Block_size[getPrimitiveOperand<uint8_t>(inst, i++)];
sstr << (unsigned)block_height;
sstr << ")";
}
sstr << " T" << (unsigned)surface;
if (opcode != ISA_TRANSPOSE_LD)
sstr << " " << (unsigned)plane;
/// x offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// y offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// message operand (src or dst)
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case ISA_OWORD_ST:
case ISA_OWORD_LD:
case ISA_OWORD_LD_UNALIGNED:
{
uint8_t size = getPrimitiveOperand<uint8_t>(inst, i++);
size = size & 0x7;
unsigned num_oword = Get_Common_ISA_Oword_Num((Common_ISA_Oword_Num)size);
if (ISA_OWORD_ST != opcode)
{
modifier = getPrimitiveOperand<uint8_t>(inst, i++);
if (modifier & 0x1) sstr << ".mod";
}
sstr << " (" << num_oword << ")";
surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << printSurfaceIndex(isaHeader, surface);
/// offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// message operand (src or dst)
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case ISA_GATHER:
case ISA_SCATTER:
{
uint8_t elt_size = 0;
uint8_t num_elts = 0;
elt_size = getPrimitiveOperand<uint8_t>(inst, i++);
elt_size = elt_size & 0x3;
switch((GATHER_SCATTER_ELEMENT_SIZE)elt_size)
{
case GATHER_SCATTER_BYTE:
elt_size = 1;
break;
case GATHER_SCATTER_WORD:
elt_size = 2;
break;
case GATHER_SCATTER_DWORD:
elt_size = 4;
break;
default:
ASSERT_USER( 0, "Incorrect element size for Gather/Scatter CISA inst." );
break;
}
if (ISA_GATHER == opcode)
{
modifier = getPrimitiveOperand<uint8_t>(inst, i++);
}
num_elts = getPrimitiveOperand<uint8_t>(inst, i++);
// modifier
if ( ISA_GATHER == opcode && modifier & 0x1 )
{
sstr << ".mod";
}
// num_elts
sstr << "." << (unsigned)elt_size;
// execution size
sstr << " " << printExecutionSizeForScatterGather(num_elts, isaHeader);
// modifier
if (ISA_GATHER == opcode && modifier & 0x1)
{
sstr << ".mod";
}
//surface
surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << printSurfaceIndex(isaHeader, surface);
/// global offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// element offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// message operand (src or dst)
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case ISA_GATHER4:
case ISA_SCATTER4:
{
uint8_t ch_mask = 0;
uint8_t num_elts = 0;
ch_mask = getPrimitiveOperand<uint8_t>(inst, i++);
ch_mask = ch_mask & 0xF;
if (ISA_GATHER4 == opcode)
{
modifier = getPrimitiveOperand<uint8_t>(inst, i++);
}
num_elts = getPrimitiveOperand<uint8_t>(inst, i++);
// channel mask
sstr << "." << channel_mask_slm_str[ch_mask];
// num_elts
sstr << " " << printExecutionSizeForScatterGather(num_elts, isaHeader);
// modifier
if (ISA_GATHER4 == opcode && modifier & 0x1)
{
sstr << ".mod";
}
//surface
surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << printSurfaceIndex(isaHeader, surface);
/// global offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// element offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// message operand (src or dst)
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case ISA_SCATTER_ATOMIC:
{
uint8_t num_elts = 0;
CMAtomicOperations op
= static_cast<CMAtomicOperations>(getPrimitiveOperand<uint8_t>(inst, i++));
/// TODO: Need platform information for this to work.
sstr << "." << CISAAtomicOpNames[op];
num_elts = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << " " << printExecutionSizeForScatterGather(num_elts, isaHeader);
surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << printSurfaceIndex(isaHeader, surface);
/// global offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// element offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// DWORD_ATOMIC is wierd and has the text version
/// putting the dst operand before the src operands.
stringstream sstr1;
/// src0
sstr1 << printOperand(isaHeader, header, inst, i++, opt);
/// src1
sstr1 << printOperand(isaHeader, header, inst, i++, opt);
/// message operand (src or dst)
sstr << printOperand(isaHeader, header, inst, i++, opt);
sstr << sstr1.str();
break;
}
case ISA_GATHER4_TYPED:
case ISA_SCATTER4_TYPED:
{
ChannelMask chMask = ChannelMask::createFromBinary(opcode,
getPrimitiveOperand<uint8_t>(inst, i++));
sstr << "." << chMask.getString();
sstr << " " << printExecutionSize(inst->opcode, inst->execsize, isaHeader);
surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << printSurfaceIndex(isaHeader, surface);
/// u offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// v offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// r offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// lod
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// message operand (src or dst)
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case ISA_GATHER4_SCALED:
case ISA_SCATTER4_SCALED:
{
ChannelMask chMask = ChannelMask::createFromBinary(opcode,
getPrimitiveOperand<uint8_t>(inst, i++));
sstr << "." << chMask.getString();
// ignore scale which must be 0
(void) getPrimitiveOperand<uint8_t>(inst, i++);
sstr << " " << printExecutionSize(inst->opcode, inst->execsize, isaHeader);
/// surface
surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << printSurfaceIndex(isaHeader, surface);
/// global offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// offsets
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// src/dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case ISA_STRBUFLD_SCALED:
case ISA_STRBUFST_SCALED:
{
ChannelMask chMask = ChannelMask::createFromBinary(opcode,
getPrimitiveOperand<uint8_t>(inst, i++));
sstr << "." << chMask.getString();
sstr << " " << printExecutionSize(inst->opcode, inst->execsize, isaHeader);
/// surface
surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << printSurfaceIndex(isaHeader, surface);
/// U offsets
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// V offsets
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// src/dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case ISA_GATHER_SCALED:
case ISA_SCATTER_SCALED:
{
Common_ISA_SVM_Block_Type blockSize;
Common_ISA_SVM_Block_Num numBlocks;
blockSize = static_cast<Common_ISA_SVM_Block_Type>(getPrimitiveOperand<uint8_t>(inst, i++));
numBlocks = static_cast<Common_ISA_SVM_Block_Num>(getPrimitiveOperand<uint8_t>(inst, i++));
// ignore scale (MBZ)
(void) getPrimitiveOperand<uint8_t>(inst, i++);
sstr << "." << Get_Common_ISA_SVM_Block_Num(numBlocks);
sstr << " " << printExecutionSize(inst->opcode, inst->execsize, isaHeader);
/// surface
surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << printSurfaceIndex(isaHeader, surface);
/// global offset
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// offsets
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// src/dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case ISA_3D_RT_WRITE:
{
// mode
uint16_t mode = getPrimitiveOperand<uint16_t>(inst, i++);
uint8_t surface;
if( ( mode ) != 0 )
{
sstr << ".";
if (mode & (0x1 << 2)) sstr << "<RTI>";
if( mode & (0x1 << 0x3)) sstr << "<A>";
if( mode & (0x1 << 0x4)) sstr << "<O>";
if( mode & (0x1 << 0x5)) sstr << "<Z>";
if( mode & (0x1 << 0x6)) sstr << "<ST>";
if( mode & (0x1 << 0x7)) sstr << "<LRTW>";
if( mode & (0x1 << 0x8)) sstr << "<CPS>";
if( mode & (0x1 << 0x9)) sstr << "<PS>";
if( mode & (0x1 << 0x10)) sstr << "<CM>";
if (mode & (0x1 << 0x11)) sstr << "<SI>";
}
sstr << " " << printExecutionSize(inst->opcode, inst->execsize, isaHeader) << " ";
// surface
surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << printSurfaceIndex(isaHeader, surface);
while (i < inst->opnd_count)
{
sstr << printOperand(isaHeader, header, inst, i++, opt);
}
break;
}
case ISA_DWORD_ATOMIC: {
printAtomicSubOpc(sstr, getPrimitiveOperand<uint8_t>(inst, i++));
sstr << " " << printExecutionSize(inst->opcode, inst->execsize, isaHeader);
/// surface
surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << printSurfaceIndex(isaHeader, surface);
/// offsets
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// src0
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// src1
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
case ISA_3D_TYPED_ATOMIC:
{
printAtomicSubOpc(sstr, getPrimitiveOperand<uint8_t>(inst, i++));
sstr << " " << printExecutionSize(inst->opcode, inst->execsize, isaHeader);
/// surface
surface = getPrimitiveOperand<uint8_t>(inst, i++);
sstr << printSurfaceIndex(isaHeader, surface);
/// u
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// v
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// r
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// lod
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// src0
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// src1
sstr << printOperand(isaHeader, header, inst, i++, opt);
/// dst
sstr << printOperand(isaHeader, header, inst, i++, opt);
break;
}
default:
{
ASSERT_USER(false, "Unimplemented or Illegal DataPort Opcode.");
}
}
return sstr.str();
}
extern string printKernelHeader(const common_isa_header& isaHeader, const kernel_format_t* header, bool isKernel, int funcionId, Options *options)
{
stringstream sstr;
uint8_t major_version = isaHeader.major_version;
uint8_t minor_version = isaHeader.minor_version;
sstr << ".version " << (unsigned)(major_version) << "." << (unsigned)(minor_version) << endl;
std::string name = header->strings[header->name_index];
std::replace_if(name.begin(), name.end(), [] (char c) { return c == '.'; } , ' ');
sstr << (!isKernel ? ".global_function " : ".kernel ") << name << endl;
if (!isKernel)
{
sstr << ".resolvedIndex " << funcionId << endl;
}
/// Print all the resolved function callee name decls before the kernel.
if (isKernel)
for (unsigned i = 0; i < isaHeader.num_functions; i++)
{
sstr << endl << ".funcdecl " << isaHeader.functions[i].name << " " << i;
}
// emit filescope var decls
for (unsigned i = 0; i < isaHeader.num_global_variables; i++)
{
filescope_var_info_t curVar = isaHeader.filescope_variables[i];
VISA_Type type_bits;
VISA_Align align_bits;
type_bits = (VISA_Type)((curVar.bit_properties) & 0xF);
align_bits = (VISA_Align)((curVar.bit_properties >> 4) & 0x7);
stringstream sstr1;
if (options->getOption(vISA_DumpIsaVarNames) && curVar.name)
{
char varName[64 + 1];
memset(varName, 0, lengthOf(varName));
memcpy_s(varName, 65, curVar.name, (curVar.name_len <= lengthOf(varName) ? curVar.name_len : lengthOf(varName)));
sstr1 << varName;
}
else
{
sstr1 << " F" << i;
}
sstr << endl
<< ".decl "
<< sstr1.str()
<< " v_type=F"
<< " type=" << CISATypeTable[type_bits].typeName
<< " num_elts=" << curVar.num_elements;
if (align_bits != ALIGN_UNDEF)
sstr << " align=" << Common_ISA_Get_Align_Name(align_bits);
}
// emit var decls
//.decl V<#> name=<name> type=<type> num_elts=<num_elements> [align=<align>] [alias=(<alias_index>,<alias_offset>)]
for (unsigned i = 0; i < header->variable_count; i++)
{
sstr << endl << printVariableDecl(isaHeader, header, i, isKernel, funcionId, options);
}
for (unsigned i = 0; i < header->address_count; i++)
{
sstr << endl << printAddressDecl(isaHeader, header, i);
}
for (unsigned i = 0; i < header->predicate_count; i++)
{
// P0 is reserved; starting from P1 if there is predicate decl
sstr << endl << printPredicateDecl(isaHeader, header, i);
}
// sampler
for (unsigned i = 0; i < header->sampler_count; i++)
{
sstr << endl << ".decl S" << i << " v_type=S";
state_info_t* sampler = &header->samplers[i];
sstr << " num_elts=" << sampler->num_elements;
sstr << " v_name=" << header->strings[sampler->name_index];
for (unsigned j = 0; j < sampler->attribute_count; j++)
{
sstr << " " << printAttribute(&sampler->attributes[j], header);
}
}
unsigned numPreDefinedSurfs = Get_CISA_PreDefined_Surf_Count(major_version, minor_version);
for (unsigned i = 0; i < header->surface_count; i++)
{
sstr << endl << ".decl T" << i+numPreDefinedSurfs << " v_type=T";
state_info_t* surface = &header->surfaces[i];
sstr << " num_elts=" << surface->num_elements;
sstr << " v_name=" << header->strings[surface->name_index];
for (unsigned j = 0; j < surface->attribute_count; j++)
{
sstr << " " << printAttribute(&surface->attributes[j], header);
}
}
for (unsigned i = 0; i < header->vme_count; i++)
{
sstr << endl;
sstr << ".decl VME" << i;
sstr << " v_type=VME";
state_info_t* vme = &header->vmes[i];
sstr << " num_elts=" << vme->num_elements;
sstr << " v_name=" << header->strings[vme->name_index];
for (unsigned j = 0; j < vme->attribute_count; j++)
{
sstr << " " << printAttribute(&vme->attributes[j], header);
}
}
/// .inputs to kernel
for (unsigned i = 0; i < header->input_count; i++)
{
input_info_t* input = &header->inputs[i];
//sstr << endl << (!isKernel ? ".parameter " /* function */ : ".input " /* kernel */);
if (!isKernel)
{
sstr << endl << ".parameter " /* function */;
}
else if (!input->getImplicitKind())
{
sstr << endl << ".input " /* kernel */;
}
else
{
sstr << endl << input->getImplicitKindString() << " ";
}
if (options->getOption(vISA_DumpIsaVarNames) && INPUT_GENERAL == input->getInputClass())
{
sstr << getVarName(input->index, isaHeader, *header);
}
else
{
const char* Input_Class_String[] = { "V", "S", "T" };
sstr << Input_Class_String[input->getInputClass()] << input->index;
}
if (isKernel)
sstr << " offset=" << input->offset;
sstr << " size=" << input->size;
}
/// .return directive for functions
if (!isKernel)
{
VISA_Type isa_type = (VISA_Type)(header->return_type & 0xF);
sstr << endl << ".return " << CISATypeTable[isa_type].typeName;
}
bool isTargetSet = false;
for (unsigned i = 0; i < header->attribute_count; i++)
{
sstr << endl << printAttribute(&header->attributes[i], header, true);
if(strcmp(header->strings[header->attributes[i].nameIndex], "Target") == 0)
{
isTargetSet = true;
}
}
if(isTargetSet == false)
{
sstr << endl << ".kernel_attr Target=";
if(options->getTarget() == VISA_CM)
{
sstr << "cm";
}
else if(options->getTarget() == VISA_3D)
{
sstr << "3d";
}
else if(options->getTarget() == VISA_CS)
{
sstr << "cs";
}
else
{
MUST_BE_TRUE(false, "Invalid kernel target attribute.");
}
}
return sstr.str();
}
extern string printInstruction(const common_isa_header& isaHeader, const kernel_format_t* header, const CISA_INST* instruction, Options *opt)
{
stringstream sstr;
ISA_Opcode opcode = (ISA_Opcode)instruction->opcode;
if (opcode != ISA_LOC || !g_ignorelocs)
{
if (opcode != ISA_LABEL)
{
sstr << " ";
}
switch(ISA_Inst_Table[opcode].type)
{
case ISA_Inst_Mov:
case ISA_Inst_Sync:
case ISA_Inst_Arith:
case ISA_Inst_Logic:
case ISA_Inst_Compare:
case ISA_Inst_Address:
case ISA_Inst_SIMD_Flow: sstr << printInstructionCommon (isaHeader, header, instruction, opt); break;
case ISA_Inst_SVM: sstr << printInstructionSVM (isaHeader, header, instruction, opt); break;
case ISA_Inst_Flow: sstr << printInstructionControlFlow (isaHeader, header, instruction, opt); break;
case ISA_Inst_Misc: sstr << printInstructionMisc (isaHeader, header, instruction, opt); break;
case ISA_Inst_Sampler: sstr << printInstructionSampler (isaHeader, header, instruction, opt); break;
case ISA_Inst_Data_Port: sstr << printInstructionDataport (isaHeader, header, instruction, opt); break;
default:
{
sstr << "Illegal or unimplemented CISA instruction (opcode, type): ("
<< opcode << ", " << ISA_Inst_Table[opcode].type << ").";
MUST_BE_TRUE(false, sstr.str());
}
}
switch (opcode)
{
case ISA_LOC:
case ISA_SUBROUTINE:
case ISA_FILE:
case ISA_LABEL: break;
default:
{
stringstream sstr2;
if (g_prettyPrint)
for (int i = 0; i < (int)80 - (int)sstr.str().length(); i++)
sstr2 << ' ';
if (!g_noinstid)
sstr << sstr2.str() << " /// $" << instruction->id;
}
}
}
else
{
sstr << "";
}
return sstr.str();
}
static string printRoutine(const common_isa_header& isaHeader, const kernel_format_t* header, list<CISA_INST*>& instructions, bool isKernel, int funcionId, Options *options)
{
stringstream sstr;
sstr << printKernelHeader(isaHeader, header, isKernel, funcionId, options);
for (auto I = instructions.begin(), E = instructions.end(); I != E; I++)
{
CISA_INST* inst = *I;
if (((ISA_Opcode)inst->opcode) != ISA_LOC || !g_ignorelocs)
{
if (((ISA_Opcode)inst->opcode) != ISA_LABEL)
sstr << " ";
sstr << printInstruction(isaHeader, header, inst, options) << endl;
}
}
return sstr.str();
}
extern string printKernel(const common_isa_header& isaHeader, const kernel_format_t* header, list<CISA_INST*>& instructions, Options *opt)
{
return printRoutine(isaHeader, header, instructions, true, 0, opt);
}
extern string printFunction(const common_isa_header& isaHeader, const function_format_t* header, list<CISA_INST*>& instructions, int funcionId, Options *opt)
{
return printRoutine(isaHeader, header, instructions, false, funcionId, opt);
}
#endif // IS_RELEASE_DLL