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)