diff options
Diffstat (limited to 'src/gallium/drivers/freedreno/ir3/ir3.c')
-rw-r--r-- | src/gallium/drivers/freedreno/ir3/ir3.c | 74 |
1 files changed, 66 insertions, 8 deletions
diff --git a/src/gallium/drivers/freedreno/ir3/ir3.c b/src/gallium/drivers/freedreno/ir3/ir3.c index ff2c342c357..d703f4e7f38 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3.c +++ b/src/gallium/drivers/freedreno/ir3/ir3.c @@ -475,6 +475,13 @@ static int emit_cat6(struct ir3_instruction *instr, void *ptr, struct ir3_register *dst, *src1, *src2; instr_cat6_t *cat6 = ptr; + cat6->type = instr->cat6.type; + cat6->opc = instr->opc; + cat6->jmp_tgt = !!(instr->flags & IR3_INSTR_JP); + cat6->sync = !!(instr->flags & IR3_INSTR_SY); + cat6->g = !!(instr->flags & IR3_INSTR_G); + cat6->opc_cat = 6; + /* the "dst" for a store instruction is (from the perspective * of data flow in the shader, ie. register use/def, etc) in * fact a register that is read by the instruction, rather @@ -500,7 +507,65 @@ static int emit_cat6(struct ir3_instruction *instr, void *ptr, * indicate to use the src_off encoding even if offset is zero * (but then what to do about dst_off?) */ - if (instr->cat6.src_offset || (instr->opc == OPC_LDG)) { + if ((instr->opc == OPC_LDGB) || is_atomic(instr->opc)) { + struct ir3_register *src3 = instr->regs[3]; + instr_cat6ldgb_t *ldgb = ptr; + + /* maybe these two bits both determine the instruction encoding? */ + cat6->src_off = false; + + ldgb->d = 4 - 1; /* always .4d ? */ + ldgb->typed = false; /* TODO true for images */ + ldgb->type_size = instr->cat6.iim_val - 1; + + ldgb->dst = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF); + + /* first src is src_ssbo: */ + iassert(src1->flags & IR3_REG_IMMED); + ldgb->src_ssbo = src1->uim_val; + + /* then next two are src1/src2: */ + ldgb->src1 = reg(src2, info, instr->repeat, IR3_REG_IMMED); + ldgb->src1_im = !!(src2->flags & IR3_REG_IMMED); + ldgb->src2 = reg(src3, info, instr->repeat, IR3_REG_IMMED); + ldgb->src2_im = !!(src3->flags & IR3_REG_IMMED); + + if (is_atomic(instr->opc)) { + struct ir3_register *src4 = instr->regs[4]; + ldgb->src3 = reg(src4, info, instr->repeat, 0); + ldgb->pad0 = 0x1; + ldgb->pad3 = 0x3; + } else { + ldgb->pad0 = 0x0; + ldgb->pad3 = 0x2; + } + + return 0; + } else if (instr->opc == OPC_STGB) { + struct ir3_register *src3 = instr->regs[4]; + instr_cat6stgb_t *stgb = ptr; + + /* maybe these two bits both determine the instruction encoding? */ + cat6->src_off = true; + stgb->pad3 = 0x2; + + stgb->d = 4 - 1; /* always .4d ? */ + stgb->typed = false; + stgb->type_size = instr->cat6.iim_val - 1; + + /* first src is dst_ssbo: */ + iassert(dst->flags & IR3_REG_IMMED); + stgb->dst_ssbo = dst->uim_val; + + /* then src1/src2/src3: */ + stgb->src1 = reg(src1, info, instr->repeat, 0); + stgb->src2 = reg(src2, info, instr->repeat, IR3_REG_IMMED); + stgb->src2_im = !!(src2->flags & IR3_REG_IMMED); + stgb->src3 = reg(src3, info, instr->repeat, IR3_REG_IMMED); + stgb->src3_im = !!(src3->flags & IR3_REG_IMMED); + + return 0; + } else if (instr->cat6.src_offset || (instr->opc == OPC_LDG)) { instr_cat6a_t *cat6a = ptr; cat6->src_off = true; @@ -536,13 +601,6 @@ static int emit_cat6(struct ir3_instruction *instr, void *ptr, cat6d->dst = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF); } - cat6->type = instr->cat6.type; - cat6->opc = instr->opc; - cat6->jmp_tgt = !!(instr->flags & IR3_INSTR_JP); - cat6->sync = !!(instr->flags & IR3_INSTR_SY); - cat6->g = !!(instr->flags & IR3_INSTR_G); - cat6->opc_cat = 6; - return 0; } |