+static void print_sequence(struct disasm_ctx *ctx, int first, int last)
+{
+ if (first != MAX_REG) {
+ if (first == last) {
+ fprintf(ctx->out, " %d", first);
+ } else {
+ fprintf(ctx->out, " %d-%d", first, last);
+ }
+ }
+}
+
+static int print_regs(struct disasm_ctx *ctx, regmask_t *regmask, bool full)
+{
+ int num, max = 0, cnt = 0;
+ int first, last;
+
+ first = last = MAX_REG;
+
+ for (num = 0; num < MAX_REG; num++) {
+ if (regmask_get(regmask, num, full)) {
+ if (num != (last + 1)) {
+ print_sequence(ctx, first, last);
+ first = num;
+ }
+ last = num;
+ if (num < (48*4))
+ max = num;
+ cnt++;
+ }
+ }
+
+ print_sequence(ctx, first, last);
+
+ fprintf(ctx->out, " (cnt=%d, max=%d)", cnt, max);
+
+ return max;
+}
+
+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");
+ 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 = ctx->regs.used.mergedregs ? 0 : (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);
+ }
+
+ ctx->last_dst_valid = false;
+}