r600/shader: add utility functions to do single slot arithmatic
authorDave Airlie <airlied@redhat.com>
Mon, 30 Nov 2015 05:34:14 +0000 (15:34 +1000)
committerDave Airlie <airlied@redhat.com>
Sun, 6 Dec 2015 23:59:01 +0000 (09:59 +1000)
These utilities are to be used to do things like integer adds and
multiplies to be used in calculating the LDS offsets etc.

It handles CAYMAN MULLO differences as well.

Signed-off-by: Dave Airlie <airlied@redhat.com>
src/gallium/drivers/r600/r600_shader.c

index 284eeead3e4551caf8f999bc30ff1f93cfc07822..8d117c1cb5f3f999f4b4c59a1a72fad2ca51ffcb 100644 (file)
@@ -666,6 +666,101 @@ static int select_twoside_color(struct r600_shader_ctx *ctx, int front, int back
        return 0;
 }
 
+/* execute a single slot ALU calculation */
+static int single_alu_op2(struct r600_shader_ctx *ctx, int op,
+                         int dst_sel, int dst_chan,
+                         int src0_sel, unsigned src0_chan_val,
+                         int src1_sel, unsigned src1_chan_val)
+{
+       struct r600_bytecode_alu alu;
+       int r, i;
+
+       if (ctx->bc->chip_class == CAYMAN && op == ALU_OP2_MULLO_INT) {
+               for (i = 0; i < 4; i++) {
+                       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+                       alu.op = op;
+                       alu.src[0].sel = src0_sel;
+                       if (src0_sel == V_SQ_ALU_SRC_LITERAL)
+                               alu.src[0].value = src0_chan_val;
+                       else
+                               alu.src[0].chan = src0_chan_val;
+                       alu.src[1].sel = src1_sel;
+                       if (src1_sel == V_SQ_ALU_SRC_LITERAL)
+                               alu.src[1].value = src1_chan_val;
+                       else
+                               alu.src[1].chan = src1_chan_val;
+                       alu.dst.sel = dst_sel;
+                       alu.dst.chan = i;
+                       alu.dst.write = i == dst_chan;
+                       alu.last = (i == 3);
+                       r = r600_bytecode_add_alu(ctx->bc, &alu);
+                       if (r)
+                               return r;
+               }
+               return 0;
+       }
+
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = op;
+       alu.src[0].sel = src0_sel;
+       if (src0_sel == V_SQ_ALU_SRC_LITERAL)
+               alu.src[0].value = src0_chan_val;
+       else
+               alu.src[0].chan = src0_chan_val;
+       alu.src[1].sel = src1_sel;
+       if (src1_sel == V_SQ_ALU_SRC_LITERAL)
+               alu.src[1].value = src1_chan_val;
+       else
+               alu.src[1].chan = src1_chan_val;
+       alu.dst.sel = dst_sel;
+       alu.dst.chan = dst_chan;
+       alu.dst.write = 1;
+       alu.last = 1;
+       r = r600_bytecode_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+       return 0;
+}
+
+/* execute a single slot ALU calculation */
+static int single_alu_op3(struct r600_shader_ctx *ctx, int op,
+                         int dst_sel, int dst_chan,
+                         int src0_sel, unsigned src0_chan_val,
+                         int src1_sel, unsigned src1_chan_val,
+                         int src2_sel, unsigned src2_chan_val)
+{
+       struct r600_bytecode_alu alu;
+       int r;
+
+       /* validate this for other ops */
+       assert(op == ALU_OP3_MULADD_UINT24);
+       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+       alu.op = op;
+       alu.src[0].sel = src0_sel;
+       if (src0_sel == V_SQ_ALU_SRC_LITERAL)
+               alu.src[0].value = src0_chan_val;
+       else
+               alu.src[0].chan = src0_chan_val;
+       alu.src[1].sel = src1_sel;
+       if (src1_sel == V_SQ_ALU_SRC_LITERAL)
+               alu.src[1].value = src1_chan_val;
+       else
+               alu.src[1].chan = src1_chan_val;
+       alu.src[2].sel = src2_sel;
+       if (src2_sel == V_SQ_ALU_SRC_LITERAL)
+               alu.src[2].value = src2_chan_val;
+       else
+               alu.src[2].chan = src2_chan_val;
+       alu.dst.sel = dst_sel;
+       alu.dst.chan = dst_chan;
+       alu.is_op3 = 1;
+       alu.last = 1;
+       r = r600_bytecode_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+       return 0;
+}
+
 static inline int get_address_file_reg(struct r600_shader_ctx *ctx, int index)
 {
        return index > 0 ? ctx->bc->index_reg[index - 1] : ctx->bc->ar_reg;