summaryrefslogtreecommitdiffstats
path: root/src/freedreno
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2019-02-07 11:02:45 -0500
committerRob Clark <[email protected]>2019-02-16 16:27:59 -0500
commitb46d5b8a8420d3e1a0da172940c318bb9ad369e1 (patch)
tree248e054e12644f795a9b9ece209e1b8704b02d29 /src/freedreno
parent2e0ea3f09c79c657116cbc9cbc68377e364dfe28 (diff)
freedreno/ir3: add a6xx instruction encoding
For the handful of instructions that use a new encoding. Signed-off-by: Rob Clark <[email protected]>
Diffstat (limited to 'src/freedreno')
-rw-r--r--src/freedreno/ir3/ir3.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/freedreno/ir3/ir3.c b/src/freedreno/ir3/ir3.c
index 3d1c4449b12..8c28e05f19e 100644
--- a/src/freedreno/ir3/ir3.c
+++ b/src/freedreno/ir3/ir3.c
@@ -480,11 +480,101 @@ static int emit_cat5(struct ir3_instruction *instr, void *ptr,
return 0;
}
+static int emit_cat6_a6xx(struct ir3_instruction *instr, void *ptr,
+ struct ir3_info *info)
+{
+ struct ir3_register *src1, *src2;
+ instr_cat6_a6xx_t *cat6 = ptr;
+
+ /* first reg should be SSBO binding point: */
+ iassert(instr->regs[1]->flags & IR3_REG_IMMED);
+
+ src1 = instr->regs[2];
+ src2 = instr->regs[3];
+
+ cat6->type = instr->cat6.type;
+ cat6->d = instr->cat6.d - 1;
+ cat6->typed = instr->cat6.typed;
+ cat6->type_size = instr->cat6.iim_val - 1;
+ cat6->opc = instr->opc;
+ cat6->jmp_tgt = !!(instr->flags & IR3_INSTR_JP);
+ cat6->sync = !!(instr->flags & IR3_INSTR_SY);
+ cat6->opc_cat = 6;
+
+ cat6->src1 = reg(src1, info, instr->repeat, 0);
+ cat6->src2 = reg(src2, info, instr->repeat, 0);
+ cat6->ssbo = instr->regs[1]->iim_val;
+
+ switch (instr->opc) {
+ case OPC_ATOMIC_ADD:
+ case OPC_ATOMIC_SUB:
+ case OPC_ATOMIC_XCHG:
+ case OPC_ATOMIC_INC:
+ case OPC_ATOMIC_DEC:
+ case OPC_ATOMIC_CMPXCHG:
+ case OPC_ATOMIC_MIN:
+ case OPC_ATOMIC_MAX:
+ case OPC_ATOMIC_AND:
+ case OPC_ATOMIC_OR:
+ case OPC_ATOMIC_XOR:
+ cat6->pad1 = 0x1;
+ cat6->pad2 = 0xc;
+ cat6->pad3 = 0x0;
+ cat6->pad4 = 0x3;
+ break;
+ case OPC_STIB:
+ cat6->pad1 = 0x0;
+ cat6->pad2 = 0xc;
+ cat6->pad3 = 0x0;
+ cat6->pad4 = 0x2;
+ break;
+ case OPC_LDC:
+ cat6->pad1 = 0x0;
+ cat6->pad2 = 0x8;
+ cat6->pad3 = 0x0;
+ cat6->pad4 = 0x2;
+ break;
+ default:
+ iassert(0);
+ }
+
+ return 0;
+}
+
static int emit_cat6(struct ir3_instruction *instr, void *ptr,
struct ir3_info *info)
{
struct ir3_register *dst, *src1, *src2;
instr_cat6_t *cat6 = ptr;
+
+ /* In a6xx we start using a new instruction encoding for some of
+ * these instructions:
+ */
+ if (info->gpu_id >= 600) {
+ switch (instr->opc) {
+ case OPC_ATOMIC_ADD:
+ case OPC_ATOMIC_SUB:
+ case OPC_ATOMIC_XCHG:
+ case OPC_ATOMIC_INC:
+ case OPC_ATOMIC_DEC:
+ case OPC_ATOMIC_CMPXCHG:
+ case OPC_ATOMIC_MIN:
+ case OPC_ATOMIC_MAX:
+ case OPC_ATOMIC_AND:
+ case OPC_ATOMIC_OR:
+ case OPC_ATOMIC_XOR:
+ /* The shared variants of these still use the old encoding: */
+ if (!(instr->flags & IR3_INSTR_G))
+ break;
+ /* fallthrough */
+ case OPC_STIB:
+ case OPC_LDC:
+ return emit_cat6_a6xx(instr, ptr, info);
+ default:
+ break;
+ }
+ }
+
bool type_full = type_size(instr->cat6.type) == 32;
cat6->type = instr->cat6.type;