}
static enum bifrost_packed_src
-bi_get_fma_src(bi_instruction *ins, struct bi_registers *regs, unsigned s)
+bi_get_src_const(struct bi_registers *regs, unsigned constant)
+{
+ if (regs->uniform_constant & (1 << 7))
+ unreachable("Tried to get constant but loading uniforms");
+
+ unsigned loc = (regs->uniform_constant >> 4) & 0x7;
+
+ if (loc != 0)
+ unreachable("TODO: constants in clauses");
+
+ unsigned lo = regs->uniform_constant & 0xF;
+
+ if (lo == 0) {
+ if (constant != 0)
+ unreachable("Tried to load !0 in 0 slot");
+
+ return BIFROST_SRC_CONST_LO;
+ } else {
+ unreachable("Special slot is not a fixed immediate");
+ }
+}
+
+static enum bifrost_packed_src
+bi_get_src(bi_instruction *ins, struct bi_registers *regs, unsigned s, bool is_fma)
{
unsigned src = ins->src[s];
if (src & BIR_INDEX_REGISTER)
return bi_get_src_reg_port(regs, src);
- else if (src & BIR_INDEX_ZERO)
+ else if (src & BIR_INDEX_ZERO && is_fma)
return BIFROST_SRC_STAGE;
+ else if (src & BIR_INDEX_ZERO)
+ return bi_get_src_const(regs, 0);
else if (src & BIR_INDEX_PASS)
return src & ~BIR_INDEX_PASS;
else
- unreachable("Unknown src in FMA");
+ unreachable("Unknown src");
}
static unsigned
bool negate_mul = ins->src_neg[0] ^ ins->src_neg[1];
struct bifrost_fma_fma pack = {
- .src0 = bi_get_fma_src(ins, regs, 0),
- .src1 = bi_get_fma_src(ins, regs, 1),
- .src2 = bi_get_fma_src(ins, regs, 2),
+ .src0 = bi_get_src(ins, regs, 0, true),
+ .src1 = bi_get_src(ins, regs, 1, true),
+ .src2 = bi_get_src(ins, regs, 2, true),
.src0_abs = ins->src_abs[0],
.src1_abs = ins->src_abs[1],
.src2_abs = ins->src_abs[2],
assert(ins->dest_type == nir_type_float32);
struct bifrost_fma_add pack = {
- .src0 = bi_get_fma_src(ins, regs, 0),
- .src1 = bi_get_fma_src(ins, regs, 1),
+ .src0 = bi_get_src(ins, regs, 0, true),
+ .src1 = bi_get_src(ins, regs, 1, true),
.src0_abs = ins->src_abs[0],
.src1_abs = ins->src_abs[1],
.src0_neg = ins->src_neg[0],
}
}
+static unsigned
+bi_pack_add_ld_vary(bi_instruction *ins, struct bi_registers *regs)
+{
+ unsigned size = nir_alu_type_get_type_size(ins->dest_type);
+ assert(size == 32 || size == 16);
+
+ unsigned op = (size == 32) ?
+ BIFROST_ADD_OP_LD_VAR_32 :
+ BIFROST_ADD_OP_LD_VAR_16;
+
+ unsigned cmask = bi_from_bytemask(ins->writemask, size / 8);
+ unsigned channels = util_bitcount(cmask);
+ assert(cmask == ((1 << channels) - 1));
+
+ unsigned packed_addr = 0;
+
+ if (ins->src[0] & BIR_INDEX_CONSTANT) {
+ /* Direct uses address field directly */
+ packed_addr = ins->src[0] & ~BIR_INDEX_CONSTANT;
+ assert(packed_addr < 0b1000);
+ } else {
+ /* Indirect gets an extra source */
+ packed_addr = bi_get_src(ins, regs, 0, false) | 0b11000;
+ }
+
+ assert(channels >= 1 && channels <= 4);
+
+ struct bifrost_ld_var pack = {
+ .src0 = bi_get_src(ins, regs, 1, false),
+ .addr = packed_addr,
+ .channels = MALI_POSITIVE(channels),
+ .interp_mode = ins->load_vary.interp_mode,
+ .reuse = ins->load_vary.reuse,
+ .flat = ins->load_vary.flat,
+ .op = op
+ };
+
+ RETURN_PACKED(pack);
+}
+
static unsigned
bi_pack_add(bi_clause *clause, bi_bundle bundle, struct bi_registers *regs)
{
case BI_LOAD:
case BI_LOAD_UNIFORM:
case BI_LOAD_ATTR:
+ return BIFROST_ADD_NOP;
case BI_LOAD_VAR:
+ return bi_pack_add_ld_vary(bundle.add, regs);
case BI_LOAD_VAR_ADDRESS:
case BI_MINMAX:
case BI_MOV: