#
###############
+# Basic header template for an instruction stub.
+header_template_stub = '''
+class $class_name : public $base_class
+{
+ public:
+ typedef $base_class Base;
+
+ $class_name(const Brig::BrigInstBase *ib, const BrigObject *obj)
+ : Base(ib, obj, "$opcode")
+ {
+ }
+
+ void execute(GPUDynInstPtr gpuDynInst);
+};
+
+'''
+
# Basic header template for an instruction with no template parameters.
header_template_nodt = '''
class $class_name : public $base_class
'SpecialInstNoSrc': header_template_nodt,
'SpecialInst1Src': header_template_nodt,
'SpecialInstNoSrcNoDest': '',
+ 'Stub': header_template_stub,
}
###############
###############
# exec function body
+exec_template_stub = '''
+void
+$class_name::execute(GPUDynInstPtr gpuDynInst)
+{
+ fatal("instruction unimplemented %s\\n", gpuDynInst->disassemble());
+}
+
+'''
exec_template_nodt_nosrc = '''
void
$class_name::execute(GPUDynInstPtr gpuDynInst)
'SpecialInstNoSrc': exec_template_nodt_nosrc,
'SpecialInst1Src': exec_template_nodt_1src,
'SpecialInstNoSrcNoDest': '',
+ 'Stub': exec_template_stub,
}
###############
base_class_base = re.sub(r'<.*>$', '', base_class)
header_code(header_templates[base_class_base])
- if base_class.startswith('SpecialInst'):
+ if base_class.startswith('SpecialInst') or base_class.startswith('Stub'):
exec_code(exec_templates[base_class_base])
elif base_class.startswith('ShiftInst'):
header_code(exec_template_shift)
gen('Xor', bit_types, 'src0 ^ src1')
gen('Bitselect', bit_types, '(src1 & src0) | (src2 & ~src0)')
-gen('Firstbit',bit_types, 'firstbit(src0)')
gen('Popcount', ('U32',), '__builtin_popcount(src0)', 'PopcountInst', \
('sourceType', ('B32', 'B64')))
# with magic instructions.
gen('Call', base_class='SpecialInstNoSrcNoDest')
+# Stubs for unimplemented instructions:
+# These may need to be implemented at some point in the future, but
+# for now we just match the instructions with their operands.
+#
+# By defining stubs for these instructions, we can work with
+# applications that have them in dead/unused code paths.
+#
+# Needed for rocm-hcc compilations for HSA backends since
+# builtins-hsail library is `cat`d onto the generated kernels.
+# The builtins-hsail library consists of handcoded hsail functions
+# that __might__ be needed by the rocm-hcc compiler in certain binaries.
+gen('Bitmask', base_class='Stub')
+gen('Bitrev', base_class='Stub')
+gen('Firstbit', base_class='Stub')
+gen('Lastbit', base_class='Stub')
+gen('Unpacklo', base_class='Stub')
+gen('Unpackhi', base_class='Stub')
+gen('Pack', base_class='Stub')
+gen('Unpack', base_class='Stub')
+gen('Lerp', base_class='Stub')
+gen('Packcvt', base_class='Stub')
+gen('Unpackcvt', base_class='Stub')
+gen('Sad', base_class='Stub')
+gen('Sadhi', base_class='Stub')
+gen('Activelanecount', base_class='Stub')
+gen('Activelaneid', base_class='Stub')
+gen('Activelanemask', base_class='Stub')
+gen('Activelanepermute', base_class='Stub')
+gen('Groupbaseptr', base_class='Stub')
+gen('Signalnoret', base_class='Stub')
+
###############
#
# Generate file epilogs
}
};
+ class Stub : public HsailGPUStaticInst
+ {
+ public:
+ Stub(const Brig::BrigInstBase *ib, const BrigObject *obj,
+ const char *_opcode)
+ : HsailGPUStaticInst(obj, _opcode)
+ {
+ }
+
+ void generateDisassembly() override
+ {
+ disassembly = csprintf("%s", opcode);
+ }
+
+ bool isVectorRegister(int operandIndex) override { return false; }
+ bool isCondRegister(int operandIndex) override { return false; }
+ bool isScalarRegister(int operandIndex) override { return false; }
+ bool isSrcOperand(int operandIndex) override { return false; }
+ bool isDstOperand(int operandIndex) override { return false; }
+ int getOperandSize(int operandIndex) override { return 0; }
+
+ int
+ getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst) override
+ {
+ return -1;
+ }
+
+ int numSrcRegOperands() override { return 0; }
+ int numDstRegOperands() override { return 0; }
+ int getNumOperands() override { return 0; }
+ };
+
class SpecialInstNoSrcNoDest : public HsailGPUStaticInst
{
public:
{
}
- bool isVectorRegister(int operandIndex) { return false; }
- bool isCondRegister(int operandIndex) { return false; }
- bool isScalarRegister(int operandIndex) { return false; }
- bool isSrcOperand(int operandIndex) { return false; }
- bool isDstOperand(int operandIndex) { return false; }
- int getOperandSize(int operandIndex) { return 0; }
+ bool isVectorRegister(int operandIndex) override { return false; }
+ bool isCondRegister(int operandIndex) override { return false; }
+ bool isScalarRegister(int operandIndex) override { return false; }
+ bool isSrcOperand(int operandIndex) override { return false; }
+ bool isDstOperand(int operandIndex) override { return false; }
+ int getOperandSize(int operandIndex) override { return 0; }
int
- getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst)
+ getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst) override
{
return -1;
}
- int numSrcRegOperands() { return 0; }
- int numDstRegOperands() { return 0; }
- int getNumOperands() { return 0; }
+ int numSrcRegOperands() override { return 0; }
+ int numDstRegOperands() override { return 0; }
+ int getNumOperands() override { return 0; }
};
template<typename DestOperandType>