Needed for memory and execution barriers.
Signed-off-by: Rob Clark <robdclark@gmail.com>
}
}
+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
OPC(6, OPC_LDC, ldc),
OPC(6, OPC_LDLV, ldlv),
+ OPC(7, OPC_BAR, bar),
+ OPC(7, OPC_FENCE, fence),
#undef OPC
};
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)");
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),
};
} 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;
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;
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;
}
}
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,
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
*/
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)
{
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.. */