Mesa (master): ir3: Support assembling & disassembling getspid/getwid
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Thu Nov 19 17:12:47 UTC 2020
Module: Mesa
Branch: master
Commit: e7471ce77612b746b01a4926a7d04b0921044ae0
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=e7471ce77612b746b01a4926a7d04b0921044ae0
Author: Connor Abbott <cwabbott0 at gmail.com>
Date: Fri Oct 23 14:07:04 2020 +0200
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>
---
src/freedreno/ir3/disasm-a3xx.c | 42 +++++++++++++---------
src/freedreno/ir3/ir3.c | 78 ++++++++++++++++++++++------------------
src/freedreno/ir3/ir3_lexer.l | 2 ++
src/freedreno/ir3/ir3_parser.y | 9 +++++
src/freedreno/ir3/tests/disasm.c | 4 +++
5 files changed, 84 insertions(+), 51 deletions(-)
diff --git a/src/freedreno/ir3/disasm-a3xx.c b/src/freedreno/ir3/disasm-a3xx.c
index 420d27442a8..66699e66880 100644
--- a/src/freedreno/ir3/disasm-a3xx.c
+++ b/src/freedreno/ir3/disasm-a3xx.c
@@ -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)",
diff --git a/src/freedreno/ir3/ir3.c b/src/freedreno/ir3/ir3.c
index 8966e7afecc..05720b44dc2 100644
--- a/src/freedreno/ir3/ir3.c
+++ b/src/freedreno/ir3/ir3.c
@@ -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;
- }
+ cat6->src1 = cat6->ssbo = 0;
+ cat6->d = cat6->typed = cat6->type_size = 0;
+ } else {
+ 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;
+ 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 {
- cat6->desc_mode = CAT6_BINDLESS_UNIFORM;
+ if (ssbo->flags & IR3_REG_IMMED)
+ cat6->desc_mode = CAT6_IMM;
+ else
+ cat6->desc_mode = CAT6_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;
diff --git a/src/freedreno/ir3/ir3_lexer.l b/src/freedreno/ir3/ir3_lexer.l
index f93d25b5328..b0ba0032c4a 100644
--- a/src/freedreno/ir3/ir3_lexer.l
+++ b/src/freedreno/ir3/ir3_lexer.l
@@ -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);
diff --git a/src/freedreno/ir3/ir3_parser.y b/src/freedreno/ir3/ir3_parser.y
index 945a3e0d1ce..fbb0c3f6fae 100644
--- a/src/freedreno/ir3/ir3_parser.y
+++ b/src/freedreno/ir3/ir3_parser.y
@@ -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); }
diff --git a/src/freedreno/ir3/tests/disasm.c b/src/freedreno/ir3/tests/disasm.c
index 1b16fad6957..1747f05393b 100644
--- a/src/freedreno/ir3/tests/disasm.c
+++ b/src/freedreno/ir3/tests/disasm.c
@@ -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
More information about the mesa-commit
mailing list