}
static bool
+qpu_compatible_peripheral_access(const struct v3d_device_info *devinfo,
+ const struct v3d_qpu_instr *a,
+ const struct v3d_qpu_instr *b)
+{
+ const bool a_uses_peripheral = qpu_accesses_peripheral(a);
+ const bool b_uses_peripheral = qpu_accesses_peripheral(b);
+
+ /* We can always do one peripheral access per instruction. */
+ if (!a_uses_peripheral || !b_uses_peripheral)
+ return true;
+
+ if (devinfo->ver < 41)
+ return false;
+
+ /* V3D 4.1 and later allow TMU read along with a VPM read or write, and
+ * WRTMUC with a TMU magic register write (other than tmuc).
+ */
+ if ((a->sig.ldtmu && v3d_qpu_uses_vpm(b)) ||
+ (b->sig.ldtmu && v3d_qpu_uses_vpm(a))) {
+ return true;
+ }
+
+ if ((a->sig.wrtmuc && v3d_qpu_writes_tmu_not_tmuc(b)) ||
+ (b->sig.wrtmuc && v3d_qpu_writes_tmu_not_tmuc(a))) {
+ return true;
+ }
+
+ return false;
+}
+
+static bool
qpu_merge_inst(const struct v3d_device_info *devinfo,
struct v3d_qpu_instr *result,
const struct v3d_qpu_instr *a,
return false;
}
- /* Can't do more than one peripheral access in an instruction.
- *
- * XXX: V3D 4.1 allows TMU read along with a VPM read or write, and
- * WRTMUC with a TMU magic register write (other than tmuc).
- */
- if (qpu_accesses_peripheral(a) && qpu_accesses_peripheral(b))
+ if (!qpu_compatible_peripheral_access(devinfo, a, b))
return false;
struct v3d_qpu_instr merge = *a;
}
bool
+v3d_qpu_writes_tmu_not_tmuc(const struct v3d_qpu_instr *inst)
+{
+ return v3d_qpu_writes_tmu(inst) &&
+ (!inst->alu.add.magic_write ||
+ inst->alu.add.waddr != V3D_QPU_WADDR_TMUC) &&
+ (!inst->alu.mul.magic_write ||
+ inst->alu.mul.waddr != V3D_QPU_WADDR_TMUC);
+}
+
+bool
v3d_qpu_reads_vpm(const struct v3d_qpu_instr *inst)
{
if (inst->sig.ldvpm)
bool v3d_qpu_uses_tlb(const struct v3d_qpu_instr *inst) ATTRIBUTE_CONST;
bool v3d_qpu_uses_sfu(const struct v3d_qpu_instr *inst) ATTRIBUTE_CONST;
bool v3d_qpu_writes_tmu(const struct v3d_qpu_instr *inst) ATTRIBUTE_CONST;
+bool v3d_qpu_writes_tmu_not_tmuc(const struct v3d_qpu_instr *inst) ATTRIBUTE_CONST;
bool v3d_qpu_writes_r3(const struct v3d_device_info *devinfo,
const struct v3d_qpu_instr *instr) ATTRIBUTE_CONST;
bool v3d_qpu_writes_r4(const struct v3d_device_info *devinfo,