summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerome Glisse <jglisse@redhat.com>2010-04-28 14:59:23 +0200
committerJerome Glisse <jglisse@redhat.com>2010-04-28 14:59:23 +0200
commit35c56944dfe5ca34677e39fdc0ebdab15c00b442 (patch)
tree612647786d1c1eae06178b3c7fac27c0b96005e4
parent17150fac6c9ea4b9bb22893211cd900bc2601d74 (diff)
radeondb: add r6xx/r7xx shader disassembler
Signed-off-by: Jerome Glisse <jglisse@redhat.com>
-rw-r--r--src/Makefile.am3
-rw-r--r--src/r600_disassembler.c1236
-rw-r--r--src/r600_state.c1
-rw-r--r--src/radeon.c51
-rw-r--r--src/radeon_bo.c32
-rw-r--r--src/radeon_bof.c5
-rw-r--r--src/radeon_json.c14
-rw-r--r--src/radeon_priv.h5
-rw-r--r--src/radeondb.c57
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;
+}