Path: blob/21.2-virgl/src/gallium/drivers/lima/standalone/lima_disasm.c
4574 views
/*1* Copyright (c) 2019 Vasily Khoruzhick <[email protected]>2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sub license,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the11* next paragraph) shall be included in all copies or substantial portions12* of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER20* DEALINGS IN THE SOFTWARE.21*22*/2324#include "util/ralloc.h"2526#include <err.h>27#include <stdio.h>28#include <string.h>29#include <stdint.h>3031#include "ir/pp/codegen.h"32#include "ir/gp/codegen.h"3334static void35print_usage(void)36{37printf("Usage: lima_disasm [OPTIONS]... FILE\n");38printf(" --help - show this message\n");39}4041typedef struct __attribute__((__packed__)) {42char name[4];43uint32_t size;44} mbs_chunk;4546/* Parses an MBS1 file. MBS1 is used for Mali-400 and earlier which only support47* GLES2, as opposed to MBS2 which is used by later Mali gens, and contains48* the entire inferface between the compiler and the (blob) driver. It's49* produced by the offline compiler as well as glGetProgramBinary(). The50* format is documented at51* https://web.archive.org/web/20171026141029/http://limadriver.org/MBS+File+Format/52* and consists of a bunch of nested "chunks" where each chunk has a53* 4-character tag followed by a 32-bit size, then the contents of the chunk.54* The chunks are nested as follows:55*56* - MBS157* - optional CFRA (fragment shader)58* - core version (uint32_t, Mali-200 vs Mali-400)59* - FSTA (Fragment STAck information)60* - FDIS (if Fragment shader contains a DIScard instruction)61* - FBUU (information on color/depth reads/writes)62* - SUNI (uniform symbol table)63* - SVAR (varying symbol table)64* - DBIN (the actual code)65* - optional CVER (vertex shader)66* - core version (uint32_t, GP2 vs Mali-400)67* - FINS (# of instruction and attrib_prefetch)68* - SUNI (uniform table)69* - SATT (attribute table)70* - SVAR (varying table)71* - DBIN (the actual code)72*73* This routine just finds the DBIN chunk and returns the binary assuming74* there's only the fragment or vertex shader. We don't bother to parse the75* other stuff yet.76*/77static uint32_t *78extract_shader_binary(char *filename, uint32_t *size, bool *is_frag)79{80mbs_chunk chunk;8182if (!filename || !size || !is_frag)83return NULL;8485FILE *in = fopen(filename, "rb");86if (!in)87return NULL;8889if (!fread(&chunk, sizeof(chunk), 1, in)) {90printf("Failed to read MBS1 segment\n");91return NULL;92}9394if (strncmp(chunk.name, "MBS1", 4)) {95printf("File is not MBS\n");96return NULL;97}9899if (!fread(&chunk, sizeof(chunk), 1, in)) {100printf("Failed to read shader segment\n");101return NULL;102}103104if (!strncmp(chunk.name, "CFRA", 4)) {105*is_frag = true;106} else if (!strncmp(chunk.name, "CVER", 4)) {107*is_frag = false;108} else {109printf("Unsupported shader type\n");110return NULL;111}112113/* Skip version */114fseek(in, 4, SEEK_CUR);115116/* Skip the other chunks and find the DBIN chunk. */117do {118if (!fread(&chunk, sizeof(chunk), 1, in)) {119printf("Failed to read segment\n");120return NULL;121}122if (!strncmp(chunk.name, "DBIN", 4))123break;124fseek(in, chunk.size, SEEK_CUR);125} while (!feof(in));126127if (feof(in)) {128printf("CBIN segment not found!\n");129return NULL;130}131132*size = chunk.size;133134uint32_t *bin = ralloc_size(NULL, chunk.size);135if (!bin) {136printf("Failed to allocate shader binary\n");137return NULL;138}139140if (!fread(bin, chunk.size, 1, in)) {141printf("Failed to read shader binary\n");142ralloc_free(bin);143bin = NULL;144}145146return bin;147}148149int150main(int argc, char **argv)151{152int n;153bool is_frag = true;154155if (argc < 2) {156print_usage();157return 1;158}159160for (n = 1; n < argc; n++) {161if (!strcmp(argv[n], "--help")) {162print_usage();163return 1;164}165}166167char *filename = NULL;168filename = argv[n];169170uint32_t size = 0;171uint32_t *prog = extract_shader_binary(filename, &size, &is_frag);172if (!prog) {173printf("Failed to parse mbs!\n");174return -1;175}176177if (is_frag) {178assert((size & 0x3) == 0);179size >>= 2;180uint32_t *bin = prog;181uint32_t offset = 0;182do {183ppir_codegen_ctrl *ctrl = (ppir_codegen_ctrl *)bin;184printf("@%6d: ", offset);185ppir_disassemble_instr(bin, offset);186bin += ctrl->count;187offset += ctrl->count;188size -= ctrl->count;189} while (size);190} else {191gpir_disassemble_program((gpir_codegen_instr *)prog, size / (sizeof(gpir_codegen_instr)));192}193194ralloc_free(prog);195196return 0;197}198199200201