diff options
author | Rob Clark <[email protected]> | 2019-02-07 11:02:45 -0500 |
---|---|---|
committer | Rob Clark <[email protected]> | 2019-02-16 16:27:59 -0500 |
commit | b46d5b8a8420d3e1a0da172940c318bb9ad369e1 (patch) | |
tree | 248e054e12644f795a9b9ece209e1b8704b02d29 /src/freedreno | |
parent | 2e0ea3f09c79c657116cbc9cbc68377e364dfe28 (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.c | 90 |
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; |