diff options
author | Jerome Glisse <jglisse@redhat.com> | 2010-04-28 14:59:23 +0200 |
---|---|---|
committer | Jerome Glisse <jglisse@redhat.com> | 2010-04-28 14:59:23 +0200 |
commit | 35c56944dfe5ca34677e39fdc0ebdab15c00b442 (patch) | |
tree | 612647786d1c1eae06178b3c7fac27c0b96005e4 | |
parent | 17150fac6c9ea4b9bb22893211cd900bc2601d74 (diff) |
radeondb: add r6xx/r7xx shader disassembler
Signed-off-by: Jerome Glisse <jglisse@redhat.com>
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/r600_disassembler.c | 1236 | ||||
-rw-r--r-- | src/r600_state.c | 1 | ||||
-rw-r--r-- | src/radeon.c | 51 | ||||
-rw-r--r-- | src/radeon_bo.c | 32 | ||||
-rw-r--r-- | src/radeon_bof.c | 5 | ||||
-rw-r--r-- | src/radeon_json.c | 14 | ||||
-rw-r--r-- | src/radeon_priv.h | 5 | ||||
-rw-r--r-- | src/radeondb.c | 57 |
9 files changed, 1360 insertions, 44 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 0e01d60..bb446ed 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,7 +29,8 @@ noinst_HEADER = radeon.h radeon_priv.h r600_states.h mode.h radeondb_SOURCES = radeondb.c bof.c radeon_pciid.c radeon_ctx.c radeon_bof.c\ radeon_json.c r600_state.c r600_ctx.c mode.c radeon.c radeon_state.c\ - radeon_draw.c radeon_bo.c radeon_pci.c radeon_reg.c rs600_reg.c + radeon_draw.c radeon_bo.c radeon_pci.c radeon_reg.c rs600_reg.c\ + r600_disassembler.c radeondb_LDADD = $(LIBJANSSON_LIBS) $(LIBDRM_LIBS) $(LIBDRM_RADEON_LIBS) $(PCIACCESS_LIBS) rs600_reg.c: ../json/rs600.json ../tools/rdb.c diff --git a/src/r600_disassembler.c b/src/r600_disassembler.c new file mode 100644 index 0000000..9c517da --- /dev/null +++ b/src/r600_disassembler.c @@ -0,0 +1,1236 @@ +/* + * Copyright (C) 2008-2009 Matthias Hopf + * Copyright (C) 2008-2009 Alexander Deucher + * Copyright 2010 Jerome Glisse <glisse@freedesktop.org> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Jerome Glisse + */ +#include <stdlib.h> +#include "radeon_priv.h" +#include "r600d.h" + +struct disassembler; +typedef int (*disassemble_t)(struct disassembler *d); + +struct section { + unsigned count; + disassemble_t disassemble; +}; + +/** + * struct disassembler + * + * @bcode: byte code + * @ndw: number of dwords in the shader/buffer + * @id: current index + * @id_last_cf: last possible index for a cf instruction + * it's inferior to the first address of the + * first non cf instruction + * @disassemble: disassemble function pointer for each of the + * dword in the byte code + * @is_r700: is r700 byte code + */ +struct disassembler { + u32 *bcode; + unsigned ndw; + unsigned id; + unsigned id_last_cf; + struct section *section; + int is_r700; +}; + +static const char *cf_alu_op[16]; +static const char *cf_exp_op[41]; +static const char *sel[8]; +static const char *cf_exp_type[8]; +static const char *cf_mem_type[8]; +static const char *ab_pixel[62]; +static const char *ab_pos[64]; +static const char *km[4]; +static const char *rel[2]; +static const char *cond[4]; +static const char *cf_op[25]; +static const char *format_comp_all[2]; +static const char *srf_mode_all[2]; +static const char *vtx_op[2]; +static const char *fetch_type[3]; +static const char *num_format_all[3]; +static const char *endian_swap[3]; +static const char *elem[4]; +static const char *omod[4]; +static const char *bs[6]; +static const char *op2[122]; +static const char *op3[32]; +static const char *im[5]; +static const char *ps[4]; + +void cf_alu(struct disassembler *d) +{ + u32 dword0, dword1; + int kb0, kb1, km0; + int km1, ka0, ka1, count, uw; + int cf_inst, wqm, barrier; + + dword0 = d->bcode[d->id]; + dword1 = d->bcode[d->id + 1]; + kb0 = (dword0 >> 22) & 0xf; + kb1 = (dword0 >> 26) & 0xf; + km0 = (dword0 >> 30) & 0x3; + + printf("0x%08X 0x%08X ", d->id, dword0); + printf("(ADDR(0x%06X),", (dword0 & 0x3fffff) * 2); + printf("KCB0(%d),", kb0); + printf("KCB1(%d),", kb1); + printf("KCM0(%s))\n", km[km0]); + + km1 = (dword1 >> 0) & 0x3; + ka0 = (dword1 >> 2) & 0xff; + ka1 = (dword1 >> 10) & 0xff; + count = (dword1 >> 18) & 0x7f; + uw = (dword1 >> 25) & 0x1; + cf_inst = (dword1 >> 26) & 0xf; + wqm = (dword1 >> 30) & 0x1; + barrier = (dword1 >> 31) & 0x1; + + printf("0x%08X 0x%08X ", d->id + 1, dword1); + printf("(KCM1(0x%X),", km1); + printf("KCA0(0x%X),", ka0); + printf("KCA1(0x%X),", ka1); + printf("COUNT(0x%X),", count); + printf("WATERFALL(%d),", uw); + printf("INST(%s),", cf_alu_op[cf_inst]); + printf("WQM(%d),", wqm); + printf("B(%d))\n", barrier); +} + +void cf_alloc_imp_exp(struct disassembler *d) +{ + u32 dword0, dword1; + int array_base, type, rw_gpr; + int rw_rel, index_gpr, elem_size; + int sel_x, sel_y, sel_z, sel_w, elem_loop; + int cf_inst, wqm, barrier, bc, eop, vpm; + + dword0 = d->bcode[d->id]; + dword1 = d->bcode[d->id + 1]; + array_base = (dword0 >> 0) & 0x1fff; + type = (dword0 >> 13) & 0x3; + rw_gpr = (dword0 >> 15) & 0x7f; + rw_rel = (dword0 >> 22) & 0x1; + index_gpr = (dword0 >> 23) & 0x7f; + elem_size = (dword0 >> 30) & 0x3; + + printf("0x%08X 0x%08X ", d->id, dword0); + if (type == 0) + printf("(ABASE(%s),", ab_pixel[array_base]); + else if (type == 1) + printf("(ABASE(%s),", ab_pos[array_base]); + else + printf("(ABASE(%d),", array_base); + printf("TYPE(%s),", cf_exp_type[type]); + printf("RW_GPR(%d),", rw_gpr); + printf("RW_REL(%s),", rel[rw_rel]); + printf("IGPR(%d),", index_gpr); + printf("ESIZE(%d))\n", elem_size); + + sel_x = (dword1 >> 0) & 0x7; + sel_y = (dword1 >> 3) & 0x7; + sel_z = (dword1 >> 6) & 0x7; + sel_w = (dword1 >> 9) & 0x7; + elem_loop = (dword1 >> 16) & 0x1; + bc = (dword1 >> 17) & 0xf; + eop = (dword1 >> 21) & 0x1; + vpm = (dword1 >> 22) & 0x1; + cf_inst = (dword1 >> 23) & 0x7f; + wqm = (dword1 >> 30) & 0x1; + barrier = (dword1 >> 31) & 0x1; + + printf("0x%08X 0x%08X ", d->id + 1, dword1); + printf("((%s),", sel[sel_x]); + printf("(%s),", sel[sel_y]); + printf("(%s),", sel[sel_z]); + printf("(%s),", sel[sel_w]); + printf("ELOOP(%d),", elem_loop); + printf("BC(%d),", bc); + printf("EOP(%d),", eop); + printf("VPM(%d),", vpm); + printf("INST(%s),", cf_exp_op[cf_inst]); + printf("WQM(%d),", wqm); + printf("B(%d))\n", barrier); +} + +void cf_alloc_imp_mem_exp(struct disassembler *d) +{ + u32 dword0, dword1; + int array_base, type, rw_gpr; + int rw_rel, index_gpr, elem_size; + int array_size, comp_mask, elem_loop; + int bc, eop, vpm, cf_inst, wqm, barrier; + + dword0 = d->bcode[d->id]; + dword1 = d->bcode[d->id + 1]; + array_base = (dword0 >> 0) & 0x1fff; + type = (dword0 >> 13) & 0x3; + rw_gpr = (dword0 >> 15) & 0x7f; + rw_rel = (dword0 >> 22) & 0x1; + index_gpr = (dword0 >> 23) & 0x7f; + elem_size = (dword0 >> 30) & 0x3; + + printf("0x%08X 0x%08X ", d->id, dword0); + printf("(ABASE(%d),", array_base); + printf("TYPE(%s),", cf_mem_type[type]); + printf("RW_GPR(%d),", rw_gpr); + printf("RW_REL(%s),", rel[rw_rel]); + printf("IGPR(%d),", index_gpr); + printf("ESIZE(%d))\n", elem_size); + + array_size = (dword1 >> 0) & 0xfff; + comp_mask = (dword1 >> 12) & 0xf; + bc = (dword1 >> 17) & 0xf; + eop = (dword1 >> 21) & 0x1; + vpm = (dword1 >> 22) & 0x1; + cf_inst = (dword1 >> 23) & 0x7f; + wqm = (dword1 >> 30) & 0x1; + barrier = (dword1 >> 31) & 0x1; + + printf("0x%08X 0x%08X ", d->id + 1, dword1); + printf("(ASIZE(%d),", array_size); + printf("CM(%d),", comp_mask); + if (!d->is_r700) { + elem_loop = (dword1 >> 16) & 0x1; + printf("ELOOP(%d),", elem_loop); + } + printf("BC(%d),", bc); + printf("EOP(%d),", eop); + printf("VPM(%d),", vpm); + printf("INST(%s),", cf_exp_op[cf_inst]); + printf("WQM(%d),", wqm); + printf("B(%d))\n", barrier); +} + +void cf(struct disassembler *d) +{ + u32 dword0, dword1; + int pop_count, cf_const; + int cf_cond, count, call_count; + int eop, vpm, cf_inst, wqm; + int barrier; + + dword0 = d->bcode[d->id]; + dword1 = d->bcode[d->id + 1]; + + printf("0x%08X 0x%08X ", d->id, dword0); + printf("(ADDR(0x%X))\n", dword0 * 2); + + pop_count = (dword1 >> 0) & 0x7; + cf_const = (dword1 >> 3) & 0x1f; + cf_cond = (dword1 >> 8) & 0x3; + count = (dword1 >> 10) & 0x7; + call_count = (dword1 >> 13) & 0x3f; + eop = (dword1 >> 21) & 0x1; + vpm = (dword1 >> 22) & 0x1; + cf_inst = (dword1 >> 23) & 0x7f; + wqm = (dword1 >> 30) & 0x1; + barrier = (dword1 >> 31) & 0x1; + printf("0x%08X 0x%08X ", d->id + 1, dword1); + printf("(POPC(%d),", pop_count); + printf("CONST(%d),", cf_const); + printf("COND(%s),", cond[cf_cond]); + printf("COUNT(%d),", count); + printf("CALLC(%d),", call_count); + printf("EOP(%d),", eop); + printf("VPM(%d),", vpm); + printf("INST(%s),", cf_op[cf_inst]); + printf("WQM(%d),", wqm); + printf("B(%d))\n", barrier); +} + +static void print_op(unsigned sel, unsigned rel, unsigned neg, unsigned elem, + unsigned abs, unsigned imode, u32 *litteral) +{ + unsigned pelem = 1; + float *lfloat = (float*)litteral; + + if (neg) + printf("-("); + if (abs) + printf("ABS("); + if (sel >= 128 && sel <= 159) { + /* KCACHE0 */ + printf("KCACHE0[%d]", sel - 128); + goto out; + } + if (sel >= 160 && sel <= 191) { + /* KCACHE1 */ + printf("KCACHE1[%d]", sel - 160); + goto out; + } + if (sel >= 256 && sel <= 511) { + /* CFILE */ + printf("CFILE[%d]", sel - 256); + goto out; + } + switch (sel) { + case 248: + printf("0.0"); + pelem = 0; + break; + case 249: + printf("1.0"); + pelem = 0; + break; + case 250: + printf("1"); + pelem = 0; + break; + case 251: + printf("-1"); + pelem = 0; + break; + case 252: + printf("0.5"); + pelem = 0; + break; + case 253: + printf("%f", lfloat[elem]); + pelem = 0; + break; + case 254: + printf("PV"); + break; + case 255: + printf("PS"); + break; + default: + printf("GPR[%d]", sel); + break; + } +out: + if (rel) { + switch (imode) { + case 0: + printf("[AR_X]"); + break; + case 1: + printf("[AR_Y]"); + break; + case 2: + printf("[AR_Z]"); + break; + case 3: + printf("[AR_W]"); + break; + case 4: + printf("[LOOP]"); + break; + default: + break; + } + } + if (pelem) { + switch(elem) { + case 0: + printf(".x"); + break; + case 1: + printf(".y"); + break; + case 2: + printf(".z"); + break; + case 3: + printf(".w"); + break; + } + } + if (abs) + printf(")"); + if (neg) + printf(")"); +} + +static int do_alu_clause(struct disassembler *d) +{ + u32 dword0, dword1; + int count; + unsigned sel0, sel1, sel2, dsel; + unsigned elem0, elem1, elem2, delem; + unsigned neg0, neg1, neg2; + unsigned rel0, rel1, rel2, drel; + unsigned abs0, abs1, abs2; + unsigned imode, alu_inst; + int inline_const_count = 0; + float *fn; + + count = d->section[d->id].count; + while (count) { + dword0 = d->bcode[d->id]; + dword1 = d->bcode[d->id + 1]; + if (inline_const_count) { + fn = (float*)&dword0; + printf("0x%08X 0x%08x CONST(%f)\n", d->id, dword0, *fn); + fn = (float*)&dword1; + printf("0x%08X 0x%08x CONST(%f)\n", d->id + 1, dword1, *fn); + inline_const_count--; + } else { + sel0 = (dword0 >> 0) & 0x1ff; + sel1 = (dword0 >> 13) & 0x1ff; + sel2 = 0; + elem0 = (dword0 >> 10) & 0x3; + elem1 = (dword0 >> 23) & 0x3; + elem2 = 0; + rel0 = (dword0 >> 9) & 0x1; + rel1 = (dword0 >> 22) & 0x1; + rel2 = 0; + neg0 = (dword0 >> 12) & 0x1; + neg1 = (dword0 >> 25) & 0x1; + neg2 = 0; + imode = (dword0 >> 26) & 0x7; + abs0 = abs1 = abs2 = 0; + dsel = (dword1 >> 21) & 0x7f; + drel = (dword1 >> 28) & 0x1; + delem = (dword1 >> 29) & 0x3; + /* if high 3 bits of inst are 000b, OP2, else OP3 */ + if ((dword1 >> 15) & 0x7) { + sel2 = (dword1 >> 0) & 0x1ff; + elem2 = (dword1 >> 10) & 0x3; + rel2 = (dword1 >> 9) & 0x1; + neg2 = (dword1 >> 12) & 0x1; + alu_inst = (dword1 >> 13) & 0x1f; + printf("0x%08X 0x%08x ", d->id, dword0); + printf("%s ", op3[alu_inst]); + print_op(dsel, drel, 0, delem, 0, imode, &d->bcode[d->id + 2]); + printf(", "); + print_op(sel0, rel0, neg0, elem0, abs0, imode, &d->bcode[d->id + 2]); + printf(", "); + print_op(sel1, rel1, neg1, elem1, abs1, imode, &d->bcode[d->id + 2]); + printf(", "); + print_op(sel2, rel2, neg2, elem2, abs2, imode, &d->bcode[d->id + 2]); + printf(";\n"); + printf("0x%08X 0x%08x\n", d->id + 1, dword1); + } else { + if (d->is_r700) { + alu_inst = (dword1 >> 7) & 0x7ff; + } else { + alu_inst = (dword1 >> 8) & 0x3ff; + } + printf("0x%08X 0x%08x ", d->id, dword0); + printf("%s ", op2[alu_inst]); + print_op(dsel, drel, 0, delem, 0, imode, &d->bcode[d->id + 2]); + printf(", "); + print_op(sel0, rel0, neg0, elem0, abs0, imode, &d->bcode[d->id + 2]); + printf(", "); + print_op(sel1, rel1, neg1, elem1, abs1, imode, &d->bcode[d->id + 2]); + printf(";\n"); + printf("0x%08X 0x%08x\n", d->id + 1, dword1); + } + + /* inline constants */ + if ((sel0 == 253) || (sel1 == 253) || (sel2 == 253)) { + if ((elem0 > 1) || (elem1 > 1) || (elem2 > 1)) + inline_const_count = 2; // 3-4 constants + else + inline_const_count = 1; // 1-2 constants + } + } + count--; + d->id += 2; + } + return 0; +} + +void vtx_dword0(struct disassembler *d) +{ + u32 dword0; + int inst, ft, fwq; + int buffer_id, src_gpr; + int sr, ssx, mfc; + + dword0 = d->bcode[d->id]; + inst = (dword0 >> 0) & 0x1f; + ft = (dword0 >> 5) & 0x3; + fwq = (dword0 >> 7) & 0x1; + buffer_id = (dword0 >> 8) & 0xff; + src_gpr = (dword0 >> 16) & 0x7f; + sr = (dword0 >> 23) & 0x1; + ssx = (dword0 >> 24) & 0x3; + mfc = (dword0 >> 26) & 0x3f; + mfc++; + + printf("0x%08X 0x%08X ", d->id, dword0); + printf("INST(%s),", vtx_op[inst]); + printf("FT(%s),", fetch_type[ft]); + printf("FWQ(%d),", fwq); + printf("BID(%d),", buffer_id); + printf("SGPR(%d),", src_gpr); + printf("SREL(%s),", rel[sr]); + printf("SSEL(%s),", sel[ssx]); + printf("MFC(%d))\n", mfc); +} + +void vtx_dword1_sem(struct disassembler *d) +{ + u32 dword1; + int semantic_id; + int dsx, dsy, dsz, dsw; + int ucf, df, nfa, fca, sma; + + dword1 = d->bcode[d->id + 1]; + semantic_id = (dword1 >> 0) & 0xff; + dsx = (dword1 >> 9) & 0x7; + dsy = (dword1 >> 12) & 0x7; + dsz = (dword1 >> 15) & 0x7; + dsw = (dword1 >> 18) & 0x7; + ucf = (dword1 >> 21) & 0x1; + df = (dword1 >> 22) & 0x3f; + nfa = (dword1 >> 28) & 0x3; + fca = (dword1 >> 30) & 0x1; + sma = (dword1 >> 31) & 0x1; + + printf("0x%08X 0x%08X ", d->id, dword1); + printf("(SID(%d),", semantic_id); + printf("DX(%s),", sel[dsx]); + printf("DY(%s),", sel[dsy]); + printf("DZ(%s),", sel[dsz]); + printf("DW(%s),", sel[dsw]); + printf("UCF(%d),", ucf); + printf("DFORMAT(%d),", df); + printf("NFORMATA(%s),", num_format_all[nfa]); + printf("FORMATCA(%s),", format_comp_all[fca]); + printf("SRFMALL(%s))\n", srf_mode_all[sma]); +} + +void vtx_dword1_gpr(struct disassembler *d) +{ + u32 dword1; + int dst_gpr, dr; + int dsx, dsy, dsz, dsw; + int ucf, df, nfa, fca, sma; + + dword1 = d->bcode[d->id + 1]; + dst_gpr = (dword1 >> 0) & 0x7f; + dr = (dword1 >> 7) & 0x1; + dsx = (dword1 >> 9) & 0x7; + dsy = (dword1 >> 12) & 0x7; + dsz = (dword1 >> 15) & 0x7; + dsw = (dword1 >> 18) & 0x7; + ucf = (dword1 >> 21) & 0x1; + df = (dword1 >> 22) & 0x3f; + nfa = (dword1 >> 28) & 0x3; + fca = (dword1 >> 30) & 0x1; + sma = (dword1 >> 31) & 0x1; + + printf("0x%08X 0x%08X ", d->id, dword1); + printf("(DGPR(%d),", dst_gpr); + printf("DREL(%s),", rel[dr]); + printf("DX(%s),", sel[dsx]); + printf("DY(%s),", sel[dsy]); + printf("DZ(%s),", sel[dsz]); + printf("DW(%s),", sel[dsw]); + printf("UCF(%d),", ucf); + printf("DFORMAT(%d),", df); + printf("NFORMATA(%s),", num_format_all[nfa]); + printf("FORMATCA(%s),", format_comp_all[fca]); + printf("SRFMALL(%s))\n", srf_mode_all[sma]); +} + +void vtx_dword2(struct disassembler *d) +{ + u32 dword2; + int offset, es; + int cbns, mf; + + dword2 = d->bcode[d->id + 2]; + offset = (dword2 >> 0) & 0xffff; + es = (dword2 >> 16) & 0x3; + cbns = (dword2 >> 18) & 0x1; + mf = (dword2 >> 19) & 0x1; + + printf("0x%08X 0x%08X ", d->id, dword2); + printf("(OFFSET(%d),", offset); + printf("ESWAP(%s),", endian_swap[es]); + printf("CBNSTRIDE(%d),", cbns); + printf("MFETCH(%d))\n", mf); +} + +static int do_vtx_clause(struct disassembler *d) +{ + u32 dword0, dword1, dword2; + int op, count; + + count = d->section[d->id].count; + while (count) { + dword0 = d->bcode[d->id]; + dword1 = d->bcode[d->id + 1]; + dword2 = d->bcode[d->id + 2]; + vtx_dword0(d); + /* if op = 1, sem, else gpr */ + op = (dword0 >> 0) & 0x1f; + if (op == 1) + vtx_dword1_sem(d); + else + vtx_dword1_gpr(d); + vtx_dword2(d); + printf("0x%08X 0x%08X\n", d->id, d->bcode[d->id + 3]); + count--; + d->id += 4; + } + return 0; +} + +static int do_tex_clause(struct disassembler *d) +{ + printf("0x%08X 0x%08X tex\n", d->id, d->bcode[d->id++]); + return 0; +} + +static int do_cf_inst(struct disassembler *d) +{ + u32 dword0, dword1; + int encoding, addr, op, count; + int eop = 0, i; + + dword0 = d->bcode[d->id]; + dword1 = d->bcode[d->id + 1]; + + /* if high 2 bits of inst are 10b or 11b, ALU, + * else if 01b, imp/exp + * else if 00b, cf + */ + encoding = (dword1 >> 28) & 0x3; + if (encoding >= 2) { + cf_alu(d); + addr = ((dword0 >> 0) & 0x3fffff) * 2; + d->id_last_cf = addr; + count = (dword1 >> 18) & 0x7f; + count++; + d->section[addr].disassemble = do_alu_clause; + d->section[addr].count = count; + } else if (encoding == 1) { + op = (dword1 >> 23) & 0x7f; + if ((op == 39) || (op == 40)) { + /* export inst */ + cf_alloc_imp_exp(d); + } else { + /* mem inst */ + cf_alloc_imp_mem_exp(d); + } + eop = (dword1 >> 21) & 0x1; + } else { + op = (dword1 >> 23) & 0x7f; + addr = dword0; + addr *= 2; + count = (dword1 >> 10) & 0x7; + if (d->is_r700) + count += (dword1 >> 19) & 0x1; + count++; + cf(d); + if (op == 1) { + d->section[addr].disassemble = do_tex_clause; + d->section[addr].count = count; + } else if ((op == 2) || (op == 3)) { + d->section[addr].disassemble = do_vtx_clause; + d->section[addr].count = count; + } + eop = (dword1 >> 21) & 0x1; + } + if (eop) + d->id_last_cf = d->id + 1; + d->id += 2; + return 0; +} + +static void r600_disassembler(u32 *bcode, unsigned ndw, int is_r700) +{ + struct disassembler d; + + d.bcode = bcode; + d.ndw = ndw; + d.id_last_cf = ndw; + d.id = 0; + d.is_r700 = is_r700; + d.section = calloc(1, sizeof(struct section) * ndw); + if (d.section == NULL) + return; + do { + if (do_cf_inst(&d)) + return; + } while(d.id < d.id_last_cf); + do { + if (d.section[d.id].disassemble) + if (d.section[d.id].disassemble(&d)) + goto out; + while (d.id < ndw && !d.section[d.id].count) { + printf("0x%08X 0x%08X\n", d.id, d.bcode[d.id++]); + } + } while (d.id < ndw); +out: + free(d.section); +} + +void r600_ctx_disassemble(struct radeon_ctx *ctx) +{ + unsigned i, is_r700 = 0, ndw; + u32 *ptr; + + if (ctx->radeon->family >= CHIP_RS880) + is_r700 = 1; + for (i = 0; i < ctx->ndraw; i++) { + radeon_bo_map(ctx->radeon, ctx->draw[i]->state[R600_VS_SHADER]->bo[0]); + ptr = ctx->draw[i]->state[R600_VS_SHADER]->bo[0]->data; + ndw = ctx->draw[i]->state[R600_VS_SHADER]->bo[0]->size / 4; + printf("VS_SHADER[%d][0x%X] -----------------------------------------------\n", i, ndw); + r600_disassembler(ptr, ndw, is_r700); + radeon_bo_unmap(ctx->radeon, ctx->draw[i]->state[R600_VS_SHADER]->bo[0]); + + radeon_bo_map(ctx->radeon, ctx->draw[i]->state[R600_PS_SHADER]->bo[0]); + ptr = ctx->draw[i]->state[R600_PS_SHADER]->bo[0]->data; + ndw = ctx->draw[i]->state[R600_PS_SHADER]->bo[0]->size / 4; +printf("PSshader %p %d %d 0x%X\n", ctx->draw[i]->state[R600_PS_SHADER]->bo[0], ndw * 4, ndw, ndw); + printf("PS_SHADER[%d][0x%X] -----------------------------------------------\n", i, ndw); + r600_disassembler(ptr, ndw, is_r700); + radeon_bo_unmap(ctx->radeon, ctx->draw[i]->state[R600_PS_SHADER]->bo[0]); + } +} + +static const char *rel[2] = { + "ABSOLUTE", + "RELATIVE" +}; + +static const char *im[5] = { + "AR_X", + "AR_Y", + "AR_Z", + "AR_W", + "LOOP", +}; + +static const char *ps[4] = { + "OFF", + "Reserved", + "ZERO", + "ONE" +}; + +static const char *elem[4] = { + "X", + "Y", + "Z", + "W", +}; + +static const char *omod[4] = { + "OMOD_OFF", + "OMOD_M2", + "OMOD_M4", + "OMOD_D2", +}; + +static const char *bs[6] = { + "VEC_012", + "VEC_021", + "VEC_120", + "VEC_102", + "VEC_201", + "VEC_210", +}; + +static const char *op2[122] = { + "ADD", //0 + "MUL", //1 + "MUL_IEEE", //2 + "MAX", //3 + "MIN", //4 + "MAX_DX10", //5 + "MIN_DX10", //6 + "reserved", //7 + "SETE", //8 + "SETGT", //9 + "SETGE", //10 + "SETNE", //11 + "SETE_DX10", //12 + "SETGT_DX10", //13 + "SETGE_DX10", //14 + "SETNE_DX10", //15 + "FRACT", //16 + "TRUNC", //17 + "CEIL", //18 + "RNDNE", //19 + "FLOOR", //20 + "MOVA", //21 + "MOVA_FLOOR", //22 + "reserved", //23 + "MOVA_INT", //24 + "MOV", //25 + "NOP", //26 + "reserved", //27 + "reserved", //28 + "reserved", //29 + "PRED_SETGT_UINT", //30 + "PRED_SETGE_UINT", //31 + "PRED_SETE", //32 + "PRED_SETGT", //33 + "PRED_SETGE", //34 + "PRED_SETNE", //35 + "PRED_SET_INV", //36 + "PRED_SET_POP", //37 + "PRED_SET_CLR", //38 + "PRED_SET_RESTORE", //39 + "PRED_SETE_PUSH", //40 + "PRED_SETGT_PUSH", //41 + "PRED_SETGE_PUSH", //42 + "PRED_SETNE_PUSH", //43 + "KILLE", //44 + "KILLGT", //45 + "KILLGE", //46 + "KILLNE", //47 + "AND_INT", //48 + "OR_INT", //49 + "XOR_INT", //50 + "NOT_INT", //51 + "ADD_INT", //52 + "SUB_INT", //53 + "MAX_INT", //54 + "MIN_INT", //55 + "MAX_UINT", //56 + "MIN_UINT", //57 + "SETE_INT", //58 + "SETGT_INT", //59 + "SETGE_INT", //60 + "SETNE_INT", //61 + "SETGT_UINT", //62 + "SETGE_UINT", //63 + "KILLGT_UINT", //64 + "KILLGE_UINT", //65 + "PRED_SETE_INT", //66 + "PRED_SETGT_INT", //67 + "PRED_SETGE_INT", //68 + "PRED_SETNE_INT", //69 + "PRED_SETLT_INT", //70 + "PRED_SETLE_INT", //71 + "KILLGE_INT", //72 + "KILLNE_INT", //73 + "PRED_SETE_PUSH_INT", //74 + "PRED_SETGT_PUSH_INT", //75 + "PRED_SETGE_PUSH_INT", //76 + "PRED_SETNE_PUSH_INT", //77 + "PRED_SETLT_PUSH_INT", //78 + "PRED_SETLE_PUSH_INT", //79 + "DOT4", //80 + "DOT4_IEEE", //81 + "CUBE", //82 + "MAX4", //83 + "invalid", //84 + "invalid", //85 + "invalid", //86 + "invalid", //87 + "invalid", //88 + "invalid", //89 + "invalid", //90 + "invalid", //91 + "invalid", //92 + "invalid", //93 + "invalid", //94 + "invalid", //95 + "MOVA_GPR_INT", //96 + "EXP_IEEE", //97 + "LOG_CLAMPED", //98 + "LOG_IEEE", //99 + "RECIP_CLAMPED", //100 + "RECIP_FF", //101 + "RECIP_IEEE", //102 + "RECIPSQRT_CLAMPED", //103 + "RECIPSQRT_FF", //104 + "RECIPSQRT_IEEE", //105 + "SQRT_IEEE", //106 + "FLT_TO_INT", //107 + "INT_TO_FLT", //108 + "UINT_TO_FLT", //109 + "SIN", //110 + "COS", //111 + "ASHR_INT", //112 + "LSHR_INT", //113 + "LSHL_INT", //114 + "MULLO_INT", //115 + "MULHI_INT", //116 + "MULLO_UINT", //117 + "MULHI_UINT", //118 + "RECIP_INT", //119 + "RECIP_UINT", //120 + "FLT_TO_UINT", //121 +}; + +static const char *op3[32] = { + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "reserved", + "reserved", + "reserved", + "reserved", + "MUL_LIT", + "MUL_LIT_M2", + "MUL_LIT_M4", + "MUL_LIT_D2", + "MULADD", + "MULADD_M2", + "MULADD_M4", + "MULADD_D2", + "MULADD_IEEE", + "MULADD_IEEE_M2", + "MULADD_IEEE_M4", + "MULADD_IEEE_D2", + "CNDE", + "CNDGT", + "CNDGE", + "reserved", + "CNDE_INT", + "CNDGT_INT", + "CNDGE_INT", + "reserved", +}; + +static const char *cond[4] = { + "ACTIVE", + "FALSE", + "BOOL", + "NOT_BOOL", +}; + +static const char *cf_op[25] = { + "NOP", + "TEX", + "VTX", + "VTX_TC", + "LOOP_START", + "LOOP_END", + "START_DX10", + "START_NO_AL", + "LOOP_CONTINUE", + "LOOP_BREAK", + "JUMP", + "PUSH", + "PUSH_ELSE", + "ELSE", + "POP", + "POP_JUMP", + "POP_PUSH", + "POP_PUSH_ELSE", + "CALL", + "SQ_CF_CALL_FS", + "RETURN", + "EMIT_VERTEX", + "EMIT_CUT_VERTEX", + "CUT_VERTEX", + "KILL", +}; + + + +static const char *cf_exp_op[41] = { + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "MEM_STREAM0", + "MEM_STREAM1", + "MEM_STREAM2", + "MEM_STREAM3", + "MEM_SCRATCH", + "MEM_REDUCTION", + "MEM_RING", + "EXPORT", + "EXPORT_DONE", +}; + + +static const char *sel[8] = { + "X", + "Y", + "Z", + "W", + "0", + "1", + "reserved", + "MASK", +}; + +static const char *cf_exp_type[8] = { + "PIXEL", + "POS", + "PARAM", + "unused", +}; + +static const char *cf_mem_type[8] = { + "EXPORT_WRITE", + "EXPORT_WRITE_IND", + "IMPORT_READ", + "IMPORT_READ_IND", +}; + +static const char *ab_pixel[62] = { + "CF_PIXEL_MRT0", + "CF_PIXEL_MRT1", + "CF_PIXEL_MRT2", + "CF_PIXEL_MRT3", + "CF_PIXEL_MRT4", + "CF_PIXEL_MRT5", + "CF_PIXEL_MRT6", + "CF_PIXEL_MRT7", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "CF_PIXEL_MRT0_FOG", + "CF_PIXEL_MRT1_FOG", + "CF_PIXEL_MRT2_FOG", + "CF_PIXEL_MRT3_FOG", + "CF_PIXEL_MRT4_FOG", + "CF_PIXEL_MRT5_FOG", + "CF_PIXEL_MRT6_FOG", + "CF_PIXEL_MRT7_FOG", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "CF_PIXEL_Z", +}; + +static const char *ab_pos[64] = { + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "invalid", + "CF_POS0", + "CF_POS1", + "CF_POS2", + "CF_POS3", +}; + +static const char *tex_op[32] = { + "SQ_TEX_INST_VTX_FETCH", + "SQ_TEX_INST_VTX_SEMANTIC", + "reserved", + "SQ_TEX_INST_LD", + "SQ_TEX_INST_GET_TEXTURE_RESINFO", + "SQ_TEX_INST_GET_NUMBER_OF_SAMPLES", + "SQ_TEX_INST_GET_LOD", + "SQ_TEX_INST_GET_GRADIENTS_H", + "SQ_TEX_INST_GET_GRADIENTS_V", + "SQ_TEX_INST_GET_LERP", + "reserved", + "SQ_TEX_INST_SET_GRADIENTS_H", + "SQ_TEX_INST_SET_GRADIENTS_V", + "SQ_TEX_INST_PASS", + "Z set index for array of cubemaps", + "reserved", + "SQ_TEX_INST_SAMPLE", + "SQ_TEX_INST_SAMPLE_L", + "SQ_TEX_INST_SAMPLE_LB", + "SQ_TEX_INST_SAMPLE_LZ", + "SQ_TEX_INST_SAMPLE_G", + "SQ_TEX_INST_SAMPLE_G_L", + "SQ_TEX_INST_SAMPLE_G_LB", + "SQ_TEX_INST_SAMPLE_G_LZ", + "SQ_TEX_INST_SAMPLE_C", + "SQ_TEX_INST_SAMPLE_C_L", + "SQ_TEX_INST_SAMPLE_C_LB", + "SQ_TEX_INST_SAMPLE_C_LZ", + "SQ_TEX_INST_SAMPLE_C_G", + "SQ_TEX_INST_SAMPLE_C_G_L", + "SQ_TEX_INST_SAMPLE_C_G_LB", + "SQ_TEX_INST_SAMPLE_C_G_LZ", +}; + +static const char *coord_type[2] = { + "TEX_UNNORMALIZED", + "TEX_NORMALIZED", +}; + +static const char *vtx_op[2] = { + "FETCH", + "SEMANTIC", +}; + +static const char *fetch_type[3] = { + "VERTEX_DATA", + "INSTANCE_DATA", + "NO_INDEX_OFFSET", +}; + +static const char *num_format_all[3] = { + "NORM", + "INT", + "SCALED", +}; + +static const char *format_comp_all[2] = { + "UNSIGNED", + "SIGNED", +}; + +static const char *srf_mode_all[2] = { + "ZERO_CLAMP_MINUS_ONE", + "NO_ZERO", +}; + +static const char *endian_swap[3] = { + "NONE", + "8IN16", + "8IN32", +}; + +static const char *km[4] = { + "SQ_CF_KCACHE_NOP", + "SQ_CF_KCACHE_LOCK_1", + "SQ_CF_KCACHE_LOCK_2", + "SQ_CF_KCACHE_LOCK_LOOP_INDEX", +}; diff --git a/src/r600_state.c b/src/r600_state.c index 397c5ad..ad8c711 100644 --- a/src/r600_state.c +++ b/src/r600_state.c @@ -370,6 +370,7 @@ const static struct radeon_asic r600_asic = { .ctx_draw = r600_ctx_draw, .ctx_get_dst_surface = r600_ctx_get_dst_surface, .ctx_next_reloc = r600_ctx_next_reloc, + .ctx_disassemble = r600_ctx_disassemble, }; int r600_init(struct radeon *radeon) diff --git a/src/radeon.c b/src/radeon.c index 291ada0..415aeb8 100644 --- a/src/radeon.c +++ b/src/radeon.c @@ -44,28 +44,13 @@ int radeon_open_fd(void) return drmOpen("radeon", NULL); } -struct radeon *radeon_new(int fd, unsigned device) +int radeon_initialize_family(struct radeon *radeon, unsigned device) { - struct radeon *radeon; - int r; - - radeon = calloc(1, sizeof(*radeon)); - if (radeon == NULL) - return NULL; - radeon->fd = fd; radeon->device = device; - radeon->refcount = 1; - if (fd >= 0) { - r = radeon_get_device(radeon); - if (r) { - fprintf(stderr, "Failed to get device id\n"); - return radeon_decref(radeon); - } - } radeon->family = radeon_family_from_device(radeon->device); if (radeon->family == CHIP_UNKNOWN) { fprintf(stderr, "Unknown chipset 0x%04X\n", radeon->device); - return radeon_decref(radeon); + return -EINVAL; } switch (radeon->family) { case CHIP_R600: @@ -80,10 +65,7 @@ struct radeon *radeon_new(int fd, unsigned device) case CHIP_RV730: case CHIP_RV710: case CHIP_RV740: - if (r600_init(radeon)) { - return radeon_decref(radeon); - } - break; + return r600_init(radeon); case CHIP_R100: case CHIP_RV100: case CHIP_RS100: @@ -119,7 +101,32 @@ struct radeon *radeon_new(int fd, unsigned device) default: fprintf(stderr, "%s unknown or unsupported chipset 0x%04X\n", __func__, radeon->device); - break; + return -EINVAL; + } +} + +struct radeon *radeon_new(int fd, unsigned device) +{ + struct radeon *radeon; + int r; + + radeon = calloc(1, sizeof(*radeon)); + if (radeon == NULL) + return NULL; + radeon->fd = fd; + radeon->device = device; + radeon->refcount = 1; + if (fd >= 0) { + r = radeon_get_device(radeon); + if (r) { + fprintf(stderr, "Failed to get device id\n"); + return radeon_decref(radeon); + } + } + if (radeon->device) { + if (radeon_initialize_family(radeon, radeon->device)) { + return radeon_decref(radeon); + } } if (radeon->fd >= 0) { /* FIXME compile time enable */ diff --git a/src/radeon_bo.c b/src/radeon_bo.c index 32134b6..d08816b 100644 --- a/src/radeon_bo.c +++ b/src/radeon_bo.c @@ -48,6 +48,18 @@ struct radeon_bo *radeon_bo(struct radeon *radeon, unsigned handle, bo->handle = handle; bo->refcount = 1; bo->alignment = alignment; + if (radeon->fd == -1) { + bo->handle = radeon->fake_handle++; + bo->data = calloc(1, bo->size); + if (bo->data == NULL) { + free(bo); + return NULL; + } + bo->map_count = 1; + if (ptr) + memcpy(bo->data, ptr, size); + return bo; + } if (handle) { struct drm_gem_open open_arg; @@ -125,8 +137,10 @@ void radeon_bo_unmap(struct radeon *radeon, struct radeon_bo *bo) if (--bo->map_count > 0) { return; } - munmap(bo->data, bo->size); - bo->data = NULL; + if (radeon->fd != -1) { + munmap(bo->data, bo->size); + bo->data = NULL; + } } struct radeon_bo *radeon_bo_incref(struct radeon *radeon, struct radeon_bo *bo) @@ -145,10 +159,14 @@ struct radeon_bo *radeon_bo_decref(struct radeon *radeon, struct radeon_bo *bo) return NULL; } - munmap(bo->data, bo->size); - memset(&args, 0, sizeof(args)); - args.handle = bo->handle; - drmIoctl(radeon->fd, DRM_IOCTL_GEM_CLOSE, &args); + if (radeon->fd != -1) { + munmap(bo->data, bo->size); + memset(&args, 0, sizeof(args)); + args.handle = bo->handle; + drmIoctl(radeon->fd, DRM_IOCTL_GEM_CLOSE, &args); + } else { + free(bo->data); + } memset(bo, 0, sizeof(struct radeon_bo)); free(bo); return NULL; @@ -159,6 +177,8 @@ int radeon_bo_wait(struct radeon *radeon, struct radeon_bo *bo) struct drm_radeon_gem_wait_idle args; int ret; + if (radeon->fd == -1) + return 0; /* Zero out args to make valgrind happy */ memset(&args, 0, sizeof(args)); args.handle = bo->handle; diff --git a/src/radeon_bof.c b/src/radeon_bof.c index a0a8708..f252d92 100644 --- a/src/radeon_bof.c +++ b/src/radeon_bof.c @@ -55,6 +55,11 @@ struct radeon_ctx *radeon_ctx_load_bof(struct radeon *radeon, const char *filena goto out_err; } device = bof_int32_value(tmp); + if (!radeon->device) { + r = radeon_initialize_family(radeon, device); + if (r) + goto out_err; + } ctx = radeon_ctx(radeon); if (ctx == NULL) { fprintf(stderr, "%s failed to create context\n", __func__); diff --git a/src/radeon_json.c b/src/radeon_json.c index 2769a08..82087de 100644 --- a/src/radeon_json.c +++ b/src/radeon_json.c @@ -86,6 +86,13 @@ int radeon_ctx_dump_json(struct radeon_ctx *ctx, const char *filename) if (json_array_append_new(jarray, bo)) { goto out_err; } + value = json_integer(i); + if (value == NULL) { + goto out_err; + } + if (json_object_set_new(bo, "objectid", value)) { + goto out_err; + } value = json_integer(ctx->bo[i]->size); if (value == NULL) { goto out_err; @@ -363,6 +370,11 @@ struct radeon_ctx *radeon_ctx_load_json(struct radeon *radeon, const char *filen goto out_err; } device = json_integer_value(tmp); + if (!radeon->device) { + r = radeon_initialize_family(radeon, device); + if (r) + goto out_err; + } ctx = radeon_ctx(radeon); if (ctx == NULL) { goto out_err; @@ -414,7 +426,7 @@ struct radeon_ctx *radeon_ctx_load_json(struct radeon *radeon, const char *filen if (placement == NULL || !json_is_array(placement)) { goto out_err; } - for (j = 0; j < size / 4; j++) { + for (j = 0; j < json_array_size(placement); j++) { tmp = json_array_get(placement, j); if (tmp == NULL) { goto out_err; diff --git a/src/radeon_priv.h b/src/radeon_priv.h index 190cacb..0067998 100644 --- a/src/radeon_priv.h +++ b/src/radeon_priv.h @@ -46,6 +46,7 @@ struct radeon_asic { int (*ctx_draw)(struct radeon_ctx *ctx); int (*ctx_get_dst_surface)(struct radeon_ctx *ctx, struct radeon_surface *dst); int (*ctx_next_reloc)(struct radeon_ctx *ctx, unsigned *reloc); + void (*ctx_disassemble)(struct radeon_ctx *ctx); }; /* @@ -122,6 +123,7 @@ struct radeon { pciaddr_t mmio_base; pciaddr_t mmio_size; uint8_t *bios; + u32 fake_handle; }; extern int radeon_open_fd(void); @@ -133,6 +135,7 @@ extern int radeon_is_family_compatible(unsigned family1, unsigned family2); extern int radeon_reg_id(struct radeon *radeon, unsigned offset, unsigned *typeid, unsigned *stateid, unsigned *id); extern unsigned radeon_type_from_id(struct radeon *radeon, unsigned id); extern int radeon_schedule_draw(struct radeon *radeon, struct radeon_draw *draw); +extern int radeon_initialize_family(struct radeon *radeon, unsigned device); /* * radeon context functions @@ -179,6 +182,7 @@ extern int r600_init(struct radeon *radeon); extern int r600_ctx_draw(struct radeon_ctx *ctx); extern int r600_ctx_next_reloc(struct radeon_ctx *ctx, unsigned *reloc); extern int r600_ctx_get_dst_surface(struct radeon_ctx *ctx, struct radeon_surface *dst); +extern void r600_ctx_disassemble(struct radeon_ctx *ctx); /* * radeon state functions @@ -225,5 +229,6 @@ struct radeon *radeon_new_from_pci(void); #define radeon_ctx_get_dst_surface(ctx, dst) (ctx)->radeon->asic->ctx_get_dst_surface((ctx), (dst)) #define radeon_ctx_next_reloc(ctx, reloc) (ctx)->radeon->asic->ctx_next_reloc(ctx, reloc) +#define radeon_ctx_disassemble(ctx) (ctx)->radeon->asic->ctx_disassemble(ctx) #endif diff --git a/src/radeondb.c b/src/radeondb.c index 427b529..7b4ac0c 100644 --- a/src/radeondb.c +++ b/src/radeondb.c @@ -40,6 +40,10 @@ void usage(void) printf(" -j replay json command stream\n"); printf(" -p replay command stream\n"); printf(" -d dump command stream in raw hex\n"); + printf(" -r register dump (block to dump DISP, MC, ...)\n"); + printf(" -c convert bof file to json\n"); + printf(" -b benchmark (valid with -j or -p)\n"); + printf(" -s disassemble shader\n"); } static int conv(const char *file); @@ -47,15 +51,18 @@ static int json(const char *file, int bench); static int play(const char *file, int bench); static int dump(const char *file); void radeon_register_dump(const char *bname); +static int shader(const char *file); struct param { char file_json[256]; char file_play[256]; char file_conv[256]; char file_dump[256]; + char file_shader[256]; char block[256]; int bench; int json; + int shader; int play; int conv; int dump; @@ -70,6 +77,7 @@ int main(int argc, char *argv[]) {"dump", required_argument, 0, 'd'}, {"conv", required_argument, 0, 'c'}, {"reg", required_argument, 0, 'r'}, + {"shader", required_argument, 0, 's'}, {0, 0, 0, 0} }; int option_id; @@ -78,7 +86,7 @@ int main(int argc, char *argv[]) memset(&p, 0, sizeof(struct param)); while (1) { - c = getopt_long(argc, argv, "p:d:j:c:r:b", options, &option_id); + c = getopt_long(argc, argv, "p:d:j:c:r:bs:", options, &option_id); if (c == -1) break; switch (c) { @@ -89,6 +97,10 @@ int main(int argc, char *argv[]) case 'b': p.bench = 1; break; + case 's': + strcpy(p.file_shader, optarg); + p.shader = 1; + break; case 'j': strcpy(p.file_json, optarg); p.json = 1; @@ -127,6 +139,9 @@ int main(int argc, char *argv[]) if (p.conv) { return conv(p.file_conv); } + if (p.shader) { + return shader(p.file_shader); + } } static int play(const char *file, int bench) @@ -211,12 +226,7 @@ static int dump(const char *file) unsigned i; int fd; - fd = radeon_open_fd(); - if (fd < 0) { - fprintf(stderr, "failed to open radeon drm device\n"); - return -1; - } - radeon = radeon_new(fd, 0); + radeon = radeon_new(-1, 0); ctx = radeon_ctx_load_bof(radeon, file); if (ctx == NULL) { fprintf(stderr, "failed to read bof file %s\n", file); @@ -310,14 +320,9 @@ static int conv(const char *file) struct radeon *radeon; char *tmp; char name[256]; - int r, fd; + int r; - fd = radeon_open_fd(); - if (fd < 0) { - fprintf(stderr, "failed to open radeon drm device\n"); - return -1; - } - radeon = radeon_new(fd, 0); + radeon = radeon_new(-1, 0); if (radeon == NULL) { fprintf(stderr, "failed to initialize radeon\n"); return -1; @@ -343,3 +348,27 @@ static int conv(const char *file) ctx = radeon_ctx_decref(ctx); return r; } + +static int shader(const char *file) +{ + struct radeon *radeon; + struct radeon_ctx *ctx = NULL; + int r = 0, i; + + radeon = radeon_new(-1, 0); + if (radeon == NULL) { + fprintf(stderr, "failed to initialize radeon\n"); + return -1; + } + ctx = radeon_ctx_load_json(radeon, file); + if (ctx == NULL) { + fprintf(stderr, "failed to read bof file %s\n", file); + r = -EINVAL; + goto out; + } + radeon_ctx_disassemble(ctx); +out: + ctx = radeon_ctx_decref(ctx); + radeon_decref(radeon); + return r; +} |