Mesa (master): freedreno/ir3: sync instr/disasm

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Dec 7 18:50:40 UTC 2018


Module: Mesa
Branch: master
Commit: e37351fa5713aab95bc5a6af78866388d5eda70b
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=e37351fa5713aab95bc5a6af78866388d5eda70b

Author: Rob Clark <robdclark at gmail.com>
Date:   Wed Nov  7 13:22:12 2018 -0500

freedreno/ir3: sync instr/disasm

Signed-off-by: Rob Clark <robdclark at gmail.com>

---

 src/freedreno/ir3/disasm-a3xx.c        | 94 ++++++++++++++++++++++++++++------
 src/freedreno/ir3/instr-a3xx.h         | 59 ++++++++++++++++++---
 src/freedreno/ir3/ir3_shader.c         |  2 +-
 src/gallium/drivers/freedreno/disasm.h |  2 +-
 4 files changed, 132 insertions(+), 25 deletions(-)

diff --git a/src/freedreno/ir3/disasm-a3xx.c b/src/freedreno/ir3/disasm-a3xx.c
index 4cf45ce922..9c0432c67a 100644
--- a/src/freedreno/ir3/disasm-a3xx.c
+++ b/src/freedreno/ir3/disasm-a3xx.c
@@ -77,6 +77,7 @@ static const char *type[] = {
 struct disasm_ctx {
 	FILE *out;
 	int level;
+	unsigned gpu_id;
 
 	/* current instruction repeat flag: */
 	unsigned repeat;
@@ -117,7 +118,7 @@ static void print_reg(struct disasm_ctx *ctx, reg_t reg, bool full, bool r,
 	} else if ((reg.num == REG_P0) && !c) {
 		fprintf(ctx->out, "p0.%c", component[reg.comp]);
 	} else {
-		fprintf(ctx->out, "%s%c%d.%c", full ? "" : "h", type, reg.num & 0x3f, component[reg.comp]);
+		fprintf(ctx->out, "%s%c%d.%c", full ? "" : "h", type, reg.num, component[reg.comp]);
 	}
 }
 
@@ -271,20 +272,22 @@ static void print_instr_cat2(struct disasm_ctx *ctx, instr_t *instr)
 	print_reg_dst(ctx, (reg_t)(cat2->dst), cat2->full ^ cat2->dst_half, false);
 	fprintf(ctx->out, ", ");
 
+	unsigned src1_r = cat2->repeat ? cat2->src1_r : 0;
 	if (cat2->c1.src1_c) {
-		print_reg_src(ctx, (reg_t)(cat2->c1.src1), cat2->full, cat2->src1_r,
+		print_reg_src(ctx, (reg_t)(cat2->c1.src1), cat2->full, src1_r,
 				cat2->c1.src1_c, cat2->src1_im, cat2->src1_neg,
 				cat2->src1_abs, false);
 	} else if (cat2->rel1.src1_rel) {
-		print_reg_src(ctx, (reg_t)(cat2->rel1.src1), cat2->full, cat2->src1_r,
+		print_reg_src(ctx, (reg_t)(cat2->rel1.src1), cat2->full, src1_r,
 				cat2->rel1.src1_c, cat2->src1_im, cat2->src1_neg,
 				cat2->src1_abs, cat2->rel1.src1_rel);
 	} else {
-		print_reg_src(ctx, (reg_t)(cat2->src1), cat2->full, cat2->src1_r,
+		print_reg_src(ctx, (reg_t)(cat2->src1), cat2->full, src1_r,
 				false, cat2->src1_im, cat2->src1_neg,
 				cat2->src1_abs, false);
 	}
 
+	unsigned src2_r = cat2->repeat ? cat2->src2_r : 0;
 	switch (_OPC(2, cat2->opc)) {
 	case OPC_ABSNEG_F:
 	case OPC_ABSNEG_S:
@@ -305,15 +308,15 @@ static void print_instr_cat2(struct disasm_ctx *ctx, instr_t *instr)
 	default:
 		fprintf(ctx->out, ", ");
 		if (cat2->c2.src2_c) {
-			print_reg_src(ctx, (reg_t)(cat2->c2.src2), cat2->full, cat2->src2_r,
+			print_reg_src(ctx, (reg_t)(cat2->c2.src2), cat2->full, src2_r,
 					cat2->c2.src2_c, cat2->src2_im, cat2->src2_neg,
 					cat2->src2_abs, false);
 		} else if (cat2->rel2.src2_rel) {
-			print_reg_src(ctx, (reg_t)(cat2->rel2.src2), cat2->full, cat2->src2_r,
+			print_reg_src(ctx, (reg_t)(cat2->rel2.src2), cat2->full, src2_r,
 					cat2->rel2.src2_c, cat2->src2_im, cat2->src2_neg,
 					cat2->src2_abs, cat2->rel2.src2_rel);
 		} else {
-			print_reg_src(ctx, (reg_t)(cat2->src2), cat2->full, cat2->src2_r,
+			print_reg_src(ctx, (reg_t)(cat2->src2), cat2->full, src2_r,
 					false, cat2->src2_im, cat2->src2_neg,
 					cat2->src2_abs, false);
 		}
@@ -329,22 +332,24 @@ static void print_instr_cat3(struct disasm_ctx *ctx, instr_t *instr)
 	fprintf(ctx->out, " ");
 	print_reg_dst(ctx, (reg_t)(cat3->dst), full ^ cat3->dst_half, false);
 	fprintf(ctx->out, ", ");
+	unsigned src1_r = cat3->repeat ? cat3->src1_r : 0;
 	if (cat3->c1.src1_c) {
 		print_reg_src(ctx, (reg_t)(cat3->c1.src1), full,
-				cat3->src1_r, cat3->c1.src1_c, false, cat3->src1_neg,
+				src1_r, cat3->c1.src1_c, false, cat3->src1_neg,
 				false, false);
 	} else if (cat3->rel1.src1_rel) {
 		print_reg_src(ctx, (reg_t)(cat3->rel1.src1), full,
-				cat3->src1_r, cat3->rel1.src1_c, false, cat3->src1_neg,
+				src1_r, cat3->rel1.src1_c, false, cat3->src1_neg,
 				false, cat3->rel1.src1_rel);
 	} else {
 		print_reg_src(ctx, (reg_t)(cat3->src1), full,
-				cat3->src1_r, false, false, cat3->src1_neg,
+				src1_r, false, false, cat3->src1_neg,
 				false, false);
 	}
 	fprintf(ctx->out, ", ");
+	unsigned src2_r = cat3->repeat ? cat3->src2_r : 0;
 	print_reg_src(ctx, (reg_t)cat3->src2, full,
-			cat3->src2_r, cat3->src2_c, false, cat3->src2_neg,
+			src2_r, cat3->src2_c, false, cat3->src2_neg,
 			false, false);
 	fprintf(ctx->out, ", ");
 	if (cat3->c2.src3_c) {
@@ -487,7 +492,7 @@ static void print_instr_cat5(struct disasm_ctx *ctx, instr_t *instr)
 	}
 }
 
-static void print_instr_cat6(struct disasm_ctx *ctx, instr_t *instr)
+static void print_instr_cat6_a3xx(struct disasm_ctx *ctx, instr_t *instr)
 {
 	instr_cat6_t *cat6 = &instr->cat6;
 	char sd = 0, ss = 0;  /* dst/src address space */
@@ -779,6 +784,55 @@ static void print_instr_cat6(struct disasm_ctx *ctx, instr_t *instr)
 	}
 }
 
+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;
+	char ss = 0;
+
+	memset(&src1, 0, sizeof(src1));
+	memset(&src2, 0, sizeof(src2));
+
+	fprintf(ctx->out, ".%s", cat6->typed ? "typed" : "untyped");
+	fprintf(ctx->out, ".%dd", cat6->d + 1);
+	fprintf(ctx->out, ".%s", type[cat6->type]);
+	fprintf(ctx->out, ".%u ", cat6->type_size + 1);
+
+	/* NOTE: blob seems to use old encoding for ldl/stl (local memory) */
+	ss = 'g';
+
+	fprintf(ctx->out, "%c[%u", ss, cat6->ssbo);
+	fprintf(ctx->out, "] + ");
+	src1.reg = (reg_t)(cat6->src1);
+	src1.full = true; // XXX
+	print_src(ctx, &src1);
+	fprintf(ctx->out, ", ");
+
+	src2.reg = (reg_t)(cat6->src2);
+	src2.full = true; // XXX
+	print_src(ctx, &src2);
+
+	if (debug & PRINT_VERBOSE) {
+		fprintf(ctx->out, " (pad1=%x, pad2=%x, pad3=%x, pad4=%x)", cat6->pad1,
+				cat6->pad2, cat6->pad3, cat6->pad4);
+	}
+}
+
+static void print_instr_cat6(struct disasm_ctx *ctx, instr_t *instr)
+{
+	// TODO not sure if this is the best way to figure
+	// out if new vs old encoding, but it kinda seems
+	// to work:
+	if ((ctx->gpu_id >= 600) && (instr->cat6.opc == 0)) {
+		print_instr_cat6_a6xx(ctx, instr);
+		if (debug & PRINT_VERBOSE)
+			fprintf(ctx->out, " NEW");
+	} else {
+		print_instr_cat6_a3xx(ctx, instr);
+		if (debug & PRINT_VERBOSE)
+			fprintf(ctx->out, " LEGACY");
+	}
+}
 static void print_instr_cat7(struct disasm_ctx *ctx, instr_t *instr)
 {
 	instr_cat7_t *cat7 = &instr->cat7;
@@ -967,7 +1021,7 @@ static const struct opc_info {
 #undef OPC
 };
 
-#define GETINFO(instr) (&(opcs[((instr)->opc_cat << NOPC_BITS) | instr_opc(instr)]))
+#define GETINFO(instr) (&(opcs[((instr)->opc_cat << NOPC_BITS) | instr_opc(instr, ctx->gpu_id)]))
 
 // XXX hack.. probably should move this table somewhere common:
 #include "ir3.h"
@@ -980,7 +1034,7 @@ const char *ir3_instr_name(struct ir3_instruction *instr)
 static bool print_instr(struct disasm_ctx *ctx, uint32_t *dwords, int n)
 {
 	instr_t *instr = (instr_t *)dwords;
-	uint32_t opc = instr_opc(instr);
+	uint32_t opc = instr_opc(instr, ctx->gpu_id);
 	const char *name;
 
 	if (debug & PRINT_VERBOSE)
@@ -1001,8 +1055,15 @@ static bool print_instr(struct disasm_ctx *ctx, uint32_t *dwords, int n)
 		fprintf(ctx->out, "(jp)");
 	if (instr_sat(instr))
 		fprintf(ctx->out, "(sat)");
-	if (ctx->repeat)
+	if (ctx->repeat) {
 		fprintf(ctx->out, "(rpt%d)", ctx->repeat);
+	} else if ((instr->opc_cat == 2) && (instr->cat2.src1_r || instr->cat2.src2_r)) {
+		unsigned nop = (instr->cat2.src2_r * 2) + instr->cat2.src1_r;
+		fprintf(ctx->out, "(nop%d)", nop);
+	} else if ((instr->opc_cat == 3) && (instr->cat3.src1_r || instr->cat3.src2_r)) {
+		unsigned nop = (instr->cat3.src2_r * 2) + instr->cat3.src1_r;
+		fprintf(ctx->out, "(nop%d)", nop);
+	}
 	if (instr->ul && ((2 <= instr->opc_cat) && (instr->opc_cat <= 4)))
 		fprintf(ctx->out, "(ul)");
 
@@ -1020,7 +1081,7 @@ static bool print_instr(struct disasm_ctx *ctx, uint32_t *dwords, int n)
 	return (instr->opc_cat == 0) && (opc == OPC_END);
 }
 
-int disasm_a3xx(uint32_t *dwords, int sizedwords, int level, FILE *out)
+int disasm_a3xx(uint32_t *dwords, int sizedwords, int level, FILE *out, unsigned gpu_id)
 {
 	struct disasm_ctx ctx;
 	int i;
@@ -1030,6 +1091,7 @@ int disasm_a3xx(uint32_t *dwords, int sizedwords, int level, FILE *out)
 	memset(&ctx, 0, sizeof(ctx));
 	ctx.out = out;
 	ctx.level = level;
+	ctx.gpu_id = gpu_id;
 
 	for (i = 0; i < sizedwords; i += 2)
 		print_instr(&ctx, &dwords[i], i/2);
diff --git a/src/freedreno/ir3/instr-a3xx.h b/src/freedreno/ir3/instr-a3xx.h
index 7f60ee5fd4..eff720dacd 100644
--- a/src/freedreno/ir3/instr-a3xx.h
+++ b/src/freedreno/ir3/instr-a3xx.h
@@ -413,13 +413,13 @@ typedef struct PACKED {
 	uint32_t dst      : 8;
 	uint32_t repeat   : 2;
 	uint32_t sat      : 1;
-	uint32_t src1_r   : 1;
+	uint32_t src1_r   : 1;   /* doubles as nop0 if repeat==0 */
 	uint32_t ss       : 1;
 	uint32_t ul       : 1;   /* dunno */
 	uint32_t dst_half : 1;   /* or widen/narrow.. ie. dst hrN <-> rN */
 	uint32_t ei       : 1;
 	uint32_t cond     : 3;
-	uint32_t src2_r   : 1;
+	uint32_t src2_r   : 1;   /* doubles as nop1 if repeat==0 */
 	uint32_t full     : 1;   /* not half */
 	uint32_t opc      : 6;
 	uint32_t jmp_tgt  : 1;
@@ -435,7 +435,7 @@ typedef struct PACKED {
 			uint32_t must_be_zero1: 2;
 			uint32_t src2_c       : 1;
 			uint32_t src1_neg     : 1;
-			uint32_t src2_r       : 1;
+			uint32_t src2_r       : 1;  /* doubles as nop1 if repeat==0 */
 		};
 		struct PACKED {
 			uint32_t src1         : 10;
@@ -477,7 +477,7 @@ typedef struct PACKED {
 	uint32_t dst      : 8;
 	uint32_t repeat   : 2;
 	uint32_t sat      : 1;
-	uint32_t src1_r   : 1;
+	uint32_t src1_r   : 1;   /* doubles as nop0 if repeat==0 */
 	uint32_t ss       : 1;
 	uint32_t ul       : 1;
 	uint32_t dst_half : 1;   /* or widen/narrow.. ie. dst hrN <-> rN */
@@ -727,6 +727,44 @@ typedef union PACKED {
 	};
 } instr_cat6_t;
 
+/**
+ * For atomic ops (which return a value):
+ *
+ *    pad1=1, pad2=c, pad3=0, pad4=3
+ *    src1    - vecN offset/coords
+ *    src2.x  - is actually dest register
+ *    src2.y  - is 'data' except for cmpxchg where src2.y is 'compare'
+ *              and src2.z is 'data'
+ *
+ * For stib (which does not return a value):
+ *    pad1=0, pad2=c, pad3=0, pad4=2
+ *    src1    - vecN offset/coords
+ *    src2    - value to store
+ *
+ * for ldc (load from UBO using descriptor):
+ *    pad1=0, pad2=8, pad3=0, pad4=2
+ */
+typedef struct PACKED {
+	/* dword0: */
+	uint32_t pad1     : 9;
+	uint32_t d        : 2;
+	uint32_t typed    : 1;
+	uint32_t type_size : 2;
+	uint32_t opc      : 5;
+	uint32_t pad2     : 5;
+	uint32_t src1     : 8;  /* coordinate/offset */
+
+	/* dword1: */
+	uint32_t src2     : 8;
+	uint32_t pad3     : 1;  //mustbe0 ?? or zero means imm vs reg for ssbo??
+	uint32_t ssbo     : 8;  /* ssbo/image binding point */
+	uint32_t type     : 3;
+	uint32_t pad4     : 7;
+	uint32_t jmp_tgt  : 1;
+	uint32_t sync     : 1;
+	uint32_t opc_cat  : 3;
+} instr_cat6_a6xx_t;
+
 typedef struct PACKED {
 	/* dword0: */
 	uint32_t pad1     : 32;
@@ -753,6 +791,7 @@ typedef union PACKED {
 	instr_cat4_t cat4;
 	instr_cat5_t cat5;
 	instr_cat6_t cat6;
+	instr_cat6_a6xx_t cat6_a6xx;
 	instr_cat7_t cat7;
 	struct PACKED {
 		/* dword0: */
@@ -792,7 +831,7 @@ static inline bool instr_sat(instr_t *instr)
 	}
 }
 
-static inline uint32_t instr_opc(instr_t *instr)
+static inline uint32_t instr_opc(instr_t *instr, unsigned gpu_id)
 {
 	switch (instr->opc_cat) {
 	case 0:  return instr->cat0.opc;
@@ -801,7 +840,13 @@ static inline uint32_t instr_opc(instr_t *instr)
 	case 3:  return instr->cat3.opc;
 	case 4:  return instr->cat4.opc;
 	case 5:  return instr->cat5.opc;
-	case 6:  return instr->cat6.opc;
+	case 6:
+		// TODO not sure if this is the best way to figure
+		// out if new vs old encoding, but it kinda seems
+		// to work:
+		if ((gpu_id >= 600) && (instr->cat6.opc == 0))
+			return instr->cat6_a6xx.opc;
+		return instr->cat6.opc;
 	case 7:  return instr->cat7.opc;
 	default: return 0;
 	}
@@ -867,6 +912,6 @@ static inline bool is_ssbo(opc_t opc)
 	}
 }
 
-int disasm_a3xx(uint32_t *dwords, int sizedwords, int level, FILE *out);
+int disasm_a3xx(uint32_t *dwords, int sizedwords, int level, FILE *out, unsigned gpu_id);
 
 #endif /* INSTR_A3XX_H_ */
diff --git a/src/freedreno/ir3/ir3_shader.c b/src/freedreno/ir3/ir3_shader.c
index 8b18e950cc..74d92e1396 100644
--- a/src/freedreno/ir3/ir3_shader.c
+++ b/src/freedreno/ir3/ir3_shader.c
@@ -329,7 +329,7 @@ ir3_shader_disasm(struct ir3_shader_variant *so, uint32_t *bin, FILE *out)
 				so->immediates[i].val[3]);
 	}
 
-	disasm_a3xx(bin, so->info.sizedwords, 0, out);
+	disasm_a3xx(bin, so->info.sizedwords, 0, out, ir->compiler->gpu_id);
 
 	switch (so->type) {
 	case MESA_SHADER_VERTEX:
diff --git a/src/gallium/drivers/freedreno/disasm.h b/src/gallium/drivers/freedreno/disasm.h
index 9de87d8de5..dc29b2fbd2 100644
--- a/src/gallium/drivers/freedreno/disasm.h
+++ b/src/gallium/drivers/freedreno/disasm.h
@@ -37,7 +37,7 @@ enum debug_t {
 };
 
 int disasm_a2xx(uint32_t *dwords, int sizedwords, int level, gl_shader_stage type);
-int disasm_a3xx(uint32_t *dwords, int sizedwords, int level, FILE *out);
+int disasm_a3xx(uint32_t *dwords, int sizedwords, int level, FILE *out, unsigned gpu_id);
 void disasm_set_debug(enum debug_t debug);
 
 #endif /* DISASM_H_ */




More information about the mesa-commit mailing list