diff options
Diffstat (limited to 'doc/sphinx/source/libshader_disasm.rst')
-rw-r--r-- | doc/sphinx/source/libshader_disasm.rst | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/doc/sphinx/source/libshader_disasm.rst b/doc/sphinx/source/libshader_disasm.rst new file mode 100644 index 0000000..52505b6 --- /dev/null +++ b/doc/sphinx/source/libshader_disasm.rst @@ -0,0 +1,91 @@ +Shader Disassembly +================== + +UMR has functions to disassemble and pretty print shader text. This requires +low level access to a shader disassembler such as provided by +llvm-dev. + +The lowest level function from the API is to decode a block of +shader program text (code) into printable strings: + +:: + + int umr_shader_disasm(struct umr_asic *asic, + uint8_t *inst, unsigned inst_bytes, + uint64_t PC, + char ***disasm_text); + +This will disassemble shader program text from 'inst' of 'inst_bytes' in +length. The program counter address (if any) can be specified as 'PC' to +hint to the decoder the address where the shader text comes from. + +The output (if any) is stored in an array of pointers which must be freed +by the caller for instance + +:: + + int x; + + for (x = 0; x < inst_bytes/4; x++) { + printf("%s\n", disasm_text[x]); + free(disasm_text[x]); + } + free(disasm_text); + +To create more useful formatted output the following function can be +used: + +:: + + int umr_vm_disasm_to_str(struct umr_asic *asic, + unsigned vmid, uint64_t addr, + uint64_t PC, uint32_t size, + uint32_t start_offset, char ***out); + +This function will fetch a shader from an address specified by the 'vmid' and +'addr' indicated. The program counter can be passed (if there is one) as 'PC'. +The size of the shader in bytes is passed by 'size'. The output is stored in +an array of char pointers that the function itself allocates and must be +freed by the caller as well. For a given shader the decoding can be offset +by a variable amount with 'start_offset' which can be useful for only +decoding a snapshot of a shader. + +The format of the output of this function includes information about the +opcodes being printed. For instance, + +:: + + pgm[2@0x800101289000 + 0x858 ] = 0xd1c10001 v_mad_f32 v1, s0, v6, v1 + pgm[2@0x800101289000 + 0x85c ] = 0x04060c00 ;; + pgm[2@0x800101289000 + 0x860 ] = 0xd1c10002 v_mad_f32 v2, s0, v7, v2 + pgm[2@0x800101289000 + 0x864 ] = 0x040a0e00 ;; + pgm[2@0x800101289000 + 0x868 ] = 0xd2960000 v_cvt_pkrtz_f16_f32 v0, v0, v1 + pgm[2@0x800101289000 + 0x86c ] = 0x00020300 ;; + pgm[2@0x800101289000 + 0x870 ] = 0xd2960001 v_cvt_pkrtz_f16_f32 v1, v2, v3 + pgm[2@0x800101289000 + 0x874 ] = 0x00020702 ;; + * pgm[2@0x800101289000 + 0x878 ] = 0xc4001c0f exp mrt0 v0, v0, v1, v1 done compr vm + pgm[2@0x800101289000 + 0x87c ] = 0x00000100 ;; + +The line with " * " indicates the address the 'PC' program counter points to. + +To compute the size of a shader this function can be used: + +:: + + uint32_t umr_compute_shader_size(struct umr_asic *asic, + struct umr_shaders_pgm *shader) + +The shader must be terminated at some point with an S_ENDPGM opcode or ideally +with an S_ENDINV opcode (as is the case with mesa based libraries). In the +case the shader does not use an S_ENDINV opcode the function will keep reading +shader text until a page fault occurs and then use the last S_ENDPGM +as the size. + +If the option 'disasm_early_term' is specified, e.g.,: + +:: + + asic->options.disasm_early_term = 1; + +then the function will stop on the first S_ENDPGM which is usually +correct for most shaders. |