Mesa (master): freedreno/a3xx: fix const/rel/const-rel encoding

Rob Clark robclark at kemper.freedesktop.org
Fri Oct 25 00:22:27 UTC 2013


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

Author: Rob Clark <robclark at freedesktop.org>
Date:   Thu Oct 24 17:45:27 2013 -0400

freedreno/a3xx: fix const/rel/const-rel encoding

The encoding of constant, relative, and relative-const src registers is
a bit more complex than originally thought, which gives an extra bit to
encode const reg # at expense of taking a bit from relative offset.

In most cases a3xx seems to actually use a scheme whereby it can encode
an extra bit for const register.  You have three possible encodings in
thirteen bits:

   register:  (11 bits for N.c)
     00........... rN.c

   relative:  (10 bits for N)
     010.......... r<a0.x + N>
     011.......... c<a0.x + N>

   const:     (12 bits for N.c)
     1............ cN.c

Which means we can deal w/ more consts than previously thought.

Signed-off-by: Rob Clark <robclark at freedesktop.org>

---

 src/gallium/drivers/freedreno/a3xx/disasm-a3xx.c |   93 +++++++++++---
 src/gallium/drivers/freedreno/a3xx/instr-a3xx.h  |  149 +++++++++++++++++-----
 src/gallium/drivers/freedreno/a3xx/ir-a3xx.c     |  136 +++++++++++++++-----
 src/gallium/drivers/freedreno/freedreno_screen.c |    8 +-
 4 files changed, 299 insertions(+), 87 deletions(-)

diff --git a/src/gallium/drivers/freedreno/a3xx/disasm-a3xx.c b/src/gallium/drivers/freedreno/a3xx/disasm-a3xx.c
index 4db095f..d9bc499 100644
--- a/src/gallium/drivers/freedreno/a3xx/disasm-a3xx.c
+++ b/src/gallium/drivers/freedreno/a3xx/disasm-a3xx.c
@@ -111,7 +111,7 @@ static void print_reg(reg_t reg, bool full, bool r, bool c, bool im,
  * write-after-read (output.. but not 100%)..
  */
 
-#define MAX_REG 128
+#define MAX_REG 4096
 
 typedef struct {
 	uint8_t full[MAX_REG/8];
@@ -317,8 +317,7 @@ static void print_instr_cat1(instr_t *instr)
 {
 	instr_cat1_t *cat1 = &instr->cat1;
 
-	// XXX maybe a bug in libllvm disassembler?
-	if (cat1->src_rel)
+	if (cat1->ul)
 		printf("(ul)");
 
 	if (cat1->src_type == cat1->dst_type) {
@@ -355,10 +354,11 @@ static void print_instr_cat1(instr_t *instr)
 		/* I would just use %+d but trying to make it diff'able with
 		 * libllvm-a3xx...
 		 */
+		char type = cat1->src_rel_c ? 'c' : 'r';
 		if (cat1->off < 0)
-			printf("c<a0.x - %d>", -cat1->off);
+			printf("%c<a0.x - %d>", type, -cat1->off);
 		else if (cat1->off > 0)
-			printf("c<a0.x + %d>", cat1->off);
+			printf("%c<a0.x + %d>", type, cat1->off);
 		else
 			printf("c<a0.x>");
 	} else {
@@ -399,9 +399,21 @@ static void print_instr_cat2(instr_t *instr)
 		printf("(ei)");
 	print_reg_dst((reg_t)(cat2->dst), cat2->full ^ cat2->dst_half, false);
 	printf(", ");
-	print_reg_src((reg_t)(cat2->src1), cat2->full, cat2->src1_r,
-			cat2->src1_c, cat2->src1_im, cat2->src1_neg,
-			cat2->src1_abs, cat2->src1_rel);
+
+	if (cat2->c1.src1_c) {
+		print_reg_src((reg_t)(cat2->c1.src1), cat2->full, cat2->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((reg_t)(cat2->rel1.src1), cat2->full, cat2->src1_r,
+				cat2->rel1.src1_c, cat2->src1_im, cat2->src1_neg,
+				cat2->src1_abs, cat2->rel1.src1_rel);
+	} else {
+		print_reg_src((reg_t)(cat2->src1), cat2->full, cat2->src1_r,
+				false, cat2->src1_im, cat2->src1_neg,
+				cat2->src1_abs, false);
+	}
+
 	switch (cat2->opc) {
 	case OPC_ABSNEG_F:
 	case OPC_ABSNEG_S:
@@ -421,9 +433,19 @@ static void print_instr_cat2(instr_t *instr)
 		break;
 	default:
 		printf(", ");
-		print_reg_src((reg_t)(cat2->src2), cat2->full, cat2->src2_r,
-				cat2->src2_c, cat2->src2_im, cat2->src2_neg,
-				cat2->src2_abs, cat2->src2_rel);
+		if (cat2->c2.src2_c) {
+			print_reg_src((reg_t)(cat2->c2.src2), cat2->full, cat2->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((reg_t)(cat2->rel2.src2), cat2->full, cat2->src2_r,
+					cat2->rel2.src2_c, cat2->src2_im, cat2->src2_neg,
+					cat2->src2_abs, cat2->rel2.src2_rel);
+		} else {
+			print_reg_src((reg_t)(cat2->src2), cat2->full, cat2->src2_r,
+					false, cat2->src2_im, cat2->src2_neg,
+					cat2->src2_abs, false);
+		}
 		break;
 	}
 }
@@ -450,17 +472,37 @@ static void print_instr_cat3(instr_t *instr)
 	printf(" ");
 	print_reg_dst((reg_t)(cat3->dst), full ^ cat3->dst_half, false);
 	printf(", ");
-	print_reg_src((reg_t)(cat3->src1), full,
-			cat3->src1_r, cat3->src1_c, false, cat3->src1_neg,
-			false, cat3->src1_rel);
+	if (cat3->c1.src1_c) {
+		print_reg_src((reg_t)(cat3->c1.src1), full,
+				cat3->src1_r, cat3->c1.src1_c, false, cat3->src1_neg,
+				false, false);
+	} else if (cat3->rel1.src1_rel) {
+		print_reg_src((reg_t)(cat3->rel1.src1), full,
+				cat3->src1_r, cat3->rel1.src1_c, false, cat3->src1_neg,
+				false, cat3->rel1.src1_rel);
+	} else {
+		print_reg_src((reg_t)(cat3->src1), full,
+				cat3->src1_r, false, false, cat3->src1_neg,
+				false, false);
+	}
 	printf(", ");
 	print_reg_src((reg_t)cat3->src2, full,
 			cat3->src2_r, cat3->src2_c, false, cat3->src2_neg,
 			false, false);
 	printf(", ");
-	print_reg_src((reg_t)(cat3->src3), full,
-			cat3->src3_r, cat3->src3_c, false, cat3->src3_neg,
-			false, cat3->src3_rel);
+	if (cat3->c2.src3_c) {
+		print_reg_src((reg_t)(cat3->c2.src3), full,
+				cat3->src3_r, cat3->c2.src3_c, false, cat3->src3_neg,
+				false, false);
+	} else if (cat3->rel2.src3_rel) {
+		print_reg_src((reg_t)(cat3->rel2.src3), full,
+				cat3->src3_r, cat3->rel2.src3_c, false, cat3->src3_neg,
+				false, cat3->rel2.src3_rel);
+	} else {
+		print_reg_src((reg_t)(cat3->src3), full,
+				cat3->src3_r, false, false, cat3->src3_neg,
+				false, false);
+	}
 }
 
 static void print_instr_cat4(instr_t *instr)
@@ -470,9 +512,20 @@ static void print_instr_cat4(instr_t *instr)
 	printf(" ");
 	print_reg_dst((reg_t)(cat4->dst), cat4->full ^ cat4->dst_half, false);
 	printf(", ");
-	print_reg_src((reg_t)(cat4->src), cat4->full,
-			cat4->src_r, cat4->src_c, cat4->src_im,
-			cat4->src_neg, cat4->src_abs, cat4->src_rel);
+
+	if (cat4->c.src_c) {
+		print_reg_src((reg_t)(cat4->c.src), cat4->full,
+				cat4->src_r, cat4->c.src_c, cat4->src_im,
+				cat4->src_neg, cat4->src_abs, false);
+	} else if (cat4->rel.src_rel) {
+		print_reg_src((reg_t)(cat4->rel.src), cat4->full,
+				cat4->src_r, cat4->rel.src_c, cat4->src_im,
+				cat4->src_neg, cat4->src_abs, cat4->rel.src_rel);
+	} else {
+		print_reg_src((reg_t)(cat4->src), cat4->full,
+				cat4->src_r, false, cat4->src_im,
+				cat4->src_neg, cat4->src_abs, false);
+	}
 
 	if ((debug & PRINT_VERBOSE) && (cat4->dummy1|cat4->dummy2))
 		printf("\t{4: %x,%x}", cat4->dummy1, cat4->dummy2);
diff --git a/src/gallium/drivers/freedreno/a3xx/instr-a3xx.h b/src/gallium/drivers/freedreno/a3xx/instr-a3xx.h
index 464a7e9..1085ddf 100644
--- a/src/gallium/drivers/freedreno/a3xx/instr-a3xx.h
+++ b/src/gallium/drivers/freedreno/a3xx/instr-a3xx.h
@@ -232,13 +232,16 @@ typedef union PACKED {
 	/* normal gpr or const src register: */
 	struct PACKED {
 		uint32_t comp  : 2;
-		uint32_t num   : 9;
+		uint32_t num   : 10;
 	};
 	/* for immediate val: */
 	int32_t  iim_val   : 11;
 	/* to make compiler happy: */
 	uint32_t dummy32;
+	uint32_t dummy10   : 10;
 	uint32_t dummy11   : 11;
+	uint32_t dummy12   : 12;
+	uint32_t dummy13   : 13;
 	uint32_t dummy8    : 8;
 } reg_t;
 
@@ -276,12 +279,16 @@ typedef struct PACKED {
 		/* for normal src register: */
 		struct PACKED {
 			uint32_t src : 11;
+			/* at least low bit of pad must be zero or it will
+			 * look like a address relative src
+			 */
 			uint32_t pad : 21;
 		};
 		/* for address relative: */
 		struct PACKED {
 			int32_t  off : 10;
-			uint32_t must_be_3 : 2;
+			uint32_t src_rel_c : 1;
+			uint32_t src_rel : 1;
 			uint32_t unknown : 20;
 		};
 		/* for immediate: */
@@ -294,7 +301,7 @@ typedef struct PACKED {
 	uint32_t repeat     : 3;
 	uint32_t src_r      : 1;
 	uint32_t ss         : 1;
-	uint32_t src_rel    : 1;
+	uint32_t ul         : 1;
 	uint32_t dst_type   : 3;
 	uint32_t dst_rel    : 1;
 	uint32_t src_type   : 3;
@@ -310,19 +317,49 @@ typedef struct PACKED {
 
 typedef struct PACKED {
 	/* dword0: */
-	uint32_t src1     : 11;
-	uint32_t src1_rel : 1;   /* relative address */
-	uint32_t src1_c   : 1;   /* const */
-	uint32_t src1_im  : 1;   /* immediate */
-	uint32_t src1_neg : 1;   /* negate */
-	uint32_t src1_abs : 1;   /* absolute value */
-
-	uint32_t src2     : 11;
-	uint32_t src2_rel : 1;   /* relative address */
-	uint32_t src2_c   : 1;   /* const */
-	uint32_t src2_im  : 1;   /* immediate */
-	uint32_t src2_neg : 1;   /* negate */
-	uint32_t src2_abs : 1;   /* absolute value */
+	union PACKED {
+		struct PACKED {
+			uint32_t src1         : 11;
+			uint32_t must_be_zero1: 2;
+			uint32_t src1_im      : 1;   /* immediate */
+			uint32_t src1_neg     : 1;   /* negate */
+			uint32_t src1_abs     : 1;   /* absolute value */
+		};
+		struct PACKED {
+			uint32_t src1         : 10;
+			uint32_t src1_c       : 1;   /* relative-const */
+			uint32_t src1_rel     : 1;   /* relative address */
+			uint32_t must_be_zero : 1;
+			uint32_t dummy        : 3;
+		} rel1;
+		struct PACKED {
+			uint32_t src1         : 12;
+			uint32_t src1_c       : 1;   /* const */
+			uint32_t dummy        : 3;
+		} c1;
+	};
+
+	union PACKED {
+		struct PACKED {
+			uint32_t src2         : 11;
+			uint32_t must_be_zero2: 2;
+			uint32_t src2_im      : 1;   /* immediate */
+			uint32_t src2_neg     : 1;   /* negate */
+			uint32_t src2_abs     : 1;   /* absolute value */
+		};
+		struct PACKED {
+			uint32_t src2         : 10;
+			uint32_t src2_c       : 1;   /* relative-const */
+			uint32_t src2_rel     : 1;   /* relative address */
+			uint32_t must_be_zero : 1;
+			uint32_t dummy        : 3;
+		} rel2;
+		struct PACKED {
+			uint32_t src2         : 12;
+			uint32_t src2_c       : 1;   /* const */
+			uint32_t dummy        : 3;
+		} c2;
+	};
 
 	/* dword1: */
 	uint32_t dst      : 8;
@@ -343,18 +380,49 @@ typedef struct PACKED {
 
 typedef struct PACKED {
 	/* dword0: */
-	uint32_t src1     : 11;
-	uint32_t src1_rel : 1;
-	uint32_t src1_c   : 1;
-	uint32_t src2_c   : 1;
-	uint32_t src1_neg : 1;
-	uint32_t src2_r   : 1;
-	uint32_t src3     : 11;
-	uint32_t src3_rel : 1;
-	uint32_t src3_c   : 1;
-	uint32_t src3_r   : 1;
-	uint32_t src2_neg : 1;
-	uint32_t src3_neg : 1;
+	union PACKED {
+		struct PACKED {
+			uint32_t src1         : 11;
+			uint32_t must_be_zero1: 2;
+			uint32_t src2_c       : 1;
+			uint32_t src1_neg     : 1;
+			uint32_t src2_r       : 1;
+		};
+		struct PACKED {
+			uint32_t src1         : 10;
+			uint32_t src1_c       : 1;
+			uint32_t src1_rel     : 1;
+			uint32_t must_be_zero : 1;
+			uint32_t dummy        : 3;
+		} rel1;
+		struct PACKED {
+			uint32_t src1         : 12;
+			uint32_t src1_c       : 1;
+			uint32_t dummy        : 3;
+		} c1;
+	};
+
+	union PACKED {
+		struct PACKED {
+			uint32_t src3         : 11;
+			uint32_t must_be_zero2: 2;
+			uint32_t src3_r       : 1;
+			uint32_t src2_neg     : 1;
+			uint32_t src3_neg     : 1;
+		};
+		struct PACKED {
+			uint32_t src3         : 10;
+			uint32_t src3_c       : 1;
+			uint32_t src3_rel     : 1;
+			uint32_t must_be_zero : 1;
+			uint32_t dummy        : 3;
+		} rel2;
+		struct PACKED {
+			uint32_t src3         : 12;
+			uint32_t src3_c       : 1;
+			uint32_t dummy        : 3;
+		} c2;
+	};
 
 	/* dword1: */
 	uint32_t dst      : 8;
@@ -372,12 +440,27 @@ typedef struct PACKED {
 
 typedef struct PACKED {
 	/* dword0: */
-	uint32_t src      : 11;
-	uint32_t src_rel  : 1;
-	uint32_t src_c    : 1;
-	uint32_t src_im   : 1;
-	uint32_t src_neg  : 1;
-	uint32_t src_abs  : 1;
+	union PACKED {
+		struct PACKED {
+			uint32_t src          : 11;
+			uint32_t must_be_zero1: 2;
+			uint32_t src_im       : 1;   /* immediate */
+			uint32_t src_neg      : 1;   /* negate */
+			uint32_t src_abs      : 1;   /* absolute value */
+		};
+		struct PACKED {
+			uint32_t src          : 10;
+			uint32_t src_c        : 1;   /* relative-const */
+			uint32_t src_rel      : 1;   /* relative address */
+			uint32_t must_be_zero : 1;
+			uint32_t dummy        : 3;
+		} rel;
+		struct PACKED {
+			uint32_t src          : 12;
+			uint32_t src_c        : 1;   /* const */
+			uint32_t dummy        : 3;
+		} c;
+	};
 	uint32_t dummy1   : 16;  /* seem to be ignored */
 
 	/* dword1: */
diff --git a/src/gallium/drivers/freedreno/a3xx/ir-a3xx.c b/src/gallium/drivers/freedreno/a3xx/ir-a3xx.c
index 76e8b11..238ce34 100644
--- a/src/gallium/drivers/freedreno/a3xx/ir-a3xx.c
+++ b/src/gallium/drivers/freedreno/a3xx/ir-a3xx.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Rob Clark <robdclark at gmail.com>
+ * Copyright (c) 2012 Rob Clark <robdclark at gmail.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -132,11 +132,12 @@ static int emit_cat1(struct ir3_instruction *instr, void *ptr,
 	} else if (src->flags & IR3_REG_RELATIV) {
 		cat1->off       = src->offset;
 		cat1->src_rel   = 1;
-		cat1->must_be_3 = 3;
+		cat1->src_rel_c = !!(src->flags & IR3_REG_CONST);
 	} else {
 		cat1->src  = reg(src, info, instr->repeat,
-				IR3_REG_IMMED | IR3_REG_RELATIV |
-				IR3_REG_R | IR3_REG_CONST | IR3_REG_HALF);
+				IR3_REG_IMMED | IR3_REG_R |
+				IR3_REG_CONST | IR3_REG_HALF);
+		cat1->src_c     = !!(src->flags & IR3_REG_CONST);
 	}
 
 	cat1->dst      = reg(dst, info, instr->repeat,
@@ -145,10 +146,10 @@ static int emit_cat1(struct ir3_instruction *instr, void *ptr,
 	cat1->repeat   = instr->repeat;
 	cat1->src_r    = !!(src->flags & IR3_REG_R);
 	cat1->ss       = !!(instr->flags & IR3_INSTR_SS);
+	cat1->ul       = !!(instr->flags & IR3_INSTR_UL);
 	cat1->dst_type = instr->cat1.dst_type;
 	cat1->dst_rel  = !!(dst->flags & IR3_REG_RELATIV);
 	cat1->src_type = instr->cat1.src_type;
-	cat1->src_c    = !!(src->flags & IR3_REG_CONST);
 	cat1->even     = !!(dst->flags & IR3_REG_EVEN);
 	cat1->pos_inf  = !!(dst->flags & IR3_REG_POS_INF);
 	cat1->jmp_tgt  = !!(instr->flags & IR3_INSTR_JP);
@@ -168,11 +169,25 @@ static int emit_cat2(struct ir3_instruction *instr, void *ptr,
 
 	iassert((instr->regs_count == 2) || (instr->regs_count == 3));
 
-	cat2->src1     = reg(src1, info, instr->repeat,
-			IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_IMMED |
-			IR3_REG_NEGATE | IR3_REG_ABS | IR3_REG_R | IR3_REG_HALF);
-	cat2->src1_rel = !!(src1->flags & IR3_REG_RELATIV);
-	cat2->src1_c   = !!(src1->flags & IR3_REG_CONST);
+	if (src1->flags & IR3_REG_RELATIV) {
+		iassert(src1->num < (1 << 10));
+		cat2->rel1.src1      = reg(src1, info, instr->repeat,
+				IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_NEGATE |
+				IR3_REG_ABS | IR3_REG_R | IR3_REG_HALF);
+		cat2->rel1.src1_c    = !!(src1->flags & IR3_REG_CONST);
+		cat2->rel1.src1_rel  = 1;
+	} else if (src1->flags & IR3_REG_CONST) {
+		iassert(src1->num < (1 << 12));
+		cat2->c1.src1   = reg(src1, info, instr->repeat,
+				IR3_REG_CONST | IR3_REG_NEGATE | IR3_REG_ABS |
+				IR3_REG_R | IR3_REG_HALF);
+		cat2->c1.src1_c = 1;
+	} else {
+		iassert(src1->num < (1 << 11));
+		cat2->src1 = reg(src1, info, instr->repeat,
+				IR3_REG_IMMED | IR3_REG_NEGATE | IR3_REG_ABS |
+				IR3_REG_R | IR3_REG_HALF);
+	}
 	cat2->src1_im  = !!(src1->flags & IR3_REG_IMMED);
 	cat2->src1_neg = !!(src1->flags & IR3_REG_NEGATE);
 	cat2->src1_abs = !!(src1->flags & IR3_REG_ABS);
@@ -181,11 +196,27 @@ static int emit_cat2(struct ir3_instruction *instr, void *ptr,
 	if (src2) {
 		iassert((src2->flags & IR3_REG_IMMED) ||
 				!((src1->flags ^ src2->flags) & IR3_REG_HALF));
-		cat2->src2     = reg(src2, info, instr->repeat,
-				IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_IMMED |
-				IR3_REG_NEGATE | IR3_REG_ABS | IR3_REG_R | IR3_REG_HALF);
-		cat2->src2_rel = !!(src2->flags & IR3_REG_RELATIV);
-		cat2->src2_c   = !!(src2->flags & IR3_REG_CONST);
+
+		if (src2->flags & IR3_REG_RELATIV) {
+			iassert(src2->num < (1 << 10));
+			cat2->rel2.src2      = reg(src2, info, instr->repeat,
+					IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_NEGATE |
+					IR3_REG_ABS | IR3_REG_R | IR3_REG_HALF);
+			cat2->rel2.src2_c    = !!(src2->flags & IR3_REG_CONST);
+			cat2->rel2.src2_rel  = 1;
+		} else if (src2->flags & IR3_REG_CONST) {
+			iassert(src2->num < (1 << 12));
+			cat2->c2.src2   = reg(src2, info, instr->repeat,
+					IR3_REG_CONST | IR3_REG_NEGATE | IR3_REG_ABS |
+					IR3_REG_R | IR3_REG_HALF);
+			cat2->c2.src2_c = 1;
+		} else {
+			iassert(src2->num < (1 << 11));
+			cat2->src2 = reg(src2, info, instr->repeat,
+					IR3_REG_IMMED | IR3_REG_NEGATE | IR3_REG_ABS |
+					IR3_REG_R | IR3_REG_HALF);
+		}
+
 		cat2->src2_im  = !!(src2->flags & IR3_REG_IMMED);
 		cat2->src2_neg = !!(src2->flags & IR3_REG_NEGATE);
 		cat2->src2_abs = !!(src2->flags & IR3_REG_ABS);
@@ -239,11 +270,25 @@ static int emit_cat3(struct ir3_instruction *instr, void *ptr,
 	iassert(!((src2->flags ^ src_flags) & IR3_REG_HALF));
 	iassert(!((src3->flags ^ src_flags) & IR3_REG_HALF));
 
-	cat3->src1     = reg(src1, info, instr->repeat,
-			IR3_REG_RELATIV | IR3_REG_CONST |
-			IR3_REG_NEGATE | IR3_REG_R | IR3_REG_HALF);
-	cat3->src1_rel = !!(src1->flags & IR3_REG_RELATIV);
-	cat3->src1_c   = !!(src1->flags & IR3_REG_CONST);
+	if (src1->flags & IR3_REG_RELATIV) {
+		iassert(src1->num < (1 << 10));
+		cat3->rel1.src1      = reg(src1, info, instr->repeat,
+				IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_NEGATE |
+				IR3_REG_R | IR3_REG_HALF);
+		cat3->rel1.src1_c    = !!(src1->flags & IR3_REG_CONST);
+		cat3->rel1.src1_rel  = 1;
+	} else if (src1->flags & IR3_REG_CONST) {
+		iassert(src1->num < (1 << 12));
+		cat3->c1.src1   = reg(src1, info, instr->repeat,
+				IR3_REG_CONST | IR3_REG_NEGATE | IR3_REG_R |
+				IR3_REG_HALF);
+		cat3->c1.src1_c = 1;
+	} else {
+		iassert(src1->num < (1 << 11));
+		cat3->src1 = reg(src1, info, instr->repeat,
+				IR3_REG_NEGATE | IR3_REG_R | IR3_REG_HALF);
+	}
+
 	cat3->src1_neg = !!(src1->flags & IR3_REG_NEGATE);
 	cat3->src1_r   = !!(src1->flags & IR3_REG_R);
 
@@ -254,11 +299,26 @@ static int emit_cat3(struct ir3_instruction *instr, void *ptr,
 	cat3->src2_neg = !!(src2->flags & IR3_REG_NEGATE);
 	cat3->src2_r   = !!(src2->flags & IR3_REG_R);
 
-	cat3->src3     = reg(src3, info, instr->repeat,
-			IR3_REG_RELATIV | IR3_REG_CONST |
-			IR3_REG_NEGATE | IR3_REG_R | IR3_REG_HALF);
-	cat3->src3_rel = !!(src3->flags & IR3_REG_RELATIV);
-	cat3->src3_c   = !!(src3->flags & IR3_REG_CONST);
+
+	if (src3->flags & IR3_REG_RELATIV) {
+		iassert(src3->num < (1 << 10));
+		cat3->rel2.src3      = reg(src3, info, instr->repeat,
+				IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_NEGATE |
+				IR3_REG_R | IR3_REG_HALF);
+		cat3->rel2.src3_c    = !!(src3->flags & IR3_REG_CONST);
+		cat3->rel2.src3_rel  = 1;
+	} else if (src3->flags & IR3_REG_CONST) {
+		iassert(src3->num < (1 << 12));
+		cat3->c2.src3   = reg(src3, info, instr->repeat,
+				IR3_REG_CONST | IR3_REG_NEGATE | IR3_REG_R |
+				IR3_REG_HALF);
+		cat3->c2.src3_c = 1;
+	} else {
+		iassert(src3->num < (1 << 11));
+		cat3->src3 = reg(src3, info, instr->repeat,
+				IR3_REG_NEGATE | IR3_REG_R | IR3_REG_HALF);
+	}
+
 	cat3->src3_neg = !!(src3->flags & IR3_REG_NEGATE);
 	cat3->src3_r   = !!(src3->flags & IR3_REG_R);
 
@@ -284,12 +344,26 @@ static int emit_cat4(struct ir3_instruction *instr, void *ptr,
 
 	iassert(instr->regs_count == 2);
 
-	cat4->src      = reg(src, info, instr->repeat,
-			IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_IMMED |
-			IR3_REG_NEGATE | IR3_REG_ABS | IR3_REG_R |
-			IR3_REG_HALF);
-	cat4->src_rel  = !!(src->flags & IR3_REG_RELATIV);
-	cat4->src_c    = !!(src->flags & IR3_REG_CONST);
+	if (src->flags & IR3_REG_RELATIV) {
+		iassert(src->num < (1 << 10));
+		cat4->rel.src      = reg(src, info, instr->repeat,
+				IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_NEGATE |
+				IR3_REG_ABS | IR3_REG_R | IR3_REG_HALF);
+		cat4->rel.src_c    = !!(src->flags & IR3_REG_CONST);
+		cat4->rel.src_rel  = 1;
+	} else if (src->flags & IR3_REG_CONST) {
+		iassert(src->num < (1 << 12));
+		cat4->c.src   = reg(src, info, instr->repeat,
+				IR3_REG_CONST | IR3_REG_NEGATE | IR3_REG_ABS |
+				IR3_REG_R | IR3_REG_HALF);
+		cat4->c.src_c = 1;
+	} else {
+		iassert(src->num < (1 << 11));
+		cat4->src = reg(src, info, instr->repeat,
+				IR3_REG_IMMED | IR3_REG_NEGATE | IR3_REG_ABS |
+				IR3_REG_R | IR3_REG_HALF);
+	}
+
 	cat4->src_im   = !!(src->flags & IR3_REG_IMMED);
 	cat4->src_neg  = !!(src->flags & IR3_REG_NEGATE);
 	cat4->src_abs  = !!(src->flags & IR3_REG_ABS);
diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c
index a038a77..2be242a 100644
--- a/src/gallium/drivers/freedreno/freedreno_screen.c
+++ b/src/gallium/drivers/freedreno/freedreno_screen.c
@@ -267,6 +267,8 @@ static int
 fd_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader,
 		enum pipe_shader_cap param)
 {
+	struct fd_screen *screen = fd_screen(pscreen);
+
 	switch(shader)
 	{
 	case PIPE_SHADER_FRAGMENT:
@@ -293,13 +295,13 @@ fd_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader,
 	case PIPE_SHADER_CAP_MAX_INPUTS:
 		return 32;
 	case PIPE_SHADER_CAP_MAX_TEMPS:
-		return 256; /* Max native temporaries. */
+		return 64; /* Max native temporaries. */
 	case PIPE_SHADER_CAP_MAX_ADDRS:
-		/* XXX Isn't this equal to TEMPS? */
 		return 1; /* Max native address registers */
 	case PIPE_SHADER_CAP_MAX_CONSTS:
+		return (screen->gpu_id >= 300) ? 1024 : 64;
 	case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
-		return 64;
+		return 1;
 	case PIPE_SHADER_CAP_MAX_PREDS:
 		return 0; /* nothing uses this */
 	case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:




More information about the mesa-commit mailing list