diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h
index a2a9f774d3e..a82e0eabea7 100644
--- a/src/freedreno/ir3/ir3.h
+++ b/src/freedreno/ir3/ir3.h
@@ -1738,6 +1738,41 @@ unsigned ir3_cat2_absneg(opc_t opc);
unsigned ir3_cat3_absneg(struct ir3_compiler *compiler, opc_t opc,
unsigned src_n);
+static inline bool
+ir3_cat3_int(opc_t opc)
+{
+ switch (opc) {
+ case OPC_MAD_F16:
+ case OPC_MAD_F32:
+ case OPC_SEL_F16:
+ case OPC_SEL_F32:
+ return false;
+ case OPC_MAD_U16:
+ case OPC_MADSH_U16:
+ case OPC_MAD_S16:
+ case OPC_MADSH_M16:
+ case OPC_MAD_U24:
+ case OPC_MAD_S24:
+ case OPC_SEL_B16:
+ case OPC_SEL_B32:
+ case OPC_SEL_S16:
+ case OPC_SEL_S32:
+ case OPC_SAD_S16:
+ case OPC_SAD_S32:
+ case OPC_SHRM:
+ case OPC_SHLM:
+ case OPC_SHRG:
+ case OPC_SHLG:
+ case OPC_ANDG:
+ case OPC_DP2ACC:
+ case OPC_DP4ACC:
+ case OPC_WMM:
+ case OPC_WMM_ACCU:
+ default:
+ return true;
+ }
+}
+
/* Return the type (float, int, or uint) the op uses when converting from the
* internal result of the op (which is assumed to be the same size as the
* sources) to the destination when they are not the same size. If F32 it does
diff --git a/src/freedreno/ir3/ir3_parser.y b/src/freedreno/ir3/ir3_parser.y
index ad9592274b5..ce87dd489dd 100644
--- a/src/freedreno/ir3/ir3_parser.y
+++ b/src/freedreno/ir3/ir3_parser.y
@@ -839,7 +839,11 @@ cat3_wmm: T_OP_WMM { new_instr(OPC_WMM); }
cat3_dp: T_OP_DP2ACC { new_instr(OPC_DP2ACC); }
| T_OP_DP4ACC { new_instr(OPC_DP4ACC); }
-cat3_instr: cat3_opc dst_reg ',' src_reg_or_const_or_rel ',' src_reg_or_const ',' src_reg_or_const_or_rel
+src_reg_or_const_or_rel_or_flut: src_reg_or_const_or_rel
+| flut_immed { new_src(0, IR3_REG_IMMED)->uim_val = $1; }
+| 'h' flut_immed { new_src(0, IR3_REG_IMMED | IR3_REG_HALF)->uim_val = $2; }
+
+cat3_instr: cat3_opc dst_reg ',' src_reg_or_const_or_rel_or_flut ',' src_reg_or_const ',' src_reg_or_const_or_rel_or_flut
| cat3_reg_or_const_or_rel_opc dst_reg ',' src_reg_or_const_or_rel_or_imm ',' src_reg_or_const ',' src_reg_or_const_or_rel_or_imm
| cat3_imm_reg_opc dst_reg ',' src_reg_or_rel_or_imm ',' src_reg_or_const ',' src_reg_or_rel_or_imm
| cat3_wmm dst_reg ',' src_reg_gpr ',' src_reg ',' immediate
diff --git a/src/freedreno/ir3/tests/disasm.c b/src/freedreno/ir3/tests/disasm.c
index d539a66396a..bdd28a2fedb 100644
--- a/src/freedreno/ir3/tests/disasm.c
+++ b/src/freedreno/ir3/tests/disasm.c
@@ -154,6 +154,7 @@ static const struct test {
INSTR_7XX(64838806_04088406, "(nop3) sel.b32 r1.z, (last)r1.z, r1.w, (last)r2.x"),
INSTR_8XX(6206000a_040a0610, "mad.u24 r2.z, 16, r3.x, (last)r2.z"),
INSTR_8XX(62000800_06030402, "(nop1) mad.u24 r0.x, (last)r0.z, r0.x, 3"),
+ INSTR_8XX(63820009_07024409, "mad.f32 r2.y, (neg)(last)r2.y, r1.x, (1.0)"),
/* cat4 */
INSTR_6XX(8010000a_00000003, "rcp r2.z, r0.w"),
diff --git a/src/freedreno/isa/encode.c b/src/freedreno/isa/encode.c
index 224e912d69f..7f975c84cd9 100644
--- a/src/freedreno/isa/encode.c
+++ b/src/freedreno/isa/encode.c
@@ -271,6 +271,7 @@ __multisrc_case(struct encode_state *s, const struct ir3_register *reg)
typedef enum {
REG_CAT3_SRC_GPR,
REG_CAT3_SRC_ALT_IMMED,
+ REG_CAT3_SRC_FLUT,
REG_CAT3_SRC_CONST_OR_IMMED,
REG_CAT3_SRC_RELATIVE_GPR,
REG_CAT3_SRC_RELATIVE_CONST,
@@ -286,18 +287,23 @@ __cat3_src_case(struct encode_state *s, const struct ir3_register *reg)
return REG_CAT3_SRC_RELATIVE_GPR;
}
} else if (reg->flags & IR3_REG_IMMED) {
- switch (s->instr->opc) {
- case OPC_SHRM:
- case OPC_SHLM:
- case OPC_SHRG:
- case OPC_SHLG:
- case OPC_ANDG:
- case OPC_WMM:
- case OPC_WMM_ACCU:
- return REG_CAT3_SRC_CONST_OR_IMMED;
- default:
+ if (ir3_cat3_int(s->instr->opc)) {
+ switch (s->instr->opc) {
+ case OPC_SHRM:
+ case OPC_SHLM:
+ case OPC_SHRG:
+ case OPC_SHLG:
+ case OPC_ANDG:
+ case OPC_WMM:
+ case OPC_WMM_ACCU:
+ return REG_CAT3_SRC_CONST_OR_IMMED;
+ default:
+ assert(s->gen >= 800);
+ return REG_CAT3_SRC_ALT_IMMED;
+ }
+ } else {
assert(s->gen >= 800);
- return REG_CAT3_SRC_ALT_IMMED;
+ return REG_CAT3_SRC_FLUT;
}
} else if (reg->flags & IR3_REG_CONST) {
return REG_CAT3_SRC_CONST_OR_IMMED;
diff --git a/src/freedreno/isa/ir3-cat3.xml b/src/freedreno/isa/ir3-cat3.xml
index 8b8b75b4332..9834a99c7d7 100644
--- a/src/freedreno/isa/ir3-cat3.xml
+++ b/src/freedreno/isa/ir3-cat3.xml
@@ -52,6 +52,20 @@ SOFTWARE.
+
+
+
+ {HALF}{IMMED}
+
+ 00111
+
+ 000
+
+
+
+
+
+