From ccb3d7d8bead358a506bc06643d5e64ba95af0b8 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 7 Oct 2020 08:42:00 +0200 Subject: [PATCH] panfrost: bifrost: disassemble: Fix decoding of next_regs next_regs decoding is wrong for the first and last instructions in a clause: - the first instruction has its destination encoded in the second reg block - the last instruction has its destination encoded in the first reg block (things wrap around) So, only the last instruction should pass first=true when decoding next_regs. Fix that by passing the is_last_instruction information instead of is_first_instruction to the disasm helpers. Signed-off-by: Boris Brezillon Reviewed-by: Alyssa Rosenzweig Part-of: --- src/panfrost/bifrost/disassemble.c | 18 +++++++++++------- src/panfrost/bifrost/gen_disasm.py | 8 ++++---- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/panfrost/bifrost/disassemble.c b/src/panfrost/bifrost/disassemble.c index 4f0f12887f8..30361fd735a 100644 --- a/src/panfrost/bifrost/disassemble.c +++ b/src/panfrost/bifrost/disassemble.c @@ -214,9 +214,10 @@ bi_disasm_dest_mask(FILE *fp, enum bifrost_reg_op op) } void -bi_disasm_dest_fma(FILE *fp, struct bifrost_regs *next_regs, bool first) +bi_disasm_dest_fma(FILE *fp, struct bifrost_regs *next_regs, bool last) { - struct bifrost_reg_ctrl ctrl = DecodeRegCtrl(fp, *next_regs, first); + /* If this is the last instruction, next_regs points to the first reg entry. */ + struct bifrost_reg_ctrl ctrl = DecodeRegCtrl(fp, *next_regs, last); if (ctrl.slot23.slot2 >= BIFROST_OP_WRITE) { fprintf(fp, "r%u:t0", next_regs->reg2); bi_disasm_dest_mask(fp, ctrl.slot23.slot2); @@ -228,9 +229,10 @@ bi_disasm_dest_fma(FILE *fp, struct bifrost_regs *next_regs, bool first) } void -bi_disasm_dest_add(FILE *fp, struct bifrost_regs *next_regs, bool first) +bi_disasm_dest_add(FILE *fp, struct bifrost_regs *next_regs, bool last) { - struct bifrost_reg_ctrl ctrl = DecodeRegCtrl(fp, *next_regs, first); + /* If this is the last instruction, next_regs points to the first reg entry. */ + struct bifrost_reg_ctrl ctrl = DecodeRegCtrl(fp, *next_regs, last); if (ctrl.slot23.slot3 >= BIFROST_OP_WRITE && !ctrl.slot23.slot3_fma) { fprintf(fp, "r%u:t0", next_regs->reg3); @@ -671,12 +673,14 @@ static bool dump_clause(FILE *fp, uint32_t *words, unsigned *size, unsigned offs memcpy((char *) ®s, (char *) &instrs[i].reg_bits, sizeof(regs)); if (verbose) { - fprintf(fp, "# regs: %016" PRIx64 "\n", instrs->reg_bits); + fprintf(fp, "# regs: %016" PRIx64 "\n", instrs[i].reg_bits); dump_regs(fp, regs, i == 0); } - bi_disasm_fma(fp, instrs[i].fma_bits, ®s, &next_regs, header.datareg, offset, &consts, i == 0); - bi_disasm_add(fp, instrs[i].add_bits, ®s, &next_regs, header.datareg, offset, &consts, i == 0); + bi_disasm_fma(fp, instrs[i].fma_bits, ®s, &next_regs, header.datareg, + offset, &consts, i + 1 == num_instrs); + bi_disasm_add(fp, instrs[i].add_bits, ®s, &next_regs, header.datareg, + offset, &consts, i + 1 == num_instrs); } fprintf(fp, "}\n"); diff --git a/src/panfrost/bifrost/gen_disasm.py b/src/panfrost/bifrost/gen_disasm.py index 61080a333c3..4df7b1bf728 100644 --- a/src/panfrost/bifrost/gen_disasm.py +++ b/src/panfrost/bifrost/gen_disasm.py @@ -64,7 +64,7 @@ def decode_op(instructions, is_fma): # Generate checks in order template = """void -bi_disasm_${unit}(FILE *fp, unsigned bits, struct bifrost_regs *srcs, struct bifrost_regs *next_regs, unsigned staging_register, unsigned branch_offset, struct bi_constants *consts, bool first) +bi_disasm_${unit}(FILE *fp, unsigned bits, struct bifrost_regs *srcs, struct bifrost_regs *next_regs, unsigned staging_register, unsigned branch_offset, struct bi_constants *consts, bool last) { % for (i, (name, (emask, ebits), derived)) in enumerate(options): % if len(derived) > 0: @@ -76,7 +76,7 @@ bi_disasm_${unit}(FILE *fp, unsigned bits, struct bifrost_regs *srcs, struct bif % else: ${"else " if i > 0 else ""}if (unlikely(((bits & ${hex(emask)}) == ${hex(ebits)}))) % endif - bi_disasm_${name}(fp, bits, srcs, next_regs, staging_register, branch_offset, consts, first); + bi_disasm_${name}(fp, bits, srcs, next_regs, staging_register, branch_offset, consts, last); % endfor else fprintf(fp, "INSTR_INVALID_ENC ${unit} %X\\n", bits); @@ -89,7 +89,7 @@ bi_disasm_${unit}(FILE *fp, unsigned bits, struct bifrost_regs *srcs, struct bif # state. Sync prototypes to avoid moves when calling. disasm_op_template = Template("""static void -bi_disasm_${c_name}(FILE *fp, unsigned bits, struct bifrost_regs *srcs, struct bifrost_regs *next_regs, unsigned staging_register, unsigned branch_offset, struct bi_constants *consts, bool first) +bi_disasm_${c_name}(FILE *fp, unsigned bits, struct bifrost_regs *srcs, struct bifrost_regs *next_regs, unsigned staging_register, unsigned branch_offset, struct bi_constants *consts, bool last) { ${body.strip()} } @@ -316,7 +316,7 @@ def disasm_op(name, op): body += disasm_mod(mod, skip_mods) body += ' fputs(" ", fp);\n' - body += ' bi_disasm_dest_{}(fp, next_regs, first);\n'.format('fma' if is_fma else 'add') + body += ' bi_disasm_dest_{}(fp, next_regs, last);\n'.format('fma' if is_fma else 'add') # Next up, each source. Source modifiers are inserterd here