enum debug_t {
PRINT_RAW = 0x1, /* dump raw hexdump */
PRINT_VERBOSE = 0x2,
+ EXPAND_REPEAT = 0x4,
};
static enum debug_t debug;
/* current instruction repeat flag: */
unsigned repeat;
+ /* current instruction repeat indx/offset (for --expand): */
+ unsigned repeatidx;
};
static void print_reg(struct disasm_ctx *ctx, reg_t reg, bool full, bool r,
}
}
+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_reg_dst(struct disasm_ctx *ctx, reg_t reg, bool full, bool addr_rel)
{
+ reg = idxreg(regidx(reg) + ctx->repeatidx);
print_reg(ctx, reg, full, false, false, false, false, false, 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)
{
+ if (r)
+ reg = idxreg(regidx(reg) + ctx->repeatidx);
+
print_reg(ctx, reg, full, r, c, im, neg, abs, addr_rel);
}
/* note: dst might actually be a src (ie. address to store to) */
print_src(ctx, &dst);
if (cat6->dst_off && cat6->g) {
- struct reginfo dstoff_reg = {};
+ struct reginfo dstoff_reg = {0};
dstoff_reg.reg = (reg_t) cat6->c.off;
- dstoff_reg.full = true;
+ dstoff_reg.full = true;
fprintf(ctx->out, "+");
print_src(ctx, &dstoff_reg);
- } else if (dstoff) {
+ } else if (dstoff)
fprintf(ctx->out, "%+d", dstoff);
- }
if (sd)
fprintf(ctx->out, "]");
fprintf(ctx->out, ", ");
OPC(4, OPC_SIN, sin),
OPC(4, OPC_COS, cos),
OPC(4, OPC_SQRT, sqrt),
+ OPC(4, OPC_HRSQ, hrsq),
+ OPC(4, OPC_HLOG2, hlog2),
+ OPC(4, OPC_HEXP2, hexp2),
/* category 5: */
OPC(5, OPC_ISAM, isam),
return opcs[instr->opc].name;
}
+static void print_single_instr(struct disasm_ctx *ctx, instr_t *instr)
+{
+ const char *name = GETINFO(instr)->name;
+ uint32_t opc = instr_opc(instr, ctx->gpu_id);
+
+ if (name) {
+ fprintf(ctx->out, "%s", name);
+ GETINFO(instr)->print(ctx, instr);
+ } else {
+ fprintf(ctx->out, "unknown(%d,%d)", instr->opc_cat, opc);
+
+ switch (instr->opc_cat) {
+ case 0: print_instr_cat0(ctx, instr); break;
+ case 1: print_instr_cat1(ctx, instr); break;
+ case 2: print_instr_cat2(ctx, instr); break;
+ case 3: print_instr_cat3(ctx, instr); break;
+ case 4: print_instr_cat4(ctx, instr); break;
+ case 5: print_instr_cat5(ctx, instr); break;
+ case 6: print_instr_cat6(ctx, instr); break;
+ case 7: print_instr_cat7(ctx, instr); break;
+ }
+ }
+}
+
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, ctx->gpu_id);
- const char *name;
+ unsigned nop = 0;
if (debug & PRINT_VERBOSE)
fprintf(ctx->out, "%s%04d[%08xx_%08xx] ", levels[ctx->level], n, dwords[1], dwords[0]);
ctx->repeat = instr_repeat(instr);
- if (instr->sync)
+ if (instr->sync) {
fprintf(ctx->out, "(sy)");
- if (instr->ss && ((instr->opc_cat <= 4) || (instr->opc_cat == 7)))
+ }
+ if (instr->ss && ((instr->opc_cat <= 4) || (instr->opc_cat == 7))) {
fprintf(ctx->out, "(ss)");
+ }
if (instr->jmp_tgt)
fprintf(ctx->out, "(jp)");
if (instr_sat(instr))
fprintf(ctx->out, "(sat)");
- if (ctx->repeat) {
+ if (ctx->repeat)
fprintf(ctx->out, "(rpt%d)", ctx->repeat);
- } else if ((instr->opc_cat == 2) && (instr->cat2.src1_r || instr->cat2.src2_r)) {
- unsigned nop = (instr->cat2.src2_r * 2) + instr->cat2.src1_r;
- fprintf(ctx->out, "(nop%d)", nop);
- } else if ((instr->opc_cat == 3) && (instr->cat3.src1_r || instr->cat3.src2_r)) {
- unsigned nop = (instr->cat3.src2_r * 2) + instr->cat3.src1_r;
+ else if ((instr->opc_cat == 2) && (instr->cat2.src1_r || instr->cat2.src2_r))
+ nop = (instr->cat2.src2_r * 2) + instr->cat2.src1_r;
+ else if ((instr->opc_cat == 3) && (instr->cat3.src1_r || instr->cat3.src2_r))
+ nop = (instr->cat3.src2_r * 2) + instr->cat3.src1_r;
+ if (nop)
fprintf(ctx->out, "(nop%d)", nop);
- }
+
if (instr->ul && ((2 <= instr->opc_cat) && (instr->opc_cat <= 4)))
fprintf(ctx->out, "(ul)");
- name = GETINFO(instr)->name;
+ print_single_instr(ctx, instr);
+ fprintf(ctx->out, "\n");
- if (name) {
- fprintf(ctx->out, "%s", name);
- GETINFO(instr)->print(ctx, instr);
- } else {
- fprintf(ctx->out, "unknown(%d,%d)", instr->opc_cat, opc);
- }
+ if ((instr->opc_cat <= 4) && (debug & EXPAND_REPEAT)) {
+ int i;
+ for (i = 0; i < nop; i++) {
+ fprintf(ctx->out, "%s%04d[ ] ", levels[ctx->level], n);
+ fprintf(ctx->out, "nop\n");
+ }
+ for (i = 0; i < ctx->repeat; i++) {
+ ctx->repeatidx = i + 1;
+ fprintf(ctx->out, "%s%04d[ ] ", levels[ctx->level], n);
- fprintf(ctx->out, "\n");
+ print_single_instr(ctx, instr);
+ fprintf(ctx->out, "\n");
+ }
+ ctx->repeatidx = 0;
+ }
return (instr->opc_cat == 0) && (opc == OPC_END);
}
{
struct disasm_ctx ctx;
int i;
+ int nop_count = 0;
assert((sizedwords % 2) == 0);
ctx.level = level;
ctx.gpu_id = gpu_id;
- for (i = 0; i < sizedwords; i += 2)
+ for (i = 0; i < sizedwords; i += 2) {
print_instr(&ctx, &dwords[i], i/2);
+ if (dwords[i] == 0 && dwords[i + 1] == 0)
+ nop_count++;
+ else
+ nop_count = 0;
+ if (nop_count > 3)
+ break;
+ }
return 0;
}