X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Famd%2Fcompiler%2Faco_print_asm.cpp;h=d4b0e0edbcf3e6acb2776e35846988bf8798bd7f;hb=fb6b38d78007436326cf451a210033a20616f2ce;hp=deb15a8b2563848e832dc1295a2815d8b7395e90;hpb=a01d796de4096331a6950699d4ac66a3f3b91ef3;p=mesa.git diff --git a/src/amd/compiler/aco_print_asm.cpp b/src/amd/compiler/aco_print_asm.cpp index deb15a8b256..d4b0e0edbcf 100644 --- a/src/amd/compiler/aco_print_asm.cpp +++ b/src/amd/compiler/aco_print_asm.cpp @@ -5,12 +5,97 @@ #include "ac_llvm_util.h" #include +#if LLVM_VERSION_MAJOR >= 11 +#include +#endif namespace aco { +/* LLVM disassembler only supports GFX8+, try to disassemble with CLRXdisasm + * for GFX6-GFX7 if found on the system, this is better than nothing. +*/ +void print_asm_gfx6_gfx7(Program *program, std::vector& binary, + std::ostream& out) +{ + char path[] = "/tmp/fileXXXXXX"; + char line[2048], command[128]; + const char *gpu_type; + FILE *p; + int fd; + + /* Dump the binary into a temporary file. */ + fd = mkstemp(path); + if (fd < 0) + return; + + for (uint32_t w : binary) + { + if (write(fd, &w, sizeof(w)) == -1) + goto fail; + } + + /* Determine the GPU type for CLRXdisasm. Use the family for GFX6 chips + * because it doesn't allow to use gfx600 directly. + */ + switch (program->chip_class) { + case GFX6: + switch (program->family) { + case CHIP_TAHITI: + gpu_type = "tahiti"; + break; + case CHIP_PITCAIRN: + gpu_type = "pitcairn"; + break; + case CHIP_VERDE: + gpu_type = "capeverde"; + break; + case CHIP_OLAND: + gpu_type = "oland"; + break; + case CHIP_HAINAN: + gpu_type = "hainan"; + break; + default: + unreachable("Invalid GFX6 family!"); + } + break; + case GFX7: + gpu_type = "gfx700"; + break; + default: + unreachable("Invalid chip class!"); + } + + sprintf(command, "clrxdisasm --gpuType=%s -r %s", gpu_type, path); + + p = popen(command, "r"); + if (p) { + if (!fgets(line, sizeof(line), p)) { + out << "clrxdisasm not found\n"; + pclose(p); + goto fail; + } + + do { + out << line; + } while (fgets(line, sizeof(line), p)); + + pclose(p); + } + +fail: + close(fd); + unlink(path); +} + void print_asm(Program *program, std::vector& binary, unsigned exec_size, std::ostream& out) { + if (program->chip_class <= GFX7) { + print_asm_gfx6_gfx7(program, binary, out); + return; + } + std::vector referenced_blocks(program->blocks.size()); referenced_blocks[0] = true; for (Block& block : program->blocks) { @@ -18,7 +103,11 @@ void print_asm(Program *program, std::vector& binary, referenced_blocks[succ] = true; } + #if LLVM_VERSION_MAJOR >= 11 + std::vector symbols; + #else std::vector> symbols; + #endif std::vector> block_names; block_names.reserve(program->blocks.size()); for (Block& block : program->blocks) { @@ -51,14 +140,28 @@ void print_asm(Program *program, std::vector& binary, next_block++; } + /* mask out src2 on v_writelane_b32 */ + if (((program->chip_class == GFX8 || program->chip_class == GFX9) && (binary[pos] & 0xffff8000) == 0xd28a0000) || + (program->chip_class >= GFX10 && (binary[pos] & 0xffff8000) == 0xd7610000)) { + binary[pos+1] = binary[pos+1] & 0xF803FFFF; + } + size_t l = LLVMDisasmInstruction(disasm, (uint8_t *) &binary[pos], (exec_size - pos) * sizeof(uint32_t), pos * 4, outline, sizeof(outline)); size_t new_pos; const int align_width = 60; - if (program->chip_class == GFX9 && !l && ((binary[pos] & 0xffff8000) == 0xd1348000)) { /* not actually an invalid instruction */ - out << std::left << std::setw(align_width) << std::setfill(' ') << "\tv_add_u32_e64 + clamp"; + if (!l && + ((program->chip_class >= GFX9 && (binary[pos] & 0xffff8000) == 0xd1348000) || /* v_add_u32_e64 + clamp */ + (program->chip_class >= GFX10 && (binary[pos] & 0xffff8000) == 0xd7038000) || /* v_add_u16_e64 + clamp */ + (program->chip_class <= GFX9 && (binary[pos] & 0xffff8000) == 0xd1268000)) /* v_add_u16_e64 + clamp */) { + out << std::left << std::setw(align_width) << std::setfill(' ') << "\tinteger addition + clamp"; + bool has_literal = program->chip_class >= GFX10 && + (((binary[pos+1] & 0x1ff) == 0xff) || (((binary[pos+1] >> 9) & 0x1ff) == 0xff)); + new_pos = pos + 2 + has_literal; + } else if (program->chip_class >= GFX10 && l == 4 && ((binary[pos] & 0xfe0001ff) == 0x020000f9)) { + out << std::left << std::setw(align_width) << std::setfill(' ') << "\tv_cndmask_b32 + sdwa"; new_pos = pos + 2; } else if (!l) { out << std::left << std::setw(align_width) << std::setfill(' ') << "(invalid instruction)";