There are lots of MUL quirks for gen8+. This patch is missing one assertion, "In Align16 mode, format conversion from double-float to floats is not allowed when source is immediate data" I don't believe we're using double floats, and I wasn't actually sure what the best way to make the assertion was.
Signed-off-by: Ben Widawsky <b...@bwidawsk.net> --- src/mesa/drivers/dri/i965/brw_eu_emit.c | 77 ++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 5 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_eu_emit.c b/src/mesa/drivers/dri/i965/brw_eu_emit.c index 1fc5a2f..c53e039 100644 --- a/src/mesa/drivers/dri/i965/brw_eu_emit.c +++ b/src/mesa/drivers/dri/i965/brw_eu_emit.c @@ -36,6 +36,15 @@ #include "util/ralloc.h" +static const int hstride_for_reg[] = {0, 1, 2, 4}; +static const int vstride_for_reg[] = {0, 1, 2, 4, 8, 16, 32}; +static const int width_for_reg[] = {1, 2, 4, 8, 16}; +static const int execsize_for_reg[] = {1, 2, 4, 8, 16}; + +#define reg_vs(reg) vstride_for_reg[reg.vstride] +#define reg_hs(reg) hstride_for_reg[reg.hstride] +#define reg_wi(reg) width_for_reg[reg.width] + /*********************************************************************** * Internal helper for constructing instructions */ @@ -226,10 +235,6 @@ extern int reg_type_size[]; static void validate_reg(const struct brw_context *brw, brw_inst *inst, struct brw_reg reg) { - const int hstride_for_reg[] = {0, 1, 2, 4}; - const int vstride_for_reg[] = {0, 1, 2, 4, 8, 16, 32}; - const int width_for_reg[] = {1, 2, 4, 8, 16}; - const int execsize_for_reg[] = {1, 2, 4, 8, 16}; int width, hstride, vstride, execsize; if (reg.file == BRW_IMMEDIATE_VALUE) { @@ -1099,6 +1104,9 @@ brw_inst * brw_MUL(struct brw_compile *p, struct brw_reg dest, struct brw_reg src0, struct brw_reg src1) { + const struct brw_context *brw = p->brw; + brw_inst *insn = next_insn(p, BRW_OPCODE_MUL); + /* 6.32.38: mul */ if (type_is_dword(src0.type) || type_is_dword(src1.type)) { assert(dest.type != BRW_REGISTER_TYPE_F); @@ -1121,7 +1129,66 @@ brw_MUL(struct brw_compile *p, struct brw_reg dest, assert(src1.file != BRW_ARCHITECTURE_REGISTER_FILE || src1.nr != BRW_ARF_ACCUMULATOR); - return brw_alu2(p, BRW_OPCODE_MUL, dest, src0, src1); + /* When source or destination datatype is 64b or operation is integer DWord + * multiply, regioning in Align1 must follow these rules: + */ + const bool chv_danger = (brw->is_cherryview /* TODO: next SoC */ && + (brw_inst_access_mode(brw, p->current) == BRW_ALIGN_1) && + ((type_is_dword(src0.type) && type_is_dword(src1.type)) || + dest.type == BRW_REGISTER_TYPE_UQ || dest.type == BRW_REGISTER_TYPE_Q)); + + if (chv_danger) { + /* "Source and Destination horizontal stride must be aligned to the + * same qword." + * + * XXX: We don't support qword source yet, therefore this only implies + * that the source is a multiple of dest. It is assumed that scalars + * aren't considered. + */ + assert(src0.hstride == 0 || reg_hs(dest) % reg_hs(src0) == 0); + assert(src1.hstride == 0 || reg_hs(dest) % reg_hs(src1) == 0); + + /* "Regioning must ensure Src.Vstride = Src.Width * Src.Hstride" */ + assert(reg_vs(src0) == reg_wi(src0) * reg_hs(src0)); + assert(reg_vs(src1) == reg_wi(src1) * reg_hs(src1)); + + /* "Source and Destination offset must be the same, except the case of + * scalar source." + */ + assert(is_scalar_region(src0) || src0.subnr == dest.subnr); + assert(is_scalar_region(src1) || src1.subnr == dest.subnr); + + /* "Indirect addressing must not be used." */ + assert(src0.address_mode != BRW_ADDRESS_REGISTER_INDIRECT_REGISTER && + src1.address_mode != BRW_ADDRESS_REGISTER_INDIRECT_REGISTER && + dest.address_mode != BRW_ADDRESS_REGISTER_INDIRECT_REGISTER); + + /* "ARF registers must never be used." */ + assert(dest.file != BRW_ARCHITECTURE_REGISTER_FILE && + src0.file != BRW_ARCHITECTURE_REGISTER_FILE && + src1.file != BRW_ARCHITECTURE_REGISTER_FILE); + + /* "DepCtrl must not be used." */ + assert(!brw_inst_no_dd_clear(brw, insn) && + !brw_inst_no_dd_check(brw, insn)); + } else if (brw->gen >= 8 && !brw->is_cherryview) { + if (brw->gen >= 10) + _mesa_warning(NULL, "May or may not have ALIGN16 restriction.\n"); + + /* If Align16 is required for an operation with QW destination and non-QW + * source datatypes, the execution size cannot exceed 2. + * XXX:We never use QW on Align16 + */ + assert(brw_inst_access_mode(brw, p->current) != BRW_ALIGN_16 || + (dest.type != BRW_REGISTER_TYPE_UQ && + dest.type != BRW_REGISTER_TYPE_Q)); + } + + brw_set_dest(p, insn, dest); + brw_set_src0(p, insn, src0); + brw_set_src1(p, insn, src1); + + return insn; } brw_inst * -- 2.2.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev