diff --git a/src/freedreno/ir3/disasm-a3xx.c b/src/freedreno/ir3/disasm-a3xx.c index 6c80e37ea70..8d684a6608d 100644 --- a/src/freedreno/ir3/disasm-a3xx.c +++ b/src/freedreno/ir3/disasm-a3xx.c @@ -185,6 +185,7 @@ static const struct opc_info { OPC(1, OPC_SWZ, swz), OPC(1, OPC_SCT, sct), OPC(1, OPC_GAT, gat), + OPC(1, OPC_MOVS, movs), OPC(1, OPC_BALLOT_MACRO, ballot.macro), OPC(1, OPC_ANY_MACRO, any.macro), OPC(1, OPC_ALL_MACRO, all.macro), diff --git a/src/freedreno/ir3/instr-a3xx.h b/src/freedreno/ir3/instr-a3xx.h index 5807c817bab..d387113a74d 100644 --- a/src/freedreno/ir3/instr-a3xx.h +++ b/src/freedreno/ir3/instr-a3xx.h @@ -82,6 +82,7 @@ typedef enum { /* category 1: */ OPC_MOV = _OPC(1, 0), OPC_MOVP = _OPC(1, 1), + OPC_MOVS = _OPC(1, 2), /* swz, gat, sct */ OPC_MOVMSK = _OPC(1, 3), @@ -98,6 +99,8 @@ typedef enum { OPC_MOV_GPR = _OPC(1, 42), OPC_MOV_RELGPR = _OPC(1, 43), OPC_MOV_RELCONST = _OPC(1, 44), + OPC_MOVS_IMMED = _OPC(1, 45), + OPC_MOVS_A0 = _OPC(1, 46), /* Macros that expand to an if statement + move */ OPC_BALLOT_MACRO = _OPC(1, 50), diff --git a/src/freedreno/ir3/ir3_lexer.l b/src/freedreno/ir3/ir3_lexer.l index 6c1916aafb2..c4a064d03f0 100644 --- a/src/freedreno/ir3/ir3_lexer.l +++ b/src/freedreno/ir3/ir3_lexer.l @@ -223,6 +223,7 @@ static int parse_reg(const char *str) "swz" return TOKEN(T_OP_SWZ); "gat" return TOKEN(T_OP_GAT); "sct" return TOKEN(T_OP_SCT); +"movs" return TOKEN(T_OP_MOVS); ("f16"|"f32"|"u16"|"u32"|"s16"|"s32"|"u8"|"u8_32"|"u64"){2} ir3_yylval.str = yytext; return T_CAT1_TYPE_TYPE; /* category 2: */ diff --git a/src/freedreno/ir3/ir3_parser.y b/src/freedreno/ir3/ir3_parser.y index e215ec2dd6f..95f2b0baf94 100644 --- a/src/freedreno/ir3/ir3_parser.y +++ b/src/freedreno/ir3/ir3_parser.y @@ -502,6 +502,7 @@ static void print_token(FILE *file, int type, YYSTYPE value) %token T_OP_SWZ %token T_OP_GAT %token T_OP_SCT +%token T_OP_MOVS /* category 2: */ %token T_OP_ADD_F @@ -1040,6 +1041,11 @@ cat1_gat: T_OP_GAT '.' T_CAT1_TYPE_TYPE { parse_type_type(new_instr(OPC cat1_sct: T_OP_SCT '.' T_CAT1_TYPE_TYPE { parse_type_type(new_instr(OPC_SCT), $3); } dst_reg ',' dst_reg ',' dst_reg ',' dst_reg ',' src_reg +movs_invocation: uinteger { new_src(0, IR3_REG_IMMED)->uim_val = $1; } +| src_a0 + +cat1_movs: T_OP_MOVS '.' T_CAT1_TYPE_TYPE { parse_type_type(new_instr(OPC_MOVS), $3); } dst_reg ',' src_reg ',' movs_invocation + /* NOTE: cat1 can also *write* to relative gpr */ cat1_instr: cat1_movmsk | cat1_mova1 @@ -1049,6 +1055,7 @@ cat1_instr: cat1_movmsk | cat1_sct | cat1_opc dst_reg ',' cat1_src | cat1_opc relative_gpr_dst ',' cat1_src +| cat1_movs cat2_opc_1src: T_OP_ABSNEG_F { new_instr(OPC_ABSNEG_F); } | T_OP_ABSNEG_S { new_instr(OPC_ABSNEG_S); } diff --git a/src/freedreno/ir3/tests/disasm.c b/src/freedreno/ir3/tests/disasm.c index 1c18dfecea2..a37bd187b34 100644 --- a/src/freedreno/ir3/tests/disasm.c +++ b/src/freedreno/ir3/tests/disasm.c @@ -93,6 +93,9 @@ static const struct test { INSTR_7XX(2004c005_00000405, "cov.f32u32 r1.y, (last)r1.y"), + INSTR_7XX(200440c0_ae800004, "movs.f32f32 r48.x, r1.x, 93"), + INSTR_7XX(201100c0_c000040b, "movs.s16s16 hr48.x, (last)hr2.w, a0.x"), + /* cat2 */ INSTR_6XX(40104002_0c210001, "add.f hr0.z, r0.y, c"), INSTR_6XX(40b80804_10408004, "(nop3) cmps.f.lt r1.x, (abs)r1.x, c16.x"), diff --git a/src/freedreno/isa/encode.c b/src/freedreno/isa/encode.c index bf227e2c36c..1b1876b6e2f 100644 --- a/src/freedreno/isa/encode.c +++ b/src/freedreno/isa/encode.c @@ -79,6 +79,12 @@ __instruction_case(struct encode_state *s, const struct ir3_instruction *instr) } else { return OPC_MOV_GPR; } + } else if (instr->opc == OPC_MOVS) { + if (instr->srcs[1]->flags & IR3_REG_IMMED) { + return OPC_MOVS_IMMED; + } else { + return OPC_MOVS_A0; + } } else if (instr->opc == OPC_DEMOTE) { return OPC_KILL; } else if (s->compiler->gen >= 6) { diff --git a/src/freedreno/isa/ir3-cat1.xml b/src/freedreno/isa/ir3-cat1.xml index 15bd97f9514..a120515aed8 100644 --- a/src/freedreno/isa/ir3-cat1.xml +++ b/src/freedreno/isa/ir3-cat1.xml @@ -277,7 +277,7 @@ SOFTWARE. 01 - + @@ -285,7 +285,6 @@ SOFTWARE. 00 - 000000000000000000000 00 @@ -293,6 +292,50 @@ SOFTWARE. + + 000000000000000000000 + + + + + movs works like subgroupBroadcast/OpGroupNonUniformBroadcast. + The fiber id can either be an immediate or a value in a0.x. In + the latter case, the value has to be dynamically uniform or else + the behavior is undefined. The dst register has to be shared or + else the behavior seems to be equivalent to a normal mov (i.e., + the fiber id is not taken into account anymore). + + movs can do a cov on the broadcasted value. It works exactly + like a normal cov except that using u8 as the src type does not + seem to work at all. + + + 000000000000 + 1 + + + + + {SY}{SS}{JP}{REPEAT}{UL}movs.{SRC_TYPE}{DST_TYPE} {ROUND}{DST_HALF}{DST}, {SRC}, {INVOCATION} + + + + 0 + + + extract_reg_uim(src->srcs[1]) + + + + + + {SY}{SS}{JP}{REPEAT}{UL}movs.{SRC_TYPE}{DST_TYPE} {ROUND}{DST_HALF}{DST}, {SRC}, a0.x + + + 0000000 + 1 + + 1 00000000000000000000