aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2014-07-16 08:12:27 -0700
committerEric Anholt <[email protected]>2014-08-08 18:59:47 -0700
commit4c53087c67a266d81653459baa08ece5c1b418d8 (patch)
tree105694f640c6a1b65d11dae94f06469e2b9dea4e
parenteea1d36915cb97ee1a6eb6aeaf15dd5689f03148 (diff)
vc4: Add support for CMP.
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.
-rw-r--r--src/gallium/drivers/vc4/vc4_program.c7
-rw-r--r--src/gallium/drivers/vc4/vc4_qir.c1
-rw-r--r--src/gallium/drivers/vc4/vc4_qir.h1
-rw-r--r--src/gallium/drivers/vc4/vc4_qpu_emit.c40
4 files changed, 48 insertions, 1 deletions
diff --git a/src/gallium/drivers/vc4/vc4_program.c b/src/gallium/drivers/vc4/vc4_program.c
index 0e415a8baf6..993ac41fc11 100644
--- a/src/gallium/drivers/vc4/vc4_program.c
+++ b/src/gallium/drivers/vc4/vc4_program.c
@@ -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 },
diff --git a/src/gallium/drivers/vc4/vc4_qir.c b/src/gallium/drivers/vc4/vc4_qir.c
index 02342f212c3..b8a8a7ca7dc 100644
--- a/src/gallium/drivers/vc4/vc4_qir.c
+++ b/src/gallium/drivers/vc4/vc4_qir.c
@@ -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 },
diff --git a/src/gallium/drivers/vc4/vc4_qir.h b/src/gallium/drivers/vc4/vc4_qir.h
index cd7133cdc88..76e46ff107f 100644
--- a/src/gallium/drivers/vc4/vc4_qir.h
+++ b/src/gallium/drivers/vc4/vc4_qir.h
@@ -55,6 +55,7 @@ enum qop {
QOP_SNE,
QOP_SGE,
QOP_SLT,
+ QOP_CMP,
QOP_FTOI,
QOP_RCP,
diff --git a/src/gallium/drivers/vc4/vc4_qpu_emit.c b/src/gallium/drivers/vc4/vc4_qpu_emit.c
index b8a506eb174..da47539af0f 100644
--- a/src/gallium/drivers/vc4/vc4_qpu_emit.c
+++ b/src/gallium/drivers/vc4/vc4_qpu_emit.c
@@ -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: