diff options
author | Eric Anholt <[email protected]> | 2016-08-25 13:21:58 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2016-08-25 17:24:11 -0700 |
commit | b160708e0307ea0baa2c7891ad9760cdfd39b4bc (patch) | |
tree | 05595bd2eb28f56f8173a94242bd11913e7c6f17 | |
parent | 31da39ddc92e780dc539bf34d2de7f82fc65fa86 (diff) |
vc4: Add real validation for MUL rotation.
Caught problems in the upcoming DDX/DDY implementation.
-rw-r--r-- | src/gallium/drivers/vc4/vc4_qpu_defines.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/vc4/vc4_qpu_validate.c | 49 |
2 files changed, 43 insertions, 10 deletions
diff --git a/src/gallium/drivers/vc4/vc4_qpu_defines.h b/src/gallium/drivers/vc4/vc4_qpu_defines.h index c0b7c56c007..3ca5aba76c9 100644 --- a/src/gallium/drivers/vc4/vc4_qpu_defines.h +++ b/src/gallium/drivers/vc4/vc4_qpu_defines.h @@ -286,6 +286,10 @@ enum qpu_unpack { #define QPU_RADDR_B_MASK QPU_MASK(17, 12) #define QPU_SMALL_IMM_SHIFT 12 #define QPU_SMALL_IMM_MASK QPU_MASK(17, 12) +/* Small immediate value for rotate-by-r5, and 49-63 are "rotate by n + * channels" + */ +#define QPU_SMALL_IMM_MUL_ROT 48 #define QPU_ADD_A_SHIFT 9 #define QPU_ADD_A_MASK QPU_MASK(11, 9) diff --git a/src/gallium/drivers/vc4/vc4_qpu_validate.c b/src/gallium/drivers/vc4/vc4_qpu_validate.c index 10bb84dd039..02fadaf6128 100644 --- a/src/gallium/drivers/vc4/vc4_qpu_validate.c +++ b/src/gallium/drivers/vc4/vc4_qpu_validate.c @@ -258,19 +258,48 @@ vc4_qpu_validate(uint64_t *insts, uint32_t num_inst) last_sfu_inst = i; } - int last_r5_write = -10; for (int i = 0; i < num_inst - 1; i++) { uint64_t inst = insts[i]; - /* "An instruction that does a vector rotate by r5 must not - * immediately follow an instruction that writes to r5." - */ - if (last_r5_write == i - 1 && - QPU_GET_FIELD(inst, QPU_SIG) == QPU_SIG_SMALL_IMM && - QPU_GET_FIELD(inst, QPU_SMALL_IMM) == 48) { - fail_instr(inst, - "vector rotate by r5 immediately " - "after r5 write"); + if (QPU_GET_FIELD(inst, QPU_SIG) == QPU_SIG_SMALL_IMM && + QPU_GET_FIELD(inst, QPU_SMALL_IMM) >= + QPU_SMALL_IMM_MUL_ROT) { + uint32_t mux_a = QPU_GET_FIELD(inst, QPU_MUL_A); + uint32_t mux_b = QPU_GET_FIELD(inst, QPU_MUL_B); + + /* "The full horizontal vector rotate is only + * available when both of the mul ALU input arguments + * are taken from accumulators r0-r3." + */ + if (mux_a > QPU_MUX_R3 || mux_b > QPU_MUX_R3) { + fail_instr(inst, + "MUL rotate using non-accumulator " + "input"); + } + + if (QPU_GET_FIELD(inst, QPU_SMALL_IMM) == + QPU_SMALL_IMM_MUL_ROT) { + /* "An instruction that does a vector rotate + * by r5 must not immediately follow an + * instruction that writes to r5." + */ + if (writes_reg(insts[i - 1], QPU_W_ACC5)) { + fail_instr(inst, + "vector rotate by r5 " + "immediately after r5 write"); + } + } + + /* "An instruction that does a vector rotate must not + * immediately follow an instruction that writes to the + * accumulator that is being rotated." + */ + if (writes_reg(insts[i - 1], QPU_W_ACC0 + mux_a) || + writes_reg(insts[i - 1], QPU_W_ACC0 + mux_b)) { + fail_instr(inst, + "vector rotate of value " + "written in previous instruction"); + } } } |