vc4: Add support for CMP.
authorEric Anholt <eric@anholt.net>
Wed, 16 Jul 2014 15:12:27 +0000 (08:12 -0700)
committerEric Anholt <eric@anholt.net>
Sat, 9 Aug 2014 01:59:47 +0000 (18:59 -0700)
This took a couple of tries, and this is the squash of those attempts.

v2: Fix register file conflicts on the args in the
    destination-is-accumulator case.
v3: Rebase on helper change and qir_inst4 change.

src/gallium/drivers/vc4/vc4_program.c
src/gallium/drivers/vc4/vc4_qir.c
src/gallium/drivers/vc4/vc4_qir.h
src/gallium/drivers/vc4/vc4_qpu_emit.c

index 0e415a8baf61dc5e39ba390a3996a7f73ad3b3a1..993ac41fc110a695fdb5461f9438262e0c5021cf 100644 (file)
@@ -202,7 +202,11 @@ tgsi_to_qir_alu(struct tgsi_to_qir *trans,
 {
         struct qcompile *c = trans->c;
         struct qreg dst = qir_get_temp(c);
-        qir_emit(c, qir_inst(op, dst, src[0 * 4 + i], src[1 * 4 + i]));
+        qir_emit(c, qir_inst4(op, dst,
+                              src[0 * 4 + i],
+                              src[1 * 4 + i],
+                              src[2 * 4 + i],
+                              c->undef));
         return dst;
 }
 
@@ -325,6 +329,7 @@ emit_tgsi_instruction(struct tgsi_to_qir *trans,
                 [TGSI_OPCODE_SNE] = { QOP_SNE, tgsi_to_qir_alu },
                 [TGSI_OPCODE_SGE] = { QOP_SGE, tgsi_to_qir_alu },
                 [TGSI_OPCODE_SLT] = { QOP_SLT, tgsi_to_qir_alu },
+                [TGSI_OPCODE_CMP] = { QOP_CMP, tgsi_to_qir_alu },
                 [TGSI_OPCODE_MAD] = { 0, tgsi_to_qir_mad },
                 [TGSI_OPCODE_DP2] = { 0, tgsi_to_qir_dp2 },
                 [TGSI_OPCODE_DP3] = { 0, tgsi_to_qir_dp3 },
index 02342f212c317edcc0734f1bc1875f613a3520c4..b8a8a7ca7dc18a5b1cc55ee2045bf8ad1ea22a02 100644 (file)
@@ -48,6 +48,7 @@ static const struct qir_op_info qir_op_info[] = {
         [QOP_SNE] = { "sne", 1, 2 },
         [QOP_SGE] = { "sge", 1, 2 },
         [QOP_SLT] = { "slt", 1, 2 },
+        [QOP_CMP] = { "cmp", 1, 3 },
 
         [QOP_FTOI] = { "ftoi", 1, 1 },
         [QOP_RCP] = { "rcp", 1, 1 },
index cd7133cdc88761422af4177243bf36f5b0e0b959..76e46ff107f3a419ae09b00f6f1a1866ba3426ad 100644 (file)
@@ -55,6 +55,7 @@ enum qop {
         QOP_SNE,
         QOP_SGE,
         QOP_SLT,
+        QOP_CMP,
 
         QOP_FTOI,
         QOP_RCP,
index b8a506eb174cf18e77cdd67bcb22d9c15518a57f..da47539af0f2f6694bbc4a9969050fe13f89d756 100644 (file)
@@ -332,6 +332,46 @@ vc4_generate_code(struct qcompile *c)
                         }
                         break;
 
+                case QOP_CMP:
+                        queue(c, qpu_inst(qpu_a_MOV(qpu_ra(QPU_W_NOP),
+                                                    src[0]),
+                                          qpu_m_NOP()));
+                        *last_inst(c) |= QPU_SF;
+
+                        if (dst.mux <= QPU_MUX_R3) {
+                                fixup_raddr_conflict(c, src[1], &src[2]);
+                                queue(c, qpu_inst(qpu_a_MOV(dst, src[1]),
+                                                  qpu_m_MOV(dst, src[2])));
+                                *last_inst(c) = ((*last_inst(c) & ~(QPU_COND_ADD_MASK |
+                                                                    QPU_COND_MUL_MASK))
+                                                 | QPU_SET_FIELD(QPU_COND_NS,
+                                                                 QPU_COND_ADD)
+                                                 | QPU_SET_FIELD(QPU_COND_NC,
+                                                                 QPU_COND_MUL));
+                        } else {
+                                if (dst.mux == src[1].mux &&
+                                    dst.addr == src[1].addr) {
+                                        queue(c, qpu_inst(qpu_a_MOV(dst, src[1]),
+                                                          qpu_m_NOP()));
+
+                                        queue(c, qpu_inst(qpu_a_MOV(dst, src[2]),
+                                                          qpu_m_NOP()));
+                                        *last_inst(c) = ((*last_inst(c) & ~(QPU_COND_ADD_MASK))
+                                                         | QPU_SET_FIELD(QPU_COND_NC,
+                                                                         QPU_COND_ADD));
+                                } else {
+                                        queue(c, qpu_inst(qpu_a_MOV(dst, src[2]),
+                                                          qpu_m_NOP()));
+
+                                        queue(c, qpu_inst(qpu_a_MOV(dst, src[1]),
+                                                          qpu_m_NOP()));
+                                        *last_inst(c) = ((*last_inst(c) & ~(QPU_COND_ADD_MASK))
+                                                         | QPU_SET_FIELD(QPU_COND_NS,
+                                                                         QPU_COND_ADD));
+                                }
+                        }
+                        break;
+
                 case QOP_SEQ:
                 case QOP_SNE:
                 case QOP_SGE: