- uint32_t src_muxes[] = {
- QPU_GET_FIELD(q->inst, QPU_ADD_A),
- QPU_GET_FIELD(q->inst, QPU_ADD_B),
- QPU_GET_FIELD(q->inst, QPU_MUL_A),
- QPU_GET_FIELD(q->inst, QPU_MUL_B),
- };
-
- /* "An instruction must not read from a location in physical
- * regfile A or B that was written to by the previous
- * instruction."
- */
- bool needs_raddr_vs_waddr_nop = false;
- bool reads_r4 = false;
- for (int i = 0; i < ARRAY_SIZE(src_muxes); i++) {
- if ((raddr_a < 32 &&
- src_muxes[i] == QPU_MUX_A &&
- last_waddr_a == raddr_a) ||
- (raddr_b < 32 &&
- src_muxes[i] == QPU_MUX_B &&
- last_waddr_b == raddr_b)) {
- needs_raddr_vs_waddr_nop = true;
- }
- if (src_muxes[i] == QPU_MUX_R4)
- reads_r4 = true;
- }
-
- if (needs_raddr_vs_waddr_nop) {
- serialize_one_inst(c, qpu_NOP());
- }
-
- /* "After an SFU lookup instruction, accumulator r4 must not
- * be read in the following two instructions. Any other
- * instruction that results in r4 being written (that is, TMU
- * read, TLB read, SFU lookup) cannot occur in the two
- * instructions following an SFU lookup."
- */
- if (reads_r4) {
- while (c->qpu_inst_count - last_sfu_write < 3) {
- serialize_one_inst(c, qpu_NOP());
- }
- }
-
- uint32_t waddr_a = QPU_GET_FIELD(q->inst, QPU_WADDR_ADD);
- uint32_t waddr_m = QPU_GET_FIELD(q->inst, QPU_WADDR_MUL);
- if ((waddr_a >= QPU_W_SFU_RECIP && waddr_a <= QPU_W_SFU_LOG) ||
- (waddr_m >= QPU_W_SFU_RECIP && waddr_m <= QPU_W_SFU_LOG)) {
- last_sfu_write = c->qpu_inst_count;
- }
-
- /* "A scoreboard wait must not occur in the first two
- * instructions of a fragment shader. This is either the
- * explicit Wait for Scoreboard signal or an implicit wait
- * with the first tile-buffer read or write instruction."
- */
- if (!scoreboard_wait_emitted &&
- (waddr_a == QPU_W_TLB_Z || waddr_m == QPU_W_TLB_Z ||
- waddr_a == QPU_W_TLB_COLOR_MS ||
- waddr_m == QPU_W_TLB_COLOR_MS ||
- waddr_a == QPU_W_TLB_COLOR_ALL ||
- waddr_m == QPU_W_TLB_COLOR_ALL ||
- QPU_GET_FIELD(q->inst, QPU_SIG) == QPU_SIG_COLOR_LOAD)) {
- while (c->qpu_inst_count < 3 ||
- QPU_GET_FIELD(c->qpu_insts[c->qpu_inst_count - 1],
- QPU_SIG) != QPU_SIG_NONE) {
- serialize_one_inst(c, qpu_NOP());
- }
- c->qpu_insts[c->qpu_inst_count - 1] =
- qpu_set_sig(c->qpu_insts[c->qpu_inst_count - 1],
- QPU_SIG_WAIT_FOR_SCOREBOARD);
- scoreboard_wait_emitted = true;
- }