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 <robdclark@gmail.com>
This commit is contained in:
Rob Clark 2019-02-20 10:21:18 -05:00
parent cadf6def0c
commit c543a2cf6f
4 changed files with 42 additions and 14 deletions

View File

@ -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),

View File

@ -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;

View File

@ -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 */

View File

@ -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)