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)
#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),
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, ),
}
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)
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),
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),
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 {
};
/* 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;
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;
}
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;
}
#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)
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;
/* 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;
* 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));
}
/**
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);
/* 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]) {
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);
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); }
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;
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));
}
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"),