From c543a2cf6f4ab86b78ef314f4be22d6dd2e4604a Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 20 Feb 2019 10:21:18 -0500 Subject: [PATCH] freedreno/ir3: sync instr/disasm and add ldib encoding Resync disasm and instr header from envytools, and add ldib encoding. This replaces an opcode from a3xx which was never seen in practice, since that seemed easier than dealing with the same opc # meaning a different thing on a6xx. (Not really sure if 'sti' was actually a real thing, I think it was only seen in fuzzing.) Signed-off-by: Rob Clark --- src/freedreno/ir3/disasm-a3xx.c | 27 +++++++++++++++++---------- src/freedreno/ir3/instr-a3xx.h | 8 ++++++-- src/freedreno/ir3/ir3.c | 19 +++++++++++++++++-- src/freedreno/ir3/ir3.h | 2 ++ 4 files changed, 42 insertions(+), 14 deletions(-) diff --git a/src/freedreno/ir3/disasm-a3xx.c b/src/freedreno/ir3/disasm-a3xx.c index 9c0432c67ab..b857b381212 100644 --- a/src/freedreno/ir3/disasm-a3xx.c +++ b/src/freedreno/ir3/disasm-a3xx.c @@ -520,7 +520,6 @@ static void print_instr_cat6_a3xx(struct disasm_ctx *ctx, instr_t *instr) case OPC_STG: case OPC_STL: case OPC_STP: - case OPC_STI: case OPC_STLW: case OPC_STIB: dst.full = true; @@ -617,10 +616,6 @@ static void print_instr_cat6_a3xx(struct disasm_ctx *ctx, instr_t *instr) ss = 'g'; nodst = true; break; - - case OPC_STI: - dst.full = false; // XXX or inverts?? - break; } if ((_OPC(6, cat6->opc) == OPC_STGB) || (_OPC(6, cat6->opc) == OPC_STIB)) { @@ -788,6 +783,7 @@ static void print_instr_cat6_a6xx(struct disasm_ctx *ctx, instr_t *instr) { instr_cat6_a6xx_t *cat6 = &instr->cat6_a6xx; struct reginfo src1, src2; + bool has_dest = _OPC(6, cat6->opc) == OPC_LDIB; char ss = 0; memset(&src1, 0, sizeof(src1)); @@ -798,6 +794,14 @@ static void print_instr_cat6_a6xx(struct disasm_ctx *ctx, instr_t *instr) fprintf(ctx->out, ".%s", type[cat6->type]); fprintf(ctx->out, ".%u ", cat6->type_size + 1); + if (has_dest) { + src2.reg = (reg_t)(cat6->src2); + src2.full = true; // XXX + print_src(ctx, &src2); + + fprintf(ctx->out, ", "); + } + /* NOTE: blob seems to use old encoding for ldl/stl (local memory) */ ss = 'g'; @@ -806,11 +810,14 @@ static void print_instr_cat6_a6xx(struct disasm_ctx *ctx, instr_t *instr) src1.reg = (reg_t)(cat6->src1); src1.full = true; // XXX print_src(ctx, &src1); - fprintf(ctx->out, ", "); - src2.reg = (reg_t)(cat6->src2); - src2.full = true; // XXX - print_src(ctx, &src2); + if (!has_dest) { + fprintf(ctx->out, ", "); + + src2.reg = (reg_t)(cat6->src2); + src2.full = true; // XXX + print_src(ctx, &src2); + } if (debug & PRINT_VERBOSE) { fprintf(ctx->out, " (pad1=%x, pad2=%x, pad3=%x, pad4=%x)", cat6->pad1, @@ -990,7 +997,7 @@ static const struct opc_info { OPC(6, OPC_STG, stg), OPC(6, OPC_STL, stl), OPC(6, OPC_STP, stp), - OPC(6, OPC_STI, sti), + OPC(6, OPC_LDIB, ldib), OPC(6, OPC_G2L, g2l), OPC(6, OPC_L2G, l2g), OPC(6, OPC_PREFETCH, prefetch), diff --git a/src/freedreno/ir3/instr-a3xx.h b/src/freedreno/ir3/instr-a3xx.h index eff720dacd5..9e83e04c816 100644 --- a/src/freedreno/ir3/instr-a3xx.h +++ b/src/freedreno/ir3/instr-a3xx.h @@ -172,7 +172,7 @@ typedef enum { OPC_STG = _OPC(6, 3), /* store-global */ OPC_STL = _OPC(6, 4), OPC_STP = _OPC(6, 5), - OPC_STI = _OPC(6, 6), + OPC_LDIB = _OPC(6, 6), OPC_G2L = _OPC(6, 7), OPC_L2G = _OPC(6, 8), OPC_PREFETCH = _OPC(6, 9), @@ -741,6 +741,10 @@ typedef union PACKED { * src1 - vecN offset/coords * src2 - value to store * + * For ldib: + * pad1=1, pad2=c, pad3=0, pad4=2 + * src1 - vecN offset/coords + * * for ldc (load from UBO using descriptor): * pad1=0, pad2=8, pad3=0, pad4=2 */ @@ -755,7 +759,7 @@ typedef struct PACKED { uint32_t src1 : 8; /* coordinate/offset */ /* dword1: */ - uint32_t src2 : 8; + uint32_t src2 : 8; /* or the dst for load instructions */ uint32_t pad3 : 1; //mustbe0 ?? or zero means imm vs reg for ssbo?? uint32_t ssbo : 8; /* ssbo/image binding point */ uint32_t type : 3; diff --git a/src/freedreno/ir3/ir3.c b/src/freedreno/ir3/ir3.c index 8c28e05f19e..a4de1d3ab49 100644 --- a/src/freedreno/ir3/ir3.c +++ b/src/freedreno/ir3/ir3.c @@ -485,12 +485,21 @@ static int emit_cat6_a6xx(struct ir3_instruction *instr, void *ptr, { struct ir3_register *src1, *src2; instr_cat6_a6xx_t *cat6 = ptr; + bool has_dest = (instr->opc == OPC_LDIB); /* first reg should be SSBO binding point: */ iassert(instr->regs[1]->flags & IR3_REG_IMMED); src1 = instr->regs[2]; - src2 = instr->regs[3]; + + if (has_dest) { + /* the src2 field in the instruction is actually the destination + * register for load instructions: + */ + src2 = instr->regs[0]; + } else { + src2 = instr->regs[3]; + } cat6->type = instr->cat6.type; cat6->d = instr->cat6.d - 1; @@ -528,6 +537,12 @@ static int emit_cat6_a6xx(struct ir3_instruction *instr, void *ptr, cat6->pad3 = 0x0; cat6->pad4 = 0x2; break; + case OPC_LDIB: + cat6->pad1 = 0x1; + cat6->pad2 = 0xc; + cat6->pad3 = 0x0; + cat6->pad4 = 0x2; + break; case OPC_LDC: cat6->pad1 = 0x0; cat6->pad2 = 0x8; @@ -568,6 +583,7 @@ static int emit_cat6(struct ir3_instruction *instr, void *ptr, break; /* fallthrough */ case OPC_STIB: + case OPC_LDIB: case OPC_LDC: return emit_cat6_a6xx(instr, ptr, info); default: @@ -598,7 +614,6 @@ static int emit_cat6(struct ir3_instruction *instr, void *ptr, case OPC_STG: case OPC_STL: case OPC_STP: - case OPC_STI: case OPC_STLW: case OPC_STIB: /* no dst, so regs[0] is dummy */ diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h index 918fce833f2..36d645f0b50 100644 --- a/src/freedreno/ir3/ir3.h +++ b/src/freedreno/ir3/ir3.h @@ -688,6 +688,7 @@ static inline bool is_load(struct ir3_instruction *instr) switch (instr->opc) { case OPC_LDG: case OPC_LDGB: + case OPC_LDIB: case OPC_LDL: case OPC_LDP: case OPC_L2G: @@ -1360,6 +1361,7 @@ INSTR2(ATOMIC_OR) INSTR2(ATOMIC_XOR) #if GPU >= 600 INSTR3(STIB); +INSTR2(LDIB); INSTR3F(G, ATOMIC_ADD) INSTR3F(G, ATOMIC_SUB) INSTR3F(G, ATOMIC_XCHG) -- 2.30.2