+static unsigned regidx(reg_t reg)
+{
+ return (4 * reg.num) + reg.comp;
+}
+
+static reg_t idxreg(unsigned idx)
+{
+ return (reg_t){
+ .comp = idx & 0x3,
+ .num = idx >> 2,
+ };
+}
+
+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)