freedreno/ir3: Sync some new changes from envytools.
With this I also brought in a few new control flow instruction disasm tests that I'd made back when I wrote the disasm test, but which were too far from correct to include until now. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4857>
This commit is contained in:
parent
1e5b0c92c5
commit
97b21110b8
|
@ -203,26 +203,54 @@ static void print_src(struct disasm_ctx *ctx, struct reginfo *info)
|
|||
|
||||
static void print_instr_cat0(struct disasm_ctx *ctx, instr_t *instr)
|
||||
{
|
||||
static const struct {
|
||||
const char *suffix;
|
||||
int nsrc;
|
||||
bool idx;
|
||||
} brinfo[7] = {
|
||||
[BRANCH_PLAIN] = { "r", 1, false },
|
||||
[BRANCH_OR] = { "rao", 2, false },
|
||||
[BRANCH_AND] = { "raa", 2, false },
|
||||
[BRANCH_CONST] = { "rac", 0, true },
|
||||
[BRANCH_ANY] = { "any", 1, false },
|
||||
[BRANCH_ALL] = { "all", 1, false },
|
||||
[BRANCH_X] = { "rax", 0, false },
|
||||
};
|
||||
instr_cat0_t *cat0 = &instr->cat0;
|
||||
|
||||
switch (cat0->opc) {
|
||||
switch (instr_opc(instr, ctx->gpu_id)) {
|
||||
case OPC_KILL:
|
||||
case OPC_IF:
|
||||
fprintf(ctx->out, " %sp0.%c", cat0->inv ? "!" : "",
|
||||
component[cat0->comp]);
|
||||
case OPC_PREDT:
|
||||
case OPC_PREDF:
|
||||
fprintf(ctx->out, " %sp0.%c", cat0->inv0 ? "!" : "",
|
||||
component[cat0->comp0]);
|
||||
break;
|
||||
case OPC_BR:
|
||||
fprintf(ctx->out, " %sp0.%c, #%d", cat0->inv ? "!" : "",
|
||||
component[cat0->comp], cat0->a3xx.immed);
|
||||
case OPC_B:
|
||||
fprintf(ctx->out, "%s", brinfo[cat0->brtype].suffix);
|
||||
if (brinfo[cat0->brtype].idx) {
|
||||
fprintf(ctx->out, ".%u", cat0->idx);
|
||||
}
|
||||
if (brinfo[cat0->brtype].nsrc >= 1) {
|
||||
fprintf(ctx->out, " %sp0.%c,", cat0->inv0 ? "!" : "",
|
||||
component[cat0->comp0]);
|
||||
}
|
||||
if (brinfo[cat0->brtype].nsrc >= 2) {
|
||||
fprintf(ctx->out, " %sp0.%c,", cat0->inv1 ? "!" : "",
|
||||
component[cat0->comp1]);
|
||||
}
|
||||
fprintf(ctx->out, " #%d", cat0->a3xx.immed);
|
||||
break;
|
||||
case OPC_JUMP:
|
||||
case OPC_CALL:
|
||||
case OPC_BKT:
|
||||
case OPC_GETONE:
|
||||
case OPC_SHPS:
|
||||
fprintf(ctx->out, " #%d", cat0->a3xx.immed);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((debug & PRINT_VERBOSE) && (cat0->dummy2|cat0->dummy3|cat0->dummy4))
|
||||
fprintf(ctx->out, "\t{0: %x,%x,%x}", cat0->dummy2, cat0->dummy3, cat0->dummy4);
|
||||
if ((debug & PRINT_VERBOSE) && (cat0->dummy3|cat0->dummy4))
|
||||
fprintf(ctx->out, "\t{0: %x,%x}", cat0->dummy3, cat0->dummy4);
|
||||
}
|
||||
|
||||
static void print_instr_cat1(struct disasm_ctx *ctx, instr_t *instr)
|
||||
|
@ -1065,7 +1093,7 @@ static const struct opc_info {
|
|||
#define OPC(cat, opc, name) [(opc)] = { (cat), (opc), #name, print_instr_cat##cat }
|
||||
/* category 0: */
|
||||
OPC(0, OPC_NOP, nop),
|
||||
OPC(0, OPC_BR, br),
|
||||
OPC(0, OPC_B, b),
|
||||
OPC(0, OPC_JUMP, jump),
|
||||
OPC(0, OPC_CALL, call),
|
||||
OPC(0, OPC_RET, ret),
|
||||
|
@ -1076,9 +1104,18 @@ static const struct opc_info {
|
|||
OPC(0, OPC_CHMASK, chmask),
|
||||
OPC(0, OPC_CHSH, chsh),
|
||||
OPC(0, OPC_FLOW_REV, flow_rev),
|
||||
OPC(0, OPC_IF, if),
|
||||
OPC(0, OPC_ELSE, else),
|
||||
OPC(0, OPC_ENDIF, endif),
|
||||
OPC(0, OPC_PREDT, predt),
|
||||
OPC(0, OPC_PREDF, predf),
|
||||
OPC(0, OPC_PREDE, prede),
|
||||
OPC(0, OPC_BKT, bkt),
|
||||
OPC(0, OPC_STKS, stks),
|
||||
OPC(0, OPC_STKR, stkr),
|
||||
OPC(0, OPC_XSET, xset),
|
||||
OPC(0, OPC_XCLR, xclr),
|
||||
OPC(0, OPC_GETONE, getone),
|
||||
OPC(0, OPC_DBG, dbg),
|
||||
OPC(0, OPC_SHPS, shps),
|
||||
OPC(0, OPC_SHPE, shpe),
|
||||
|
||||
/* category 1: */
|
||||
OPC(1, OPC_MOV, ),
|
||||
|
@ -1292,6 +1329,8 @@ static bool print_instr(struct disasm_ctx *ctx, uint32_t *dwords, int n)
|
|||
}
|
||||
if (instr->jmp_tgt)
|
||||
fprintf(ctx->out, "(jp)");
|
||||
if ((instr->opc_cat == 0) && instr->cat0.eq)
|
||||
fprintf(ctx->out, "(eq)");
|
||||
if (instr_sat(instr))
|
||||
fprintf(ctx->out, "(sat)");
|
||||
if (ctx->repeat)
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
typedef enum {
|
||||
/* category 0: */
|
||||
OPC_NOP = _OPC(0, 0),
|
||||
OPC_BR = _OPC(0, 1),
|
||||
OPC_B = _OPC(0, 1),
|
||||
OPC_JUMP = _OPC(0, 2),
|
||||
OPC_CALL = _OPC(0, 3),
|
||||
OPC_RET = _OPC(0, 4),
|
||||
|
@ -51,9 +51,19 @@ typedef enum {
|
|||
OPC_CHSH = _OPC(0, 10),
|
||||
OPC_FLOW_REV = _OPC(0, 11),
|
||||
|
||||
OPC_IF = _OPC(0, 13),
|
||||
OPC_ELSE = _OPC(0, 14),
|
||||
OPC_ENDIF = _OPC(0, 15),
|
||||
OPC_BKT = _OPC(0, 16),
|
||||
OPC_STKS = _OPC(0, 17),
|
||||
OPC_STKR = _OPC(0, 18),
|
||||
OPC_XSET = _OPC(0, 19),
|
||||
OPC_XCLR = _OPC(0, 20),
|
||||
OPC_GETONE = _OPC(0, 21),
|
||||
OPC_DBG = _OPC(0, 22),
|
||||
OPC_SHPS = _OPC(0, 23), /* shader prologue start */
|
||||
OPC_SHPE = _OPC(0, 24), /* shader prologue end */
|
||||
|
||||
OPC_PREDT = _OPC(0, 29), /* predicated true */
|
||||
OPC_PREDF = _OPC(0, 30), /* predicated false */
|
||||
OPC_PREDE = _OPC(0, 31), /* predicated end */
|
||||
|
||||
/* category 1: */
|
||||
OPC_MOV = _OPC(1, 0),
|
||||
|
@ -311,6 +321,16 @@ static inline int reg_special(reg_t reg)
|
|||
return (reg.num == REG_A0) || (reg.num == REG_P0);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
BRANCH_PLAIN = 0, /* br */
|
||||
BRANCH_OR = 1, /* brao */
|
||||
BRANCH_AND = 2, /* braa */
|
||||
BRANCH_CONST = 3, /* brac */
|
||||
BRANCH_ANY = 4, /* bany */
|
||||
BRANCH_ALL = 5, /* ball */
|
||||
BRANCH_X = 6, /* brax ??? */
|
||||
} brtype_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
/* dword0: */
|
||||
union PACKED {
|
||||
|
@ -328,13 +348,18 @@ typedef struct PACKED {
|
|||
};
|
||||
|
||||
/* dword1: */
|
||||
uint32_t dummy2 : 8;
|
||||
uint32_t idx : 5; /* brac.N index */
|
||||
uint32_t brtype : 3; /* branch type, see brtype_t */
|
||||
uint32_t repeat : 3;
|
||||
uint32_t dummy3 : 1;
|
||||
uint32_t ss : 1;
|
||||
uint32_t dummy4 : 7;
|
||||
uint32_t inv : 1;
|
||||
uint32_t comp : 2;
|
||||
uint32_t inv1 : 1;
|
||||
uint32_t comp1 : 2;
|
||||
uint32_t eq : 1;
|
||||
uint32_t opc_hi : 1; /* at least one bit */
|
||||
uint32_t dummy4 : 2;
|
||||
uint32_t inv0 : 1;
|
||||
uint32_t comp0 : 2; /* component for first src */
|
||||
uint32_t opc : 4;
|
||||
uint32_t jmp_tgt : 1;
|
||||
uint32_t sync : 1;
|
||||
|
@ -963,7 +988,7 @@ static inline bool is_cat6_legacy(instr_t *instr, unsigned gpu_id)
|
|||
static inline uint32_t instr_opc(instr_t *instr, unsigned gpu_id)
|
||||
{
|
||||
switch (instr->opc_cat) {
|
||||
case 0: return instr->cat0.opc;
|
||||
case 0: return instr->cat0.opc | instr->cat0.opc_hi << 4;
|
||||
case 1: return 0;
|
||||
case 2: return instr->cat2.opc;
|
||||
case 3: return instr->cat3.opc;
|
||||
|
|
|
@ -141,23 +141,14 @@ static int emit_cat0(struct ir3_instruction *instr, void *ptr,
|
|||
}
|
||||
cat0->repeat = instr->repeat;
|
||||
cat0->ss = !!(instr->flags & IR3_INSTR_SS);
|
||||
cat0->inv = instr->cat0.inv;
|
||||
cat0->comp = instr->cat0.comp;
|
||||
cat0->inv0 = instr->cat0.inv;
|
||||
cat0->comp0 = instr->cat0.comp;
|
||||
cat0->opc = instr->opc;
|
||||
cat0->opc_hi = instr->opc >= 16;
|
||||
cat0->jmp_tgt = !!(instr->flags & IR3_INSTR_JP);
|
||||
cat0->sync = !!(instr->flags & IR3_INSTR_SY);
|
||||
cat0->opc_cat = 0;
|
||||
|
||||
switch (instr->opc) {
|
||||
case OPC_IF:
|
||||
case OPC_ELSE:
|
||||
case OPC_ENDIF:
|
||||
cat0->dummy4 = 16;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1423,15 +1423,15 @@ ir3_##name(struct ir3_block *block, \
|
|||
#define INSTR4(name) __INSTR4(0, name, OPC_##name)
|
||||
|
||||
/* cat0 instructions: */
|
||||
INSTR1(BR)
|
||||
INSTR1(B)
|
||||
INSTR0(JUMP)
|
||||
INSTR1(KILL)
|
||||
INSTR0(END)
|
||||
INSTR0(CHSH)
|
||||
INSTR0(CHMASK)
|
||||
INSTR1(IF)
|
||||
INSTR0(ELSE)
|
||||
INSTR0(ENDIF)
|
||||
INSTR1(PREDT)
|
||||
INSTR0(PREDF)
|
||||
INSTR0(PREDE)
|
||||
|
||||
/* cat2 instructions, most 2 src but some 1 src: */
|
||||
INSTR2(ADD_F)
|
||||
|
|
|
@ -1536,7 +1536,7 @@ emit_intrinsic(struct ir3_context *ctx, nir_intrinsic_instr *intr)
|
|||
|
||||
case nir_intrinsic_end_patch_ir3:
|
||||
assert(ctx->so->type == MESA_SHADER_TESS_CTRL);
|
||||
struct ir3_instruction *end = ir3_ENDIF(b);
|
||||
struct ir3_instruction *end = ir3_PREDE(b);
|
||||
array_insert(b, b->keeps, end);
|
||||
|
||||
end->barrier_class = IR3_BARRIER_EVERYTHING;
|
||||
|
@ -1933,7 +1933,7 @@ emit_intrinsic(struct ir3_context *ctx, nir_intrinsic_instr *intr)
|
|||
/* condition always goes in predicate register: */
|
||||
cond->regs[0]->num = regid(REG_P0, 0);
|
||||
|
||||
kill = ir3_IF(b, cond, 0);
|
||||
kill = ir3_PREDT(b, cond, 0);
|
||||
|
||||
kill->barrier_class = IR3_BARRIER_EVERYTHING;
|
||||
kill->barrier_conflict = IR3_BARRIER_EVERYTHING;
|
||||
|
|
|
@ -123,7 +123,7 @@ count_instruction(struct ir3_instruction *n)
|
|||
* be eliminated later in resolve_jumps().. really should do that
|
||||
* earlier so we don't have this constraint.
|
||||
*/
|
||||
return is_alu(n) || (is_flow(n) && (n->opc != OPC_JUMP) && (n->opc != OPC_BR));
|
||||
return is_alu(n) || (is_flow(n) && (n->opc != OPC_JUMP) && (n->opc != OPC_B));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -138,7 +138,7 @@ legalize_block(struct ir3_legalize_ctx *ctx, struct ir3_block *block)
|
|||
regmask_init(&state->needs_sy);
|
||||
}
|
||||
|
||||
if (last_n && (last_n->opc == OPC_IF)) {
|
||||
if (last_n && (last_n->opc == OPC_PREDT)) {
|
||||
n->flags |= IR3_INSTR_SS;
|
||||
regmask_init(&state->needs_ss_war);
|
||||
regmask_init(&state->needs_ss);
|
||||
|
@ -574,12 +574,12 @@ block_sched(struct ir3 *ir)
|
|||
/* create "else" branch first (since "then" block should
|
||||
* frequently/always end up being a fall-thru):
|
||||
*/
|
||||
br = ir3_BR(block, block->condition, 0);
|
||||
br = ir3_B(block, block->condition, 0);
|
||||
br->cat0.inv = true;
|
||||
br->cat0.target = block->successors[1];
|
||||
|
||||
/* "then" branch: */
|
||||
br = ir3_BR(block, block->condition, 0);
|
||||
br = ir3_B(block, block->condition, 0);
|
||||
br->cat0.target = block->successors[0];
|
||||
|
||||
} else if (block->successors[0]) {
|
||||
|
@ -633,7 +633,7 @@ kill_sched(struct ir3 *ir, struct ir3_shader_variant *so)
|
|||
if (instr->opc != OPC_KILL)
|
||||
continue;
|
||||
|
||||
struct ir3_instruction *br = ir3_instr_create(block, OPC_BR);
|
||||
struct ir3_instruction *br = ir3_instr_create(block, OPC_B);
|
||||
br->regs[1] = instr->regs[1];
|
||||
br->cat0.target =
|
||||
list_last_entry(&ir->block_list, struct ir3_block, node);
|
||||
|
|
|
@ -596,7 +596,7 @@ cat0_src: '!' T_P0 { instr->cat0.inv = true; instr->cat0.comp =
|
|||
cat0_immed: '#' integer { instr->cat0.immed = $2; }
|
||||
|
||||
cat0_instr: T_OP_NOP { new_instr(OPC_NOP); }
|
||||
| T_OP_BR { new_instr(OPC_BR); } cat0_src ',' cat0_immed
|
||||
| T_OP_BR { new_instr(OPC_B); } cat0_src ',' cat0_immed
|
||||
| T_OP_JUMP { new_instr(OPC_JUMP); } cat0_immed
|
||||
| T_OP_CALL { new_instr(OPC_CALL); } cat0_immed
|
||||
| T_OP_RET { new_instr(OPC_RET); }
|
||||
|
|
|
@ -582,7 +582,7 @@ sched_block(struct ir3_postsched_ctx *ctx, struct ir3_block *block)
|
|||
foreach_instr_safe (instr, &ctx->unscheduled_list) {
|
||||
switch (instr->opc) {
|
||||
case OPC_NOP:
|
||||
case OPC_BR:
|
||||
case OPC_B:
|
||||
case OPC_JUMP:
|
||||
list_delinit(&instr->node);
|
||||
break;
|
||||
|
|
|
@ -264,8 +264,8 @@ print_instr(struct ir3_instruction *instr, int lvl)
|
|||
|
||||
if (is_flow(instr) && instr->cat0.target) {
|
||||
/* the predicate register src is implied: */
|
||||
if (instr->opc == OPC_BR) {
|
||||
printf(" %sp0.x", instr->cat0.inv ? "!" : "");
|
||||
if (instr->opc == OPC_B) {
|
||||
printf("r %sp0.x", instr->cat0.inv ? "!" : "");
|
||||
}
|
||||
printf(", target=block%u", block_id(instr->cat0.target));
|
||||
}
|
||||
|
|
|
@ -41,6 +41,9 @@ static const struct test {
|
|||
INSTR_6XX(03000000_00000000, "end"),
|
||||
INSTR_6XX(00800000_00000004, "br p0.x, #4"),
|
||||
INSTR_6XX(00900000_00000003, "br !p0.x, #3"),
|
||||
INSTR_6XX(03820000_00000015, "shps #21"), /* emit */
|
||||
INSTR_6XX(04021000_00000000, "(ss)shpe"), /* cut */
|
||||
INSTR_6XX(02820000_00000014, "getone #20"), /* kill p0.x */
|
||||
|
||||
/* cat1 */
|
||||
INSTR_6XX(20244000_00000020, "mov.f32f32 r0.x, c8.x"),
|
||||
|
|
Loading…
Reference in New Issue