From 6da513007474ddee48edf256e435a0fa7a65335d Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 30 Oct 2017 19:24:59 -0400 Subject: [PATCH] freedreno/ir3: add cat7 instructions Needed for memory and execution barriers. Signed-off-by: Rob Clark --- .../drivers/freedreno/ir3/disasm-a3xx.c | 21 ++++++++++++++- .../drivers/freedreno/ir3/instr-a3xx.h | 26 ++++++++++++++++++- src/gallium/drivers/freedreno/ir3/ir3.c | 19 ++++++++++++++ src/gallium/drivers/freedreno/ir3/ir3.h | 15 +++++++++++ 4 files changed, 79 insertions(+), 2 deletions(-) diff --git a/src/gallium/drivers/freedreno/ir3/disasm-a3xx.c b/src/gallium/drivers/freedreno/ir3/disasm-a3xx.c index 4685ed6deae..96b34649c37 100644 --- a/src/gallium/drivers/freedreno/ir3/disasm-a3xx.c +++ b/src/gallium/drivers/freedreno/ir3/disasm-a3xx.c @@ -714,6 +714,23 @@ static void print_instr_cat6(instr_t *instr) } } +static void print_instr_cat7(instr_t *instr) +{ + instr_cat7_t *cat7 = &instr->cat7; + + if (cat7->g) + printf(".g"); + if (cat7->l) + printf(".l"); + + if (_OPC(7, cat7->opc) == OPC_FENCE) { + if (cat7->r) + printf(".r"); + if (cat7->w) + printf(".w"); + } +} + /* size of largest OPC field of all the instruction categories: */ #define NOPC_BITS 6 @@ -879,6 +896,8 @@ static const struct opc_info { OPC(6, OPC_LDC, ldc), OPC(6, OPC_LDLV, ldlv), + OPC(7, OPC_BAR, bar), + OPC(7, OPC_FENCE, fence), #undef OPC }; @@ -909,7 +928,7 @@ static void print_instr(uint32_t *dwords, int level, int n) if (instr->sync) printf("(sy)"); - if (instr->ss && (instr->opc_cat <= 4)) + if (instr->ss && ((instr->opc_cat <= 4) || (instr->opc_cat == 7))) printf("(ss)"); if (instr->jmp_tgt) printf("(jp)"); diff --git a/src/gallium/drivers/freedreno/ir3/instr-a3xx.h b/src/gallium/drivers/freedreno/ir3/instr-a3xx.h index b429b3b9ffc..9edcc58ce9c 100644 --- a/src/gallium/drivers/freedreno/ir3/instr-a3xx.h +++ b/src/gallium/drivers/freedreno/ir3/instr-a3xx.h @@ -195,6 +195,10 @@ typedef enum { OPC_LDC = _OPC(6, 30), OPC_LDLV = _OPC(6, 31), + /* category 7: */ + OPC_BAR = _OPC(7, 0), + OPC_FENCE = _OPC(7, 1), + /* meta instructions (category -1): */ /* placeholder instr to mark shader inputs: */ OPC_META_INPUT = _OPC(-1, 0), @@ -715,6 +719,24 @@ typedef union PACKED { }; } instr_cat6_t; +typedef struct PACKED { + /* dword0: */ + uint32_t pad1 : 32; + + /* dword1: */ + uint32_t pad2 : 12; + uint32_t ss : 1; /* maybe in the encoding, but blob only uses (sy) */ + uint32_t pad3 : 6; + uint32_t w : 1; /* write */ + uint32_t r : 1; /* read */ + uint32_t l : 1; /* local */ + uint32_t g : 1; /* global */ + uint32_t opc : 4; /* presumed, but only a couple known OPCs */ + uint32_t jmp_tgt : 1; /* (jp) */ + uint32_t sync : 1; /* (sy) */ + uint32_t opc_cat : 3; +} instr_cat7_t; + typedef union PACKED { instr_cat0_t cat0; instr_cat1_t cat1; @@ -723,12 +745,13 @@ typedef union PACKED { instr_cat4_t cat4; instr_cat5_t cat5; instr_cat6_t cat6; + instr_cat7_t cat7; struct PACKED { /* dword0: */ uint64_t pad1 : 40; uint32_t repeat : 3; /* cat0-cat4 */ uint32_t pad2 : 1; - uint32_t ss : 1; /* cat1-cat4 (cat0??) */ + uint32_t ss : 1; /* cat1-cat4 (cat0??) and cat7 (?) */ uint32_t ul : 1; /* cat2-cat4 (and cat1 in blob.. which may be bug??) */ uint32_t pad3 : 13; uint32_t jmp_tgt : 1; @@ -748,6 +771,7 @@ static inline uint32_t instr_opc(instr_t *instr) case 4: return instr->cat4.opc; case 5: return instr->cat5.opc; case 6: return instr->cat6.opc; + case 7: return instr->cat7.opc; default: return 0; } } diff --git a/src/gallium/drivers/freedreno/ir3/ir3.c b/src/gallium/drivers/freedreno/ir3/ir3.c index d703f4e7f38..61bc3b5ad47 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3.c +++ b/src/gallium/drivers/freedreno/ir3/ir3.c @@ -604,9 +604,28 @@ static int emit_cat6(struct ir3_instruction *instr, void *ptr, return 0; } +static int emit_cat7(struct ir3_instruction *instr, void *ptr, + struct ir3_info *info) +{ + instr_cat7_t *cat7 = ptr; + + cat7->ss = !!(instr->flags & IR3_INSTR_SS); + cat7->w = instr->cat7.w; + cat7->r = instr->cat7.r; + cat7->l = instr->cat7.l; + cat7->g = instr->cat7.g; + cat7->opc = instr->opc; + cat7->jmp_tgt = !!(instr->flags & IR3_INSTR_JP); + cat7->sync = !!(instr->flags & IR3_INSTR_SY); + cat7->opc_cat = 7; + + return 0; +} + static int (*emit[])(struct ir3_instruction *instr, void *ptr, struct ir3_info *info) = { emit_cat0, emit_cat1, emit_cat2, emit_cat3, emit_cat4, emit_cat5, emit_cat6, + emit_cat7, }; void * ir3_assemble(struct ir3 *shader, struct ir3_info *info, diff --git a/src/gallium/drivers/freedreno/ir3/ir3.h b/src/gallium/drivers/freedreno/ir3/ir3.h index de7a2a88733..25fddbf00f4 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3.h +++ b/src/gallium/drivers/freedreno/ir3/ir3.h @@ -228,6 +228,12 @@ struct ir3_instruction { int dst_offset; int iim_val; /* for ldgb/stgb, # of components */ } cat6; + struct { + unsigned w : 1; /* write */ + unsigned r : 1; /* read */ + unsigned l : 1; /* local */ + unsigned g : 1; /* global */ + } cat7; /* for meta-instructions, just used to hold extra data * before instruction scheduling, etc */ @@ -605,6 +611,11 @@ static inline bool is_mem(struct ir3_instruction *instr) return (opc_cat(instr->opc) == 6); } +static inline bool is_barrier(struct ir3_instruction *instr) +{ + return (opc_cat(instr->opc) == 7); +} + static inline bool is_store(struct ir3_instruction *instr) { @@ -1179,6 +1190,10 @@ INSTR4(ATOMIC_AND); INSTR4(ATOMIC_OR); INSTR4(ATOMIC_XOR); +/* cat7 instructions: */ +INSTR0(BAR); +INSTR0(FENCE); + /* ************************************************************************* */ /* split this out or find some helper to use.. like main/bitset.h.. */ -- 2.30.2