mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 11:18:08 +02:00
ir3: Support assembling & disassembling getspid/getwid
These aren't useful yet in the driver, but were useful for reverse-engineering how private memory works. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7386>
This commit is contained in:
parent
2cee8642ca
commit
e7471ce776
5 changed files with 86 additions and 53 deletions
|
|
@ -1185,6 +1185,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, ssbo;
|
||||
uint32_t opc = _OPC(6, cat6->opc);
|
||||
bool is_id = opc == OPC_GETSPID || opc == OPC_GETWID;
|
||||
bool uses_type = opc != OPC_LDC;
|
||||
|
||||
static const struct {
|
||||
|
|
@ -1229,35 +1230,44 @@ static void print_instr_cat6_a6xx(struct disasm_ctx *ctx, instr_t *instr)
|
|||
memset(&ssbo, 0, sizeof(ssbo));
|
||||
|
||||
if (uses_type) {
|
||||
fprintf(ctx->out, ".%s", cat6->typed ? "typed" : "untyped");
|
||||
fprintf(ctx->out, ".%dd", cat6->d + 1);
|
||||
if (!is_id) {
|
||||
fprintf(ctx->out, ".%s", cat6->typed ? "typed" : "untyped");
|
||||
fprintf(ctx->out, ".%dd", cat6->d + 1);
|
||||
}
|
||||
fprintf(ctx->out, ".%s", type[cat6->type]);
|
||||
} else {
|
||||
fprintf(ctx->out, ".offset%d", cat6->d);
|
||||
}
|
||||
fprintf(ctx->out, ".%u", cat6->type_size + 1);
|
||||
|
||||
fprintf(ctx->out, ".%s", desc_features[cat6->desc_mode].name);
|
||||
if (bindless)
|
||||
fprintf(ctx->out, ".base%d", cat6->base);
|
||||
if (!is_id) {
|
||||
fprintf(ctx->out, ".%u", cat6->type_size + 1);
|
||||
fprintf(ctx->out, ".%s", desc_features[cat6->desc_mode].name);
|
||||
|
||||
if (bindless)
|
||||
fprintf(ctx->out, ".base%d", cat6->base);
|
||||
}
|
||||
|
||||
fprintf(ctx->out, " ");
|
||||
|
||||
src2.reg = (reg_t)(cat6->src2);
|
||||
src2.full = type_full;
|
||||
print_src(ctx, &src2);
|
||||
fprintf(ctx->out, ", ");
|
||||
|
||||
if (opc != OPC_RESINFO) {
|
||||
src1.reg = (reg_t)(cat6->src1);
|
||||
src1.full = true; // XXX
|
||||
print_src(ctx, &src1);
|
||||
if (!is_id) {
|
||||
fprintf(ctx->out, ", ");
|
||||
}
|
||||
|
||||
ssbo.reg = (reg_t)(cat6->ssbo);
|
||||
ssbo.im = !indirect_ssbo;
|
||||
ssbo.full = true;
|
||||
print_src(ctx, &ssbo);
|
||||
if (opc != OPC_RESINFO) {
|
||||
src1.reg = (reg_t)(cat6->src1);
|
||||
src1.full = true; // XXX
|
||||
print_src(ctx, &src1);
|
||||
fprintf(ctx->out, ", ");
|
||||
}
|
||||
|
||||
ssbo.reg = (reg_t)(cat6->ssbo);
|
||||
ssbo.im = !indirect_ssbo;
|
||||
ssbo.full = true;
|
||||
print_src(ctx, &ssbo);
|
||||
}
|
||||
|
||||
if (debug & PRINT_VERBOSE) {
|
||||
fprintf(ctx->out, " (pad1=%x, pad2=%x, pad3=%x, pad4=%x, pad5=%x)",
|
||||
|
|
|
|||
|
|
@ -537,53 +537,57 @@ static int emit_cat5(struct ir3_instruction *instr, void *ptr,
|
|||
static int emit_cat6_a6xx(struct ir3_instruction *instr, void *ptr,
|
||||
struct ir3_info *info)
|
||||
{
|
||||
struct ir3_register *ssbo;
|
||||
instr_cat6_a6xx_t *cat6 = ptr;
|
||||
|
||||
ssbo = instr->regs[1];
|
||||
|
||||
cat6->type = instr->cat6.type;
|
||||
cat6->d = instr->cat6.d - (instr->opc == OPC_LDC ? 0 : 1);
|
||||
cat6->typed = instr->cat6.typed;
|
||||
cat6->type_size = instr->cat6.iim_val - 1;
|
||||
cat6->opc = instr->opc;
|
||||
cat6->jmp_tgt = !!(instr->flags & IR3_INSTR_JP);
|
||||
cat6->sync = !!(instr->flags & IR3_INSTR_SY);
|
||||
cat6->opc_cat = 6;
|
||||
|
||||
cat6->ssbo = reg(ssbo, info, instr->repeat, IR3_REG_IMMED);
|
||||
|
||||
/* For unused sources in an opcode, initialize contents with the ir3 dest
|
||||
* reg
|
||||
*/
|
||||
switch (instr->opc) {
|
||||
case OPC_RESINFO:
|
||||
cat6->src1 = reg(instr->regs[0], info, instr->repeat, 0);
|
||||
if (instr->opc == OPC_GETWID || instr->opc == OPC_GETSPID) {
|
||||
cat6->src2 = reg(instr->regs[0], info, instr->repeat, 0);
|
||||
break;
|
||||
case OPC_LDC:
|
||||
case OPC_LDIB:
|
||||
cat6->src1 = reg(instr->regs[2], info, instr->repeat, 0);
|
||||
cat6->src2 = reg(instr->regs[0], info, instr->repeat, 0);
|
||||
break;
|
||||
default:
|
||||
cat6->src1 = reg(instr->regs[2], info, instr->repeat, 0);
|
||||
cat6->src2 = reg(instr->regs[3], info, instr->repeat, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (instr->flags & IR3_INSTR_B) {
|
||||
if (ssbo->flags & IR3_REG_IMMED) {
|
||||
cat6->desc_mode = CAT6_BINDLESS_IMM;
|
||||
} else {
|
||||
cat6->desc_mode = CAT6_BINDLESS_UNIFORM;
|
||||
}
|
||||
cat6->base = instr->cat6.base;
|
||||
cat6->src1 = cat6->ssbo = 0;
|
||||
cat6->d = cat6->typed = cat6->type_size = 0;
|
||||
} else {
|
||||
if (ssbo->flags & IR3_REG_IMMED)
|
||||
cat6->desc_mode = CAT6_IMM;
|
||||
else
|
||||
cat6->desc_mode = CAT6_UNIFORM;
|
||||
struct ir3_register *ssbo = instr->regs[1];
|
||||
cat6->d = instr->cat6.d - (instr->opc == OPC_LDC ? 0 : 1);
|
||||
cat6->typed = instr->cat6.typed;
|
||||
cat6->type_size = instr->cat6.iim_val - 1;
|
||||
cat6->ssbo = reg(ssbo, info, instr->repeat, IR3_REG_IMMED);
|
||||
|
||||
/* For unused sources in an opcode, initialize contents with the ir3
|
||||
* dest reg
|
||||
*/
|
||||
switch (instr->opc) {
|
||||
case OPC_RESINFO:
|
||||
cat6->src1 = reg(instr->regs[0], info, instr->repeat, 0);
|
||||
cat6->src2 = reg(instr->regs[0], info, instr->repeat, 0);
|
||||
break;
|
||||
case OPC_LDC:
|
||||
case OPC_LDIB:
|
||||
cat6->src1 = reg(instr->regs[2], info, instr->repeat, 0);
|
||||
cat6->src2 = reg(instr->regs[0], info, instr->repeat, 0);
|
||||
break;
|
||||
default:
|
||||
cat6->src1 = reg(instr->regs[2], info, instr->repeat, 0);
|
||||
cat6->src2 = reg(instr->regs[3], info, instr->repeat, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (instr->flags & IR3_INSTR_B) {
|
||||
if (ssbo->flags & IR3_REG_IMMED) {
|
||||
cat6->desc_mode = CAT6_BINDLESS_IMM;
|
||||
} else {
|
||||
cat6->desc_mode = CAT6_BINDLESS_UNIFORM;
|
||||
}
|
||||
cat6->base = instr->cat6.base;
|
||||
} else {
|
||||
if (ssbo->flags & IR3_REG_IMMED)
|
||||
cat6->desc_mode = CAT6_IMM;
|
||||
else
|
||||
cat6->desc_mode = CAT6_UNIFORM;
|
||||
}
|
||||
}
|
||||
|
||||
switch (instr->opc) {
|
||||
|
|
@ -614,6 +618,8 @@ static int emit_cat6_a6xx(struct ir3_instruction *instr, void *ptr,
|
|||
cat6->pad5 = 0x2;
|
||||
break;
|
||||
case OPC_LDC:
|
||||
case OPC_GETWID:
|
||||
case OPC_GETSPID:
|
||||
cat6->pad1 = 0x0;
|
||||
cat6->pad3 = 0x4;
|
||||
cat6->pad5 = 0x2;
|
||||
|
|
@ -658,6 +664,8 @@ static int emit_cat6(struct ir3_instruction *instr, void *ptr,
|
|||
case OPC_LDIB:
|
||||
case OPC_LDC:
|
||||
case OPC_RESINFO:
|
||||
case OPC_GETSPID:
|
||||
case OPC_GETWID:
|
||||
return emit_cat6_a6xx(instr, ptr, info);
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -264,6 +264,8 @@ static int parse_reg(const char *str)
|
|||
"stib" return TOKEN(T_OP_STIB);
|
||||
"ldc" return TOKEN(T_OP_LDC);
|
||||
"ldlv" return TOKEN(T_OP_LDLV);
|
||||
"getspid" return TOKEN(T_OP_GETSPID);
|
||||
"getwid" return TOKEN(T_OP_GETWID);
|
||||
|
||||
"f16" return TOKEN(T_TYPE_F16);
|
||||
"f32" return TOKEN(T_TYPE_F32);
|
||||
|
|
|
|||
|
|
@ -439,6 +439,8 @@ static void print_token(FILE *file, int type, YYSTYPE value)
|
|||
%token <tok> T_OP_STIB
|
||||
%token <tok> T_OP_LDC
|
||||
%token <tok> T_OP_LDLV
|
||||
%token <tok> T_OP_GETSPID
|
||||
%token <tok> T_OP_GETWID
|
||||
|
||||
/* type qualifiers: */
|
||||
%token <tok> T_TYPE_F16
|
||||
|
|
@ -811,6 +813,12 @@ cat6_atomic: T_OP_ATOMIC_ADD { new_instr(OPC_ATOMIC_ADD); } cat6_at
|
|||
| T_OP_ATOMIC_OR { new_instr(OPC_ATOMIC_OR); } cat6_atomic_l_g cat6_type dst_reg ',' 'l' '[' reg cat6_offset ']' ',' cat6_immed
|
||||
| T_OP_ATOMIC_XOR { new_instr(OPC_ATOMIC_XOR); } cat6_atomic_l_g cat6_type dst_reg ',' 'l' '[' reg cat6_offset ']' ',' cat6_immed
|
||||
|
||||
cat6_id_opc:
|
||||
T_OP_GETSPID { new_instr(OPC_GETSPID); }
|
||||
| T_OP_GETWID { new_instr(OPC_GETWID); }
|
||||
|
||||
cat6_id: cat6_id_opc cat6_type dst_reg
|
||||
|
||||
cat6_todo: T_OP_G2L { new_instr(OPC_G2L); }
|
||||
| T_OP_L2G { new_instr(OPC_L2G); }
|
||||
| T_OP_RESFMT { new_instr(OPC_RESFMT); }
|
||||
|
|
@ -824,6 +832,7 @@ cat6_instr: cat6_load
|
|||
| cat6_storeib
|
||||
| cat6_prefetch
|
||||
| cat6_atomic
|
||||
| cat6_id
|
||||
| cat6_todo
|
||||
|
||||
reg: T_REGISTER { $$ = new_reg($1, 0); }
|
||||
|
|
|
|||
|
|
@ -192,6 +192,10 @@ static const struct test {
|
|||
INSTR_6XX(a0c81f07_0100000b, "sam.s2en (f32)(xyzw)r1.w, r1.y, hr2.x"), /* sam.s2en.mode0 (f32)(xyzw)r1.w, r1.y, hr2.x */
|
||||
/* dEQP-GLES31.functional.shaders.opaque_type_indexing.sampler.dynamically_uniform.fragment.sampler2d */
|
||||
INSTR_6XX(a0c81f07_8100000b, "sam.s2en.uniform (f32)(xyzw)r1.w, r1.y, hr2.x"), /* sam.s2en.mode4 (f32)(xyzw)r1.w, r1.y, hr2.x */
|
||||
|
||||
/* Custom test since we've never seen the blob emit these. */
|
||||
INSTR_6XX(c0260004_00490000, "getspid.u32 r1.x"),
|
||||
INSTR_6XX(c0260005_00494000, "getwid.u32 r1.y"),
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue