diff options
author | Rob Clark <[email protected]> | 2018-07-09 10:14:14 -0400 |
---|---|---|
committer | Rob Clark <[email protected]> | 2018-07-18 10:10:45 -0400 |
commit | 4c58db806449ec4e4cf14c1ffdce60ad5ac12adc (patch) | |
tree | 2381ca7e367247391dc2f0fa4561eb816c3a6d40 | |
parent | 97a9283f5dbbc78d48d6b0a21fdcab991328bc0f (diff) |
freedreno/ir3: resync ir3 disassembler
Pull in latest updates from cffdump in envytools tree, so we can output
to other than just stdout.
Signed-off-by: Rob Clark <[email protected]>
-rw-r--r-- | src/gallium/drivers/freedreno/disasm.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/ir3/disasm-a3xx.c | 391 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/ir3/instr-a3xx.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/ir3/ir3_shader.c | 4 |
4 files changed, 209 insertions, 191 deletions
diff --git a/src/gallium/drivers/freedreno/disasm.h b/src/gallium/drivers/freedreno/disasm.h index 579dd503a6e..3266c6a484f 100644 --- a/src/gallium/drivers/freedreno/disasm.h +++ b/src/gallium/drivers/freedreno/disasm.h @@ -24,6 +24,8 @@ #ifndef DISASM_H_ #define DISASM_H_ +#include <stdio.h> + enum shader_t { SHADER_VERTEX, SHADER_TCS, @@ -41,7 +43,7 @@ enum debug_t { }; int disasm_a2xx(uint32_t *dwords, int sizedwords, int level, enum shader_t type); -int disasm_a3xx(uint32_t *dwords, int sizedwords, int level, enum shader_t type); +int disasm_a3xx(uint32_t *dwords, int sizedwords, int level, FILE *out); void disasm_set_debug(enum debug_t debug); #endif /* DISASM_H_ */ diff --git a/src/gallium/drivers/freedreno/ir3/disasm-a3xx.c b/src/gallium/drivers/freedreno/ir3/disasm-a3xx.c index 5499e19b446..247175f142c 100644 --- a/src/gallium/drivers/freedreno/ir3/disasm-a3xx.c +++ b/src/gallium/drivers/freedreno/ir3/disasm-a3xx.c @@ -24,6 +24,7 @@ #include <stdio.h> #include <stdlib.h> #include <stdint.h> +#include <stdbool.h> #include <string.h> #include <assert.h> @@ -68,8 +69,16 @@ static const char *type[] = { [TYPE_S8] = "s8", }; -static void print_reg(reg_t reg, bool full, bool r, bool c, bool im, - bool neg, bool abs, bool addr_rel) +struct disasm_ctx { + FILE *out; + int level; + + /* current instruction repeat flag: */ + unsigned repeat; +}; + +static void print_reg(struct disasm_ctx *ctx, reg_t reg, bool full, bool r, + bool c, bool im, bool neg, bool abs, bool addr_rel) { const char type = c ? 'c' : 'r'; @@ -77,49 +86,46 @@ static void print_reg(reg_t reg, bool full, bool r, bool c, bool im, // by libllvm-a3xx for easy diffing.. if (abs && neg) - printf("(absneg)"); + fprintf(ctx->out, "(absneg)"); else if (neg) - printf("(neg)"); + fprintf(ctx->out, "(neg)"); else if (abs) - printf("(abs)"); + fprintf(ctx->out, "(abs)"); if (r) - printf("(r)"); + fprintf(ctx->out, "(r)"); if (im) { - printf("%d", reg.iim_val); + fprintf(ctx->out, "%d", reg.iim_val); } else if (addr_rel) { /* I would just use %+d but trying to make it diff'able with * libllvm-a3xx... */ if (reg.iim_val < 0) - printf("%s%c<a0.x - %d>", full ? "" : "h", type, -reg.iim_val); + fprintf(ctx->out, "%s%c<a0.x - %d>", full ? "" : "h", type, -reg.iim_val); else if (reg.iim_val > 0) - printf("%s%c<a0.x + %d>", full ? "" : "h", type, reg.iim_val); + fprintf(ctx->out, "%s%c<a0.x + %d>", full ? "" : "h", type, reg.iim_val); else - printf("%s%c<a0.x>", full ? "" : "h", type); + fprintf(ctx->out, "%s%c<a0.x>", full ? "" : "h", type); } else if ((reg.num == REG_A0) && !c) { - printf("a0.%c", component[reg.comp]); + fprintf(ctx->out, "a0.%c", component[reg.comp]); } else if ((reg.num == REG_P0) && !c) { - printf("p0.%c", component[reg.comp]); + fprintf(ctx->out, "p0.%c", component[reg.comp]); } else { - printf("%s%c%d.%c", full ? "" : "h", type, reg.num & 0x3f, component[reg.comp]); + fprintf(ctx->out, "%s%c%d.%c", full ? "" : "h", type, reg.num & 0x3f, component[reg.comp]); } } -/* current instruction repeat flag: */ -static unsigned repeat; - -static void print_reg_dst(reg_t reg, bool full, bool addr_rel) +static void print_reg_dst(struct disasm_ctx *ctx, reg_t reg, bool full, bool addr_rel) { - print_reg(reg, full, false, false, false, false, false, addr_rel); + print_reg(ctx, reg, full, false, false, false, false, false, addr_rel); } -static void print_reg_src(reg_t reg, bool full, bool r, bool c, bool im, - bool neg, bool abs, bool addr_rel) +static void print_reg_src(struct disasm_ctx *ctx, reg_t reg, bool full, bool r, + bool c, bool im, bool neg, bool abs, bool addr_rel) { - print_reg(reg, full, r, c, im, neg, abs, addr_rel); + print_reg(ctx, reg, full, r, c, im, neg, abs, addr_rel); } /* TODO switch to using reginfo struct everywhere, since more readable @@ -137,100 +143,100 @@ struct reginfo { bool addr_rel; }; -static void print_src(struct reginfo *info) +static void print_src(struct disasm_ctx *ctx, struct reginfo *info) { - print_reg_src(info->reg, info->full, info->r, info->c, info->im, + print_reg_src(ctx, info->reg, info->full, info->r, info->c, info->im, info->neg, info->abs, info->addr_rel); } -//static void print_dst(struct reginfo *info) +//static void print_dst(struct disasm_ctx *ctx, struct reginfo *info) //{ -// print_reg_dst(info->reg, info->full, info->addr_rel); +// print_reg_dst(ctx, info->reg, info->full, info->addr_rel); //} -static void print_instr_cat0(instr_t *instr) +static void print_instr_cat0(struct disasm_ctx *ctx, instr_t *instr) { instr_cat0_t *cat0 = &instr->cat0; switch (cat0->opc) { case OPC_KILL: - printf(" %sp0.%c", cat0->inv ? "!" : "", + fprintf(ctx->out, " %sp0.%c", cat0->inv ? "!" : "", component[cat0->comp]); break; case OPC_BR: - printf(" %sp0.%c, #%d", cat0->inv ? "!" : "", + fprintf(ctx->out, " %sp0.%c, #%d", cat0->inv ? "!" : "", component[cat0->comp], cat0->a3xx.immed); break; case OPC_JUMP: case OPC_CALL: - printf(" #%d", cat0->a3xx.immed); + fprintf(ctx->out, " #%d", cat0->a3xx.immed); break; } if ((debug & PRINT_VERBOSE) && (cat0->dummy2|cat0->dummy3|cat0->dummy4)) - printf("\t{0: %x,%x,%x}", cat0->dummy2, cat0->dummy3, cat0->dummy4); + fprintf(ctx->out, "\t{0: %x,%x,%x}", cat0->dummy2, cat0->dummy3, cat0->dummy4); } -static void print_instr_cat1(instr_t *instr) +static void print_instr_cat1(struct disasm_ctx *ctx, instr_t *instr) { instr_cat1_t *cat1 = &instr->cat1; if (cat1->ul) - printf("(ul)"); + fprintf(ctx->out, "(ul)"); if (cat1->src_type == cat1->dst_type) { if ((cat1->src_type == TYPE_S16) && (((reg_t)cat1->dst).num == REG_A0)) { /* special case (nmemonic?): */ - printf("mova"); + fprintf(ctx->out, "mova"); } else { - printf("mov.%s%s", type[cat1->src_type], type[cat1->dst_type]); + fprintf(ctx->out, "mov.%s%s", type[cat1->src_type], type[cat1->dst_type]); } } else { - printf("cov.%s%s", type[cat1->src_type], type[cat1->dst_type]); + fprintf(ctx->out, "cov.%s%s", type[cat1->src_type], type[cat1->dst_type]); } - printf(" "); + fprintf(ctx->out, " "); if (cat1->even) - printf("(even)"); + fprintf(ctx->out, "(even)"); if (cat1->pos_inf) - printf("(pos_infinity)"); + fprintf(ctx->out, "(pos_infinity)"); - print_reg_dst((reg_t)(cat1->dst), type_size(cat1->dst_type) == 32, + print_reg_dst(ctx, (reg_t)(cat1->dst), type_size(cat1->dst_type) == 32, cat1->dst_rel); - printf(", "); + fprintf(ctx->out, ", "); /* ugg, have to special case this.. vs print_reg().. */ if (cat1->src_im) { if (type_float(cat1->src_type)) - printf("(%f)", cat1->fim_val); + fprintf(ctx->out, "(%f)", cat1->fim_val); else if (type_uint(cat1->src_type)) - printf("0x%08x", cat1->uim_val); + fprintf(ctx->out, "0x%08x", cat1->uim_val); else - printf("%d", cat1->iim_val); + fprintf(ctx->out, "%d", cat1->iim_val); } else if (cat1->src_rel && !cat1->src_c) { /* I would just use %+d but trying to make it diff'able with * libllvm-a3xx... */ char type = cat1->src_rel_c ? 'c' : 'r'; if (cat1->off < 0) - printf("%c<a0.x - %d>", type, -cat1->off); + fprintf(ctx->out, "%c<a0.x - %d>", type, -cat1->off); else if (cat1->off > 0) - printf("%c<a0.x + %d>", type, cat1->off); + fprintf(ctx->out, "%c<a0.x + %d>", type, cat1->off); else - printf("%c<a0.x>", type); + fprintf(ctx->out, "%c<a0.x>", type); } else { - print_reg_src((reg_t)(cat1->src), type_size(cat1->src_type) == 32, + print_reg_src(ctx, (reg_t)(cat1->src), type_size(cat1->src_type) == 32, cat1->src_r, cat1->src_c, cat1->src_im, false, false, false); } if ((debug & PRINT_VERBOSE) && (cat1->must_be_0)) - printf("\t{1: %x}", cat1->must_be_0); + fprintf(ctx->out, "\t{1: %x}", cat1->must_be_0); } -static void print_instr_cat2(instr_t *instr) +static void print_instr_cat2(struct disasm_ctx *ctx, instr_t *instr) { instr_cat2_t *cat2 = &instr->cat2; static const char *cond[] = { @@ -250,26 +256,26 @@ static void print_instr_cat2(instr_t *instr) case OPC_CMPV_F: case OPC_CMPV_U: case OPC_CMPV_S: - printf(".%s", cond[cat2->cond]); + fprintf(ctx->out, ".%s", cond[cat2->cond]); break; } - printf(" "); + fprintf(ctx->out, " "); if (cat2->ei) - printf("(ei)"); - print_reg_dst((reg_t)(cat2->dst), cat2->full ^ cat2->dst_half, false); - printf(", "); + fprintf(ctx->out, "(ei)"); + print_reg_dst(ctx, (reg_t)(cat2->dst), cat2->full ^ cat2->dst_half, false); + fprintf(ctx->out, ", "); if (cat2->c1.src1_c) { - print_reg_src((reg_t)(cat2->c1.src1), cat2->full, cat2->src1_r, + print_reg_src(ctx, (reg_t)(cat2->c1.src1), cat2->full, cat2->src1_r, cat2->c1.src1_c, cat2->src1_im, cat2->src1_neg, cat2->src1_abs, false); } else if (cat2->rel1.src1_rel) { - print_reg_src((reg_t)(cat2->rel1.src1), cat2->full, cat2->src1_r, + print_reg_src(ctx, (reg_t)(cat2->rel1.src1), cat2->full, cat2->src1_r, cat2->rel1.src1_c, cat2->src1_im, cat2->src1_neg, cat2->src1_abs, cat2->rel1.src1_rel); } else { - print_reg_src((reg_t)(cat2->src1), cat2->full, cat2->src1_r, + print_reg_src(ctx, (reg_t)(cat2->src1), cat2->full, cat2->src1_r, false, cat2->src1_im, cat2->src1_neg, cat2->src1_abs, false); } @@ -292,17 +298,17 @@ static void print_instr_cat2(instr_t *instr) /* these only have one src reg */ break; default: - printf(", "); + fprintf(ctx->out, ", "); if (cat2->c2.src2_c) { - print_reg_src((reg_t)(cat2->c2.src2), cat2->full, cat2->src2_r, + print_reg_src(ctx, (reg_t)(cat2->c2.src2), cat2->full, cat2->src2_r, cat2->c2.src2_c, cat2->src2_im, cat2->src2_neg, cat2->src2_abs, false); } else if (cat2->rel2.src2_rel) { - print_reg_src((reg_t)(cat2->rel2.src2), cat2->full, cat2->src2_r, + print_reg_src(ctx, (reg_t)(cat2->rel2.src2), cat2->full, cat2->src2_r, cat2->rel2.src2_c, cat2->src2_im, cat2->src2_neg, cat2->src2_abs, cat2->rel2.src2_rel); } else { - print_reg_src((reg_t)(cat2->src2), cat2->full, cat2->src2_r, + print_reg_src(ctx, (reg_t)(cat2->src2), cat2->full, cat2->src2_r, false, cat2->src2_im, cat2->src2_neg, cat2->src2_abs, false); } @@ -310,74 +316,74 @@ static void print_instr_cat2(instr_t *instr) } } -static void print_instr_cat3(instr_t *instr) +static void print_instr_cat3(struct disasm_ctx *ctx, instr_t *instr) { instr_cat3_t *cat3 = &instr->cat3; bool full = instr_cat3_full(cat3); - printf(" "); - print_reg_dst((reg_t)(cat3->dst), full ^ cat3->dst_half, false); - printf(", "); + fprintf(ctx->out, " "); + print_reg_dst(ctx, (reg_t)(cat3->dst), full ^ cat3->dst_half, false); + fprintf(ctx->out, ", "); if (cat3->c1.src1_c) { - print_reg_src((reg_t)(cat3->c1.src1), full, + print_reg_src(ctx, (reg_t)(cat3->c1.src1), full, cat3->src1_r, cat3->c1.src1_c, false, cat3->src1_neg, false, false); } else if (cat3->rel1.src1_rel) { - print_reg_src((reg_t)(cat3->rel1.src1), full, + print_reg_src(ctx, (reg_t)(cat3->rel1.src1), full, cat3->src1_r, cat3->rel1.src1_c, false, cat3->src1_neg, false, cat3->rel1.src1_rel); } else { - print_reg_src((reg_t)(cat3->src1), full, + print_reg_src(ctx, (reg_t)(cat3->src1), full, cat3->src1_r, false, false, cat3->src1_neg, false, false); } - printf(", "); - print_reg_src((reg_t)cat3->src2, full, + fprintf(ctx->out, ", "); + print_reg_src(ctx, (reg_t)cat3->src2, full, cat3->src2_r, cat3->src2_c, false, cat3->src2_neg, false, false); - printf(", "); + fprintf(ctx->out, ", "); if (cat3->c2.src3_c) { - print_reg_src((reg_t)(cat3->c2.src3), full, + print_reg_src(ctx, (reg_t)(cat3->c2.src3), full, cat3->src3_r, cat3->c2.src3_c, false, cat3->src3_neg, false, false); } else if (cat3->rel2.src3_rel) { - print_reg_src((reg_t)(cat3->rel2.src3), full, + print_reg_src(ctx, (reg_t)(cat3->rel2.src3), full, cat3->src3_r, cat3->rel2.src3_c, false, cat3->src3_neg, false, cat3->rel2.src3_rel); } else { - print_reg_src((reg_t)(cat3->src3), full, + print_reg_src(ctx, (reg_t)(cat3->src3), full, cat3->src3_r, false, false, cat3->src3_neg, false, false); } } -static void print_instr_cat4(instr_t *instr) +static void print_instr_cat4(struct disasm_ctx *ctx, instr_t *instr) { instr_cat4_t *cat4 = &instr->cat4; - printf(" "); - print_reg_dst((reg_t)(cat4->dst), cat4->full ^ cat4->dst_half, false); - printf(", "); + fprintf(ctx->out, " "); + print_reg_dst(ctx, (reg_t)(cat4->dst), cat4->full ^ cat4->dst_half, false); + fprintf(ctx->out, ", "); if (cat4->c.src_c) { - print_reg_src((reg_t)(cat4->c.src), cat4->full, + print_reg_src(ctx, (reg_t)(cat4->c.src), cat4->full, cat4->src_r, cat4->c.src_c, cat4->src_im, cat4->src_neg, cat4->src_abs, false); } else if (cat4->rel.src_rel) { - print_reg_src((reg_t)(cat4->rel.src), cat4->full, + print_reg_src(ctx, (reg_t)(cat4->rel.src), cat4->full, cat4->src_r, cat4->rel.src_c, cat4->src_im, cat4->src_neg, cat4->src_abs, cat4->rel.src_rel); } else { - print_reg_src((reg_t)(cat4->src), cat4->full, + print_reg_src(ctx, (reg_t)(cat4->src), cat4->full, cat4->src_r, false, cat4->src_im, cat4->src_neg, cat4->src_abs, false); } if ((debug & PRINT_VERBOSE) && (cat4->dummy1|cat4->dummy2)) - printf("\t{4: %x,%x}", cat4->dummy1, cat4->dummy2); + fprintf(ctx->out, "\t{4: %x,%x}", cat4->dummy1, cat4->dummy2); } -static void print_instr_cat5(instr_t *instr) +static void print_instr_cat5(struct disasm_ctx *ctx, instr_t *instr) { static const struct { bool src1, src2, samp, tex; @@ -414,69 +420,69 @@ static void print_instr_cat5(instr_t *instr) instr_cat5_t *cat5 = &instr->cat5; int i; - if (cat5->is_3d) printf(".3d"); - if (cat5->is_a) printf(".a"); - if (cat5->is_o) printf(".o"); - if (cat5->is_p) printf(".p"); - if (cat5->is_s) printf(".s"); - if (cat5->is_s2en) printf(".s2en"); + if (cat5->is_3d) fprintf(ctx->out, ".3d"); + if (cat5->is_a) fprintf(ctx->out, ".a"); + if (cat5->is_o) fprintf(ctx->out, ".o"); + if (cat5->is_p) fprintf(ctx->out, ".p"); + if (cat5->is_s) fprintf(ctx->out, ".s"); + if (cat5->is_s2en) fprintf(ctx->out, ".s2en"); - printf(" "); + fprintf(ctx->out, " "); switch (_OPC(5, cat5->opc)) { case OPC_DSXPP_1: case OPC_DSYPP_1: break; default: - printf("(%s)", type[cat5->type]); + fprintf(ctx->out, "(%s)", type[cat5->type]); break; } - printf("("); + fprintf(ctx->out, "("); for (i = 0; i < 4; i++) if (cat5->wrmask & (1 << i)) - printf("%c", "xyzw"[i]); - printf(")"); + fprintf(ctx->out, "%c", "xyzw"[i]); + fprintf(ctx->out, ")"); - print_reg_dst((reg_t)(cat5->dst), type_size(cat5->type) == 32, false); + print_reg_dst(ctx, (reg_t)(cat5->dst), type_size(cat5->type) == 32, false); if (info[cat5->opc].src1) { - printf(", "); - print_reg_src((reg_t)(cat5->src1), cat5->full, false, false, false, + fprintf(ctx->out, ", "); + print_reg_src(ctx, (reg_t)(cat5->src1), cat5->full, false, false, false, false, false, false); } if (cat5->is_s2en) { - printf(", "); - print_reg_src((reg_t)(cat5->s2en.src2), cat5->full, false, false, false, + fprintf(ctx->out, ", "); + print_reg_src(ctx, (reg_t)(cat5->s2en.src2), cat5->full, false, false, false, false, false, false); - printf(", "); - print_reg_src((reg_t)(cat5->s2en.src3), false, false, false, false, + fprintf(ctx->out, ", "); + print_reg_src(ctx, (reg_t)(cat5->s2en.src3), false, false, false, false, false, false, false); } else { if (cat5->is_o || info[cat5->opc].src2) { - printf(", "); - print_reg_src((reg_t)(cat5->norm.src2), cat5->full, + fprintf(ctx->out, ", "); + print_reg_src(ctx, (reg_t)(cat5->norm.src2), cat5->full, false, false, false, false, false, false); } if (info[cat5->opc].samp) - printf(", s#%d", cat5->norm.samp); + fprintf(ctx->out, ", s#%d", cat5->norm.samp); if (info[cat5->opc].tex) - printf(", t#%d", cat5->norm.tex); + fprintf(ctx->out, ", t#%d", cat5->norm.tex); } if (debug & PRINT_VERBOSE) { if (cat5->is_s2en) { if ((debug & PRINT_VERBOSE) && (cat5->s2en.dummy1|cat5->s2en.dummy2|cat5->dummy2)) - printf("\t{5: %x,%x,%x}", cat5->s2en.dummy1, cat5->s2en.dummy2, cat5->dummy2); + fprintf(ctx->out, "\t{5: %x,%x,%x}", cat5->s2en.dummy1, cat5->s2en.dummy2, cat5->dummy2); } else { if ((debug & PRINT_VERBOSE) && (cat5->norm.dummy1|cat5->dummy2)) - printf("\t{5: %x,%x}", cat5->norm.dummy1, cat5->dummy2); + fprintf(ctx->out, "\t{5: %x,%x}", cat5->norm.dummy1, cat5->dummy2); } } } -static void print_instr_cat6(instr_t *instr) +static void print_instr_cat6(struct disasm_ctx *ctx, instr_t *instr) { instr_cat6_t *cat6 = &instr->cat6; char sd = 0, ss = 0; /* dst/src address space */ @@ -522,20 +528,20 @@ static void print_instr_cat6(instr_t *instr) case OPC_PREFETCH: break; case OPC_RESINFO: - printf(".%dd", cat6->ldgb.d + 1); + fprintf(ctx->out, ".%dd", cat6->ldgb.d + 1); break; case OPC_LDGB: - printf(".%s", cat6->ldgb.typed ? "typed" : "untyped"); - printf(".%dd", cat6->ldgb.d + 1); - printf(".%s", type[cat6->type]); - printf(".%d", cat6->ldgb.type_size + 1); + fprintf(ctx->out, ".%s", cat6->ldgb.typed ? "typed" : "untyped"); + fprintf(ctx->out, ".%dd", cat6->ldgb.d + 1); + fprintf(ctx->out, ".%s", type[cat6->type]); + fprintf(ctx->out, ".%d", cat6->ldgb.type_size + 1); break; case OPC_STGB: case OPC_STIB: - printf(".%s", cat6->stgb.typed ? "typed" : "untyped"); - printf(".%dd", cat6->stgb.d + 1); - printf(".%s", type[cat6->type]); - printf(".%d", cat6->stgb.type_size + 1); + fprintf(ctx->out, ".%s", cat6->stgb.typed ? "typed" : "untyped"); + fprintf(ctx->out, ".%dd", cat6->stgb.d + 1); + fprintf(ctx->out, ".%s", type[cat6->type]); + fprintf(ctx->out, ".%d", cat6->stgb.type_size + 1); break; case OPC_ATOMIC_ADD: case OPC_ATOMIC_SUB: @@ -549,18 +555,18 @@ static void print_instr_cat6(instr_t *instr) case OPC_ATOMIC_OR: case OPC_ATOMIC_XOR: ss = cat6->g ? 'g' : 'l'; - printf(".%s", cat6->ldgb.typed ? "typed" : "untyped"); - printf(".%dd", cat6->ldgb.d + 1); - printf(".%s", type[cat6->type]); - printf(".%d", cat6->ldgb.type_size + 1); - printf(".%c", ss); + fprintf(ctx->out, ".%s", cat6->ldgb.typed ? "typed" : "untyped"); + fprintf(ctx->out, ".%dd", cat6->ldgb.d + 1); + fprintf(ctx->out, ".%s", type[cat6->type]); + fprintf(ctx->out, ".%d", cat6->ldgb.type_size + 1); + fprintf(ctx->out, ".%c", ss); break; default: dst.im = cat6->g && !cat6->dst_off; - printf(".%s", type[cat6->type]); + fprintf(ctx->out, ".%s", type[cat6->type]); break; } - printf(" "); + fprintf(ctx->out, " "); switch (_OPC(6, cat6->opc)) { case OPC_STG: @@ -619,15 +625,15 @@ static void print_instr_cat6(instr_t *instr) src3.im = cat6->stgb.src3_im; src3.full = true; - printf("g[%u], ", cat6->stgb.dst_ssbo); - print_src(&src1); - printf(", "); - print_src(&src2); - printf(", "); - print_src(&src3); + fprintf(ctx->out, "g[%u], ", cat6->stgb.dst_ssbo); + print_src(ctx, &src1); + fprintf(ctx->out, ", "); + print_src(ctx, &src2); + fprintf(ctx->out, ", "); + print_src(ctx, &src3); if (debug & PRINT_VERBOSE) - printf(" (pad0=%x, pad3=%x)", cat6->stgb.pad0, cat6->stgb.pad3); + fprintf(ctx->out, " (pad0=%x, pad3=%x)", cat6->stgb.pad0, cat6->stgb.pad3); return; } @@ -640,8 +646,8 @@ static void print_instr_cat6(instr_t *instr) src2.im = cat6->ldgb.src2_im; dst.reg = (reg_t)(cat6->ldgb.dst); - print_src(&dst); - printf(", "); + print_src(ctx, &dst); + fprintf(ctx->out, ", "); if (ss == 'g') { struct reginfo src3; memset(&src3, 0, sizeof(src3)); @@ -657,25 +663,25 @@ static void print_instr_cat6(instr_t *instr) * uvec2(offset * 4, 0). Not sure the point of that. */ - printf("g[%u], ", cat6->ldgb.src_ssbo); - print_src(&src1); /* value */ - printf(", "); - print_src(&src2); /* offset/coords */ - printf(", "); - print_src(&src3); /* 64b byte offset.. */ + fprintf(ctx->out, "g[%u], ", cat6->ldgb.src_ssbo); + print_src(ctx, &src1); /* value */ + fprintf(ctx->out, ", "); + print_src(ctx, &src2); /* offset/coords */ + fprintf(ctx->out, ", "); + print_src(ctx, &src3); /* 64b byte offset.. */ if (debug & PRINT_VERBOSE) { - printf(" (pad0=%x, pad3=%x, mustbe0=%x)", cat6->ldgb.pad0, + fprintf(ctx->out, " (pad0=%x, pad3=%x, mustbe0=%x)", cat6->ldgb.pad0, cat6->ldgb.pad3, cat6->ldgb.mustbe0); } } else { /* ss == 'l' */ - printf("l["); - print_src(&src1); /* simple byte offset */ - printf("], "); - print_src(&src2); /* value */ + fprintf(ctx->out, "l["); + print_src(ctx, &src1); /* simple byte offset */ + fprintf(ctx->out, "], "); + print_src(ctx, &src2); /* value */ if (debug & PRINT_VERBOSE) { - printf(" (src3=%x, pad0=%x, pad3=%x, mustbe0=%x)", + fprintf(ctx->out, " (src3=%x, pad0=%x, pad3=%x, mustbe0=%x)", cat6->ldgb.src3, cat6->ldgb.pad0, cat6->ldgb.pad3, cat6->ldgb.mustbe0); } @@ -685,9 +691,9 @@ static void print_instr_cat6(instr_t *instr) } else if (_OPC(6, cat6->opc) == OPC_RESINFO) { dst.reg = (reg_t)(cat6->ldgb.dst); - print_src(&dst); - printf(", "); - printf("g[%u]", cat6->ldgb.src_ssbo); + print_src(ctx, &dst); + fprintf(ctx->out, ", "); + fprintf(ctx->out, "g[%u]", cat6->ldgb.src_ssbo); return; } else if (_OPC(6, cat6->opc) == OPC_LDGB) { @@ -698,15 +704,15 @@ static void print_instr_cat6(instr_t *instr) src2.im = cat6->ldgb.src2_im; dst.reg = (reg_t)(cat6->ldgb.dst); - print_src(&dst); - printf(", "); - printf("g[%u], ", cat6->ldgb.src_ssbo); - print_src(&src1); - printf(", "); - print_src(&src2); + print_src(ctx, &dst); + fprintf(ctx->out, ", "); + fprintf(ctx->out, "g[%u], ", cat6->ldgb.src_ssbo); + print_src(ctx, &src1); + fprintf(ctx->out, ", "); + print_src(ctx, &src2); if (debug & PRINT_VERBOSE) - printf(" (pad0=%x, pad3=%x, mustbe0=%x)", cat6->ldgb.pad0, cat6->ldgb.pad3, cat6->ldgb.mustbe0); + fprintf(ctx->out, " (pad0=%x, pad3=%x, mustbe0=%x)", cat6->ldgb.pad0, cat6->ldgb.pad3, cat6->ldgb.mustbe0); return; } @@ -732,56 +738,56 @@ static void print_instr_cat6(instr_t *instr) if (!nodst) { if (sd) - printf("%c[", sd); + fprintf(ctx->out, "%c[", sd); /* note: dst might actually be a src (ie. address to store to) */ - print_src(&dst); + print_src(ctx, &dst); if (dstoff) - printf("%+d", dstoff); + fprintf(ctx->out, "%+d", dstoff); if (sd) - printf("]"); - printf(", "); + fprintf(ctx->out, "]"); + fprintf(ctx->out, ", "); } if (ss) - printf("%c[", ss); + fprintf(ctx->out, "%c[", ss); /* can have a larger than normal immed, so hack: */ if (src1.im) { - printf("%u", src1.reg.dummy13); + fprintf(ctx->out, "%u", src1.reg.dummy13); } else { - print_src(&src1); + print_src(ctx, &src1); } if (src1off) - printf("%+d", src1off); + fprintf(ctx->out, "%+d", src1off); if (ss) - printf("]"); + fprintf(ctx->out, "]"); switch (_OPC(6, cat6->opc)) { case OPC_RESINFO: case OPC_RESFMT: break; default: - printf(", "); - print_src(&src2); + fprintf(ctx->out, ", "); + print_src(ctx, &src2); break; } } -static void print_instr_cat7(instr_t *instr) +static void print_instr_cat7(struct disasm_ctx *ctx, instr_t *instr) { instr_cat7_t *cat7 = &instr->cat7; if (cat7->g) - printf(".g"); + fprintf(ctx->out, ".g"); if (cat7->l) - printf(".l"); + fprintf(ctx->out, ".l"); if (_OPC(7, cat7->opc) == OPC_FENCE) { if (cat7->r) - printf(".r"); + fprintf(ctx->out, ".r"); if (cat7->w) - printf(".w"); + fprintf(ctx->out, ".w"); } } @@ -792,7 +798,7 @@ static const struct opc_info { uint16_t cat; uint16_t opc; const char *name; - void (*print)(instr_t *instr); + void (*print)(struct disasm_ctx *ctx, instr_t *instr); } opcs[1 << (3+NOPC_BITS)] = { #define OPC(cat, opc, name) [(opc)] = { (cat), (opc), #name, print_instr_cat##cat } /* category 0: */ @@ -966,55 +972,62 @@ const char *ir3_instr_name(struct ir3_instruction *instr) return opcs[instr->opc].name; } -static void print_instr(uint32_t *dwords, int level, int n) +static bool print_instr(struct disasm_ctx *ctx, uint32_t *dwords, int n) { instr_t *instr = (instr_t *)dwords; uint32_t opc = instr_opc(instr); const char *name; if (debug & PRINT_VERBOSE) - printf("%s%04d[%08xx_%08xx] ", levels[level], n, dwords[1], dwords[0]); + fprintf(ctx->out, "%s%04d[%08xx_%08xx] ", levels[ctx->level], n, dwords[1], dwords[0]); /* NOTE: order flags are printed is a bit fugly.. but for now I * try to match the order in llvm-a3xx disassembler for easy * diff'ing.. */ - repeat = instr_repeat(instr); + ctx->repeat = instr_repeat(instr); if (instr->sync) - printf("(sy)"); + fprintf(ctx->out, "(sy)"); if (instr->ss && ((instr->opc_cat <= 4) || (instr->opc_cat == 7))) - printf("(ss)"); + fprintf(ctx->out, "(ss)"); if (instr->jmp_tgt) - printf("(jp)"); + fprintf(ctx->out, "(jp)"); if (instr_sat(instr)) - printf("(sat)"); - if (repeat) - printf("(rpt%d)", repeat); + fprintf(ctx->out, "(sat)"); + if (ctx->repeat) + fprintf(ctx->out, "(rpt%d)", ctx->repeat); if (instr->ul && ((2 <= instr->opc_cat) && (instr->opc_cat <= 4))) - printf("(ul)"); + fprintf(ctx->out, "(ul)"); name = GETINFO(instr)->name; if (name) { - printf("%s", name); - GETINFO(instr)->print(instr); + fprintf(ctx->out, "%s", name); + GETINFO(instr)->print(ctx, instr); } else { - printf("unknown(%d,%d)", instr->opc_cat, opc); + fprintf(ctx->out, "unknown(%d,%d)", instr->opc_cat, opc); } - printf("\n"); + fprintf(ctx->out, "\n"); + + return (instr->opc_cat == 0) && (opc == OPC_END); } -int disasm_a3xx(uint32_t *dwords, int sizedwords, int level, enum shader_t type) +int disasm_a3xx(uint32_t *dwords, int sizedwords, int level, FILE *out) { + struct disasm_ctx ctx; int i; assert((sizedwords % 2) == 0); + memset(&ctx, 0, sizeof(ctx)); + ctx.out = out; + ctx.level = level; + for (i = 0; i < sizedwords; i += 2) - print_instr(&dwords[i], level, i/2); + print_instr(&ctx, &dwords[i], i/2); return 0; } diff --git a/src/gallium/drivers/freedreno/ir3/instr-a3xx.h b/src/gallium/drivers/freedreno/ir3/instr-a3xx.h index 904f88c7e28..8ec64b6eb35 100644 --- a/src/gallium/drivers/freedreno/ir3/instr-a3xx.h +++ b/src/gallium/drivers/freedreno/ir3/instr-a3xx.h @@ -27,6 +27,7 @@ #define PACKED __attribute__((__packed__)) #include <stdint.h> +#include <stdbool.h> #include <assert.h> /* size of largest OPC field of all the instruction categories: */ diff --git a/src/gallium/drivers/freedreno/ir3/ir3_shader.c b/src/gallium/drivers/freedreno/ir3/ir3_shader.c index 59fb3ab5a5a..64a2c8a65c7 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_shader.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_shader.c @@ -441,7 +441,9 @@ ir3_shader_disasm(struct ir3_shader_variant *so, uint32_t *bin) so->immediates[i].val[3]); } - disasm_a3xx(bin, so->info.sizedwords, 0, so->type); +#ifdef DEBUG + disasm_a3xx(bin, so->info.sizedwords, 0, stdout); +#endif switch (so->type) { case SHADER_VERTEX: |