+static void print_reg_stats(struct disasm_ctx *ctx)
+{
+ int fullreg, halfreg;
+
+ fprintf(ctx->out, "%sRegister Stats:\n", levels[ctx->level]);
+ fprintf(ctx->out, "%s- used (half):", levels[ctx->level]);
+ halfreg = print_regs(ctx, &ctx->regs.used, false);
+ fprintf(ctx->out, "\n");
+ fprintf(ctx->out, "%s- used (full):", levels[ctx->level]);
+ fullreg = print_regs(ctx, &ctx->regs.used, true);
+ fprintf(ctx->out, "\n");
+ if (ctx->gpu_id >= 600) {
+ fprintf(ctx->out, "%s- used (merged):", levels[ctx->level]);
+ print_regs(ctx, &ctx->regs.used_merged, false);
+ fprintf(ctx->out, "\n");
+ }
+ fprintf(ctx->out, "%s- input (half):", levels[ctx->level]);
+ print_regs(ctx, &ctx->regs.rbw, false);
+ fprintf(ctx->out, "\n");
+ fprintf(ctx->out, "%s- input (full):", levels[ctx->level]);
+ print_regs(ctx, &ctx->regs.rbw, true);
+ fprintf(ctx->out, "\n");
+ fprintf(ctx->out, "%s- max const: %u\n", levels[ctx->level], ctx->regs.max_const);
+ fprintf(ctx->out, "\n");
+ fprintf(ctx->out, "%s- output (half):", levels[ctx->level]);
+ print_regs(ctx, &ctx->regs.war, false);
+ fprintf(ctx->out, " (estimated)\n");
+ fprintf(ctx->out, "%s- output (full):", levels[ctx->level]);
+ print_regs(ctx, &ctx->regs.war, true);
+ fprintf(ctx->out, " (estimated)\n");
+
+ /* convert to vec4, which is the granularity that registers are
+ * assigned to shader:
+ */
+ fullreg = (fullreg + 3) / 4;
+ halfreg = (halfreg + 3) / 4;
+
+ // Note this count of instructions includes rptN, which matches
+ // up to how mesa prints this:
+ fprintf(ctx->out, "%s- shaderdb: %d instructions, %d nops, %d non-nops, "
+ "(%d instlen), %u last-baryf, %d half, %d full\n",
+ levels[ctx->level], ctx->stats->instructions, ctx->stats->nops,
+ ctx->stats->instructions - ctx->stats->nops, ctx->stats->instlen,
+ ctx->stats->last_baryf, halfreg, fullreg);
+ fprintf(ctx->out, "%s- shaderdb: %u cat0, %u cat1, %u cat2, %u cat3, "
+ "%u cat4, %u cat5, %u cat6, %u cat7\n",
+ levels[ctx->level],
+ ctx->stats->instrs_per_cat[0],
+ ctx->stats->instrs_per_cat[1],
+ ctx->stats->instrs_per_cat[2],
+ ctx->stats->instrs_per_cat[3],
+ ctx->stats->instrs_per_cat[4],
+ ctx->stats->instrs_per_cat[5],
+ ctx->stats->instrs_per_cat[6],
+ ctx->stats->instrs_per_cat[7]);
+ fprintf(ctx->out, "%s- shaderdb: %d (ss), %d (sy)\n", levels[ctx->level],
+ ctx->stats->ss, ctx->stats->sy);
+}
+
+static void process_reg_dst(struct disasm_ctx *ctx)
+{
+ if (!ctx->last_dst_valid)
+ return;
+
+ /* ignore dummy writes (ie. r63.x): */
+ if (!VALIDREG(ctx->last_dst))
+ return;
+
+ for (unsigned i = 0; i <= ctx->repeat; i++) {
+ unsigned dst = ctx->last_dst + i;
+
+ regmask_set(&ctx->regs.war, dst, ctx->last_dst_full);
+ regmask_set(&ctx->regs.used, dst, ctx->last_dst_full);
+
+ if (ctx->gpu_id >= 600) {
+ if (ctx->last_dst_full) {
+ regmask_set(&ctx->regs.used_merged, (dst*2)+0, false);
+ regmask_set(&ctx->regs.used_merged, (dst*2)+1, false);
+ } else {
+ regmask_set(&ctx->regs.used_merged, dst, false);
+ }
+ }
+ }
+
+ ctx->last_dst_valid = false;
+}
+static void print_reg_dst(struct disasm_ctx *ctx, reg_t reg, bool full, bool addr_rel)
+{
+ /* presumably the special registers a0.c and p0.c don't count.. */
+ if (!(addr_rel || (reg.num == REG_A0) || (reg.num == REG_P0))) {
+ ctx->last_dst = regidx(reg);
+ ctx->last_dst_full = full;
+ ctx->last_dst_valid = true;
+ }
+ reg = idxreg(regidx(reg) + ctx->repeatidx);
+ print_reg(ctx, reg, full, false, false, false, false, false, false, addr_rel);