printf("r%u", reg);
}
-static char *outmod_names[4] = {
+static char *outmod_names_float[4] = {
"",
".pos",
- ".int",
+ ".unk2",
".sat"
};
+static char *outmod_names_int[4] = {
+ ".isat",
+ ".usat",
+ "",
+ ".unk3"
+};
+
static void
-print_outmod(midgard_outmod outmod)
+print_outmod(unsigned outmod, bool is_int)
{
- printf("%s", outmod_names[outmod]);
+ printf("%s", is_int ? outmod_names_int[outmod] :
+ outmod_names_float[outmod]);
}
static void
printf("%s.", name);
print_alu_opcode(alu_field->op);
- print_outmod(alu_field->outmod);
+ print_outmod(alu_field->outmod,
+ midgard_is_integer_out_op(alu_field->op));
printf(" ");
bool out_high = false;
printf("%s.", name);
print_alu_opcode(alu_field->op);
- print_outmod(alu_field->outmod);
+ print_outmod(alu_field->outmod,
+ midgard_is_integer_out_op(alu_field->op));
printf(" ");
if (alu_field->output_full)
.unit = for_branch ? UNIT_SMUL : UNIT_SADD,
.ssa_args = {
-
.src0 = condition,
.src1 = condition,
.dest = SSA_FIXED_REGISTER(31),
},
+
.alu = {
.op = midgard_alu_op_iand,
- .outmod = midgard_outmod_int,
+ .outmod = midgard_outmod_int_wrap,
.reg_mode = midgard_reg_mode_32,
.dest_override = midgard_dest_override_none,
.mask = (0x3 << 6), /* w */
},
.alu = {
.op = midgard_alu_op_iand,
- .outmod = midgard_outmod_int,
+ .outmod = midgard_outmod_int_wrap,
.reg_mode = midgard_reg_mode_32,
.dest_override = midgard_dest_override_none,
.mask = expand_writemask((1 << nr_comp) - 1),
},
.alu = {
.op = midgard_alu_op_imov,
- .outmod = midgard_outmod_int,
+ .outmod = midgard_outmod_int_wrap,
.reg_mode = midgard_reg_mode_32,
.dest_override = midgard_dest_override_none,
.mask = (0x3 << 6), /* w */
}
/* Midgard can perform certain modifiers on output of an ALU op */
- midgard_outmod outmod =
- midgard_is_integer_out_op(op) ? midgard_outmod_int :
- instr->dest.saturate ? midgard_outmod_sat : midgard_outmod_none;
+ unsigned outmod;
- if (instr->op == nir_op_fsat)
- outmod = midgard_outmod_sat;
+ if (midgard_is_integer_out_op(op)) {
+ outmod = midgard_outmod_int_wrap;
+ } else {
+ bool sat = instr->dest.saturate || instr->op == nir_op_fsat;
+ outmod = sat ? midgard_outmod_sat : midgard_outmod_none;
+ }
/* fmax(a, 0.0) can turn into a .pos modifier as an optimization */
return mir_nontrivial_mod(src2, is_int, mask);
}
+static bool
+mir_nontrivial_outmod(midgard_instruction *ins)
+{
+ bool is_int = midgard_is_integer_op(ins->alu.op);
+ unsigned mod = ins->alu.outmod;
+
+ if (is_int)
+ return mod != midgard_outmod_int_wrap;
+ else
+ return mod != midgard_outmod_none;
+}
+
static bool
midgard_opt_copy_prop(compiler_context *ctx, midgard_block *block)
{
if (ins->has_constants) continue;
if (mir_nontrivial_source2_mod(ins)) continue;
- if (ins->alu.outmod != midgard_outmod_none) continue;
+ if (mir_nontrivial_outmod(ins)) continue;
/* We're clear -- rewrite */
mir_rewrite_index_src(ctx, to, from);
* the move can be propagated away entirely */
static bool
-mir_compose_outmod(midgard_outmod *outmod, midgard_outmod comp)
+mir_compose_float_outmod(midgard_outmod_float *outmod, midgard_outmod_float comp)
{
/* Nothing to do */
if (comp == midgard_outmod_none)
/* TODO: Registers? */
unsigned src = ins->ssa_args.src1;
if (src >= ctx->func->impl->ssa_alloc) continue;
+ assert(!mir_has_multiple_writes(ctx, src));
/* There might be a source modifier, too */
if (mir_nontrivial_source2_mod(ins)) continue;
if (v->type != TAG_ALU_4) continue;
if (v->ssa_args.dest != src) continue;
- midgard_outmod temp = v->alu.outmod;
- progress |= mir_compose_outmod(&temp, ins->alu.outmod);
+ /* Can we even take a float outmod? */
+ if (midgard_is_integer_out_op(v->alu.op)) continue;
+
+ midgard_outmod_float temp = v->alu.outmod;
+ progress |= mir_compose_float_outmod(&temp, ins->alu.outmod);
/* Throw in the towel.. */
if (!progress) break;
.op = midgard_alu_op_imov,
.reg_mode = midgard_reg_mode_8,
.dest_override = midgard_dest_override_none,
- .outmod = midgard_outmod_int,
+ .outmod = midgard_outmod_int_wrap,
.mask = 0xFF,
.src1 = vector_alu_srco_unsigned(blank_alu_src),
.src2 = vector_alu_srco_unsigned(blank_alu_src),