From 08a9e5e3e892e9acc7fcfc2cefb45990efa62e40 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Sat, 19 Sep 2020 16:06:22 -0400 Subject: [PATCH] pan/bi: Decode M values in disasm This is rather complicated and mostly unused in real world code but correct handling is required to disassemble branchy code. Signed-off-by: Alyssa Rosenzweig Part-of: --- src/panfrost/bifrost/disassemble.c | 59 ++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/src/panfrost/bifrost/disassemble.c b/src/panfrost/bifrost/disassemble.c index d70777aac2f..2e2775f40a2 100644 --- a/src/panfrost/bifrost/disassemble.c +++ b/src/panfrost/bifrost/disassemble.c @@ -386,6 +386,49 @@ dump_src(FILE *fp, unsigned src, struct bifrost_regs srcs, struct bi_constants * } } +/* Tables for decoding M0, or if M0 == 7, M1 respectively. + * + * XXX: It's not clear if the third entry of M1_table corresponding to (7, 2) + * should have PC_LO_HI in the EC1 slot, or it's a weird hybrid mode? I would + * say this needs testing but no code should ever actually use this mode. + */ + +static const enum bi_constmod M1_table[7][2] = { + { BI_CONSTMOD_NONE, BI_CONSTMOD_NONE }, + { BI_CONSTMOD_PC_LO, BI_CONSTMOD_NONE }, + { BI_CONSTMOD_PC_LO, BI_CONSTMOD_PC_LO }, + { ~0, ~0 }, + { BI_CONSTMOD_PC_HI, BI_CONSTMOD_NONE }, + { BI_CONSTMOD_PC_HI, BI_CONSTMOD_PC_HI }, + { BI_CONSTMOD_PC_LO, BI_CONSTMOD_NONE }, +}; + +static const enum bi_constmod M2_table[4][2] = { + { BI_CONSTMOD_PC_LO_HI, BI_CONSTMOD_NONE }, + { BI_CONSTMOD_PC_LO_HI, BI_CONSTMOD_PC_HI }, + { BI_CONSTMOD_PC_LO_HI, BI_CONSTMOD_PC_LO_HI }, + { BI_CONSTMOD_PC_LO_HI, BI_CONSTMOD_PC_HI }, +}; + +static void +decode_M(enum bi_constmod *mod, unsigned M1, unsigned M2, bool single) +{ + if (M1 >= 8) { + mod[0] = BI_CONSTMOD_NONE; + + if (!single) + mod[1] = BI_CONSTMOD_NONE; + + return; + } else if (M1 == 7) { + assert(M2 < 4); + memcpy(mod, M2_table[M2], sizeof(*mod) * (single ? 1 : 2)); + } else { + assert(M1 != 3); + memcpy(mod, M1_table[M1], sizeof(*mod) * (single ? 1 : 2)); + } +} + static bool dump_clause(FILE *fp, uint32_t *words, unsigned *size, unsigned offset, bool verbose) { // State for a decoded clause @@ -449,6 +492,7 @@ static bool dump_clause(FILE *fp, uint32_t *words, unsigned *size, unsigned offs instrs[2].add_bits = bits(words[3], 0, 17) | bits(words[3], 29, 32) << 17; instrs[2].fma_bits |= bits(words[2], 19, 32) << 10; consts.raw[0] = const0; + decode_M(&consts.mods[0], bits(words[2], 4, 8), bits(words[2], 8, 12), true); num_instrs = 3; num_consts = 1; done = stop; @@ -470,6 +514,7 @@ static bool dump_clause(FILE *fp, uint32_t *words, unsigned *size, unsigned offs instrs[5].add_bits = bits(words[3], 0, 17) | bits(words[3], 29, 32) << 17; instrs[5].fma_bits |= bits(words[2], 19, 32) << 10; consts.raw[0] = const0; + decode_M(&consts.mods[0], bits(words[2], 4, 8), bits(words[2], 8, 12), true); num_instrs = 6; num_consts = 1; done = stop; @@ -568,6 +613,20 @@ static bool dump_clause(FILE *fp, uint32_t *words, unsigned *size, unsigned offs consts.raw[const_idx] = const0; consts.raw[const_idx + 1] = const1; + + /* Calculate M values from A, B and 4-bit + * unsigned arithmetic */ + + signed A1 = bits(words[2], 0, 4); + signed B1 = bits(words[3], 28, 32); + signed A2 = bits(words[1], 0, 4); + signed B2 = bits(words[2], 28, 32); + + unsigned M1 = (A1 - B1) % 16; + unsigned M2 = (A2 - B2) % 16; + + decode_M(&consts.mods[const_idx], M1, M2, false); + done = stop; break; }