//===- disasm_instr_test.c ------------------------------------------------===// // // Part of Comgr, under the Apache License v2.0 with LLVM Exceptions. See // amd/comgr/LICENSE.TXT in this repository for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "amd_comgr.h" #include "common.h" #include #include #include #include #include const int ExpectedUserData; void checkUserData(const void *UserData) { if (UserData != (const void *)&ExpectedUserData) { fail("user_data changed"); } } const char *skipspace(const char *S) { while (isspace(*S)) { ++S; } return S; } size_t strlenWithoutTrailingWhitespace(const char *S) { size_t I = strlen(S); while (I && isspace(S[--I])) { ; } return I + 1; } const char Program[] = { '\x02', '\x00', '\x06', '\xC0', '\x00', '\x00', '\x00', '\x00', '\x7f', '\xC0', '\x8c', '\xbf', '\x00', '\x80', '\x12', '\xbf', '\x05', '\x00', '\x85', '\xbf', '\x00', '\x02', '\x00', '\x7e', '\xc0', '\x02', '\x04', '\x7e', '\x01', '\x02', '\x02', '\x7e', '\x00', '\x80', '\x70', '\xdc', '\x00', '\x02', '\x7f', '\x00', '\x00', '\x00', '\x81', '\xbf', }; const char *Instructions[] = { "s_load_dwordx2 s[0:1], s[4:5], 0x0", "s_waitcnt lgkmcnt(0)", "s_cmp_eq_u64 s[0:1], 0", "s_cbranch_scc1 5", "v_mov_b32_e32 v0, s0", "v_mov_b32_e32 v2, 64", "v_mov_b32_e32 v1, s1", "global_store_dword v[0:1], v2, off", "s_endpgm", }; const size_t InstructionsLen = sizeof(Instructions) / sizeof(*Instructions); size_t InstructionsIdx = 0; const size_t BrInstructionIdx = 3; const size_t BrInstructionAddr = 40; uint64_t readMemoryCallback(uint64_t From, char *To, uint64_t Size, void *UserData) { checkUserData(UserData); if (From >= sizeof(Program)) { return 0; } if (From + Size > sizeof(Program)) { Size = sizeof(Program) - From; } memcpy(To, Program + From, Size); return Size; } void printInstructionCallback(const char *Instruction, void *UserData) { checkUserData(UserData); if (InstructionsIdx == InstructionsLen) { fail("too many instructions"); } const char *Expected = skipspace(Instructions[InstructionsIdx++]); const char *Actual = skipspace(Instruction); if (strncmp(Expected, Actual, strlenWithoutTrailingWhitespace(Actual))) { fail("incorrect instruction: expected '%s', actual '%s'", Expected, Actual); } } void printAddressCallback(uint64_t Address, void *UserData) { checkUserData(UserData); size_t ActualIdx = InstructionsIdx - 1; if (ActualIdx != BrInstructionIdx) { fail("absolute address resolved for instruction index %zu, expected index " "%zu", InstructionsIdx, BrInstructionIdx); } if (Address != BrInstructionAddr) { fail("incorrect absolute address %llu resolved for instruction index %zu, " "expected %llu", Address, ActualIdx, BrInstructionAddr); } } int main(int argc, char *argv[]) { amd_comgr_status_t Status; amd_comgr_disassembly_info_t DisassemblyInfo; Status = amd_comgr_create_disassembly_info( "amdgcn-amd-amdhsa--gfx900", &readMemoryCallback, &printInstructionCallback, &printAddressCallback, &DisassemblyInfo); checkError(Status, "amd_comgr_create_disassembly_info"); uint64_t Addr = 0; uint64_t Size = 0; while (Status == AMD_COMGR_STATUS_SUCCESS && Addr < sizeof(Program)) { Status = amd_comgr_disassemble_instruction( DisassemblyInfo, Addr, (void *)&ExpectedUserData, &Size); checkError(Status, "amd_comgr_disassemble_instruction"); Addr += Size; } if (InstructionsIdx != InstructionsLen) { fail("too few instructions\n"); } Addr = sizeof(Program) - 1; Size = 0; Status = amd_comgr_disassemble_instruction(DisassemblyInfo, Addr, (void *)&ExpectedUserData, &Size); if (Status != AMD_COMGR_STATUS_ERROR) { fail("successfully disassembled invalid instruction encoding"); } Status = amd_comgr_destroy_disassembly_info(DisassemblyInfo); checkError(Status, "amd_comgr_destroy_disassembly_info"); return EXIT_SUCCESS; }