ir3/isa: add encoding for scalar predicates

Predicate registers can be written from the scalar ALU by using a
special cat2 encoding: if the dst is encoded as a0.c, the instruction
will execute on the scalar ALU and write to p0.c.

This commit follows the blob and disassembles scalar predicates as
up0.c. The "u" presumably stands for "uniform".

Signed-off-by: Job Noorman <jnoorman@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36614>
This commit is contained in:
Job Noorman 2025-08-19 08:35:37 +02:00 committed by Marge Bot
parent 25ab37ae5b
commit 0223ab01b7
5 changed files with 51 additions and 1 deletions

View file

@ -95,6 +95,9 @@ static int parse_reg(const char *str)
str++;
num++;
}
if (str[0] == 'u') {
str++;
}
str++;
if (str[0] == 't') {
str++;
@ -178,6 +181,7 @@ static int parse_reg(const char *str)
"a0.x" return T_A0;
"a1.x" return T_A1;
"p0."[xyzw] ir3_yylval.num = parse_reg(yytext); return T_P0;
"up0."[xyzw] ir3_yylval.num = parse_reg(yytext); return T_UP0;
"w"[0-9]+ ir3_yylval.num = strtol(yytext+1, NULL, 10); return T_W;
"s#"[0-9]+ ir3_yylval.num = strtol(yytext+2, NULL, 10); return T_SAMP;
"t#"[0-9]+ ir3_yylval.num = strtol(yytext+2, NULL, 10); return T_TEX;

View file

@ -773,6 +773,7 @@ static void print_token(FILE *file, int type, YYSTYPE value)
%token <num> T_A0
%token <num> T_A1
%token <num> T_P0
%token <num> T_UP0
%token <num> T_W
%token <str> T_CAT1_TYPE_TYPE
@ -1613,6 +1614,7 @@ dst: T_REGISTER { $$ = new_dst($1, 0); }
| T_A0 { $$ = new_dst((61 << 3), IR3_REG_HALF); }
| T_A1 { $$ = new_dst((61 << 3) + 1, IR3_REG_HALF); }
| T_P0 { $$ = new_dst((62 << 3) + $1, IR3_REG_PREDICATE); }
| T_UP0 { $$ = new_dst((62 << 3) + $1, IR3_REG_PREDICATE | IR3_REG_UNIFORM); }
const: T_CONSTANT { $$ = new_src($1, IR3_REG_CONST); }

View file

@ -117,6 +117,8 @@ static const struct test {
INSTR_7XX(42380800_04010400, "(nop3) add.s r0.x, (last)r0.x, (last)r0.y"),
INSTR_7XX(42930000_04000406, "cmps.u.ge r0.x, (last)r1.z, (last)r0.x"),
INSTR_7XX(429000f5_100600c1, "cmps.u.lt up0.y, r48.y, c1.z"),
/* cat3 */
INSTR_6XX(66000000_10421041, "sel.f16 hr0.x, hc16.y, hr0.x, hc16.z"),
INSTR_6XX(64848109_109a9099, "(rpt1)sel.b32 r2.y, c38.y, (r)r2.y, c38.z"),

View file

@ -130,6 +130,18 @@ extract_reg_uim(const struct ir3_register *reg)
return reg->uim_val;
}
static inline uint32_t
extract_dst_num(const struct ir3_register *reg)
{
if (reg->flags & IR3_REG_UNIFORM) {
assert(reg->flags & IR3_REG_PREDICATE);
assert(reg_num(reg) == REG_P0);
return REG_A0;
}
return reg_num(reg);
}
/**
* This is a bit messy, to deal with the fact that the optional "s2en"
* src is the first src, shifting everything else up by one.

View file

@ -28,8 +28,38 @@ SOFTWARE.
Cat2 Instructions: one and two src ALU instructions
-->
<bitset name="#dst-gpr-cat2" size="8">
<override expr="#reg-gpr-a0">
<doc>
Predicate registers can be written from the scalar
ALU by using a special cat2 encoding: if the dst is
encoded as a0.c, the instruction will execute on the
scalar ALU and write to p0.c.
</doc>
<display>
up0.{SWIZ}
</display>
<assert low="2" high="7">111101</assert>
</override>
<override expr="#reg-gpr-p0">
<display>
p0.{SWIZ}
</display>
<assert low="2" high="7">111110</assert>
</override>
<display>
r{GPR}.{SWIZ}
</display>
<field name="SWIZ" low="0" high="1" type="#swiz"/>
<field name="GPR" low="2" high="7" type="uint"/>
<encode type="struct ir3_register *">
<map name="GPR">extract_dst_num(src)</map>
<map name="SWIZ">src->num &amp; 0x3</map>
</encode>
</bitset>
<bitset name="#instruction-cat2" extends="#instruction">
<field name="DST" low="32" high="39" type="#reg-gpr"/>
<field name="DST" low="32" high="39" type="#dst-gpr-cat2"/>
<field name="REPEAT" low="40" high="41" type="#rptN"/>
<field name="SAT" pos="42" type="bool" display="(sat)"/>
<field name="SS" pos="44" type="bool" display="(ss)"/>