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