#include "ir3_parser.h"
+#define swap(a, b) \
+ do { __typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0)
+
/* ir3 treats the abs/neg flags as separate flags for float vs integer,
* but in the instruction encoding they are the same thing. Tracking
* them separately is only for the benefit of ir3 opt passes, and not
cat6_bindless_mode: T_IMM cat6_bindless_base
| T_UNIFORM cat6_bindless_base
-| T_NONUNIFORM cat6_bindless_base
+| T_NONUNIFORM cat6_bindless_base { instr->flags |= IR3_INSTR_NONUNIF; }
cat6_reg_or_immed: reg
| integer { new_reg(0, IR3_REG_IMMED)->iim_val = $1; }
cat6_bindless_ibo: cat6_bindless_ibo_opc cat6_typed cat6_dim cat6_type '.' cat6_immed '.' cat6_bindless_mode dst_reg ',' cat6_reg_or_immed
+cat6_bindless_ldc_opc: T_OP_LDC { new_instr(OPC_LDC); }
+
+cat6_bindless_ldc: cat6_bindless_ldc_opc '.' T_OFFSET '.' cat6_immed '.' cat6_bindless_mode dst_reg ',' cat6_reg_or_immed ',' cat6_reg_or_immed {
+ instr->cat6.d = $3;
+ instr->cat6.type = TYPE_U32;
+ /* TODO cleanup ir3 src order: */
+ swap(instr->regs[1], instr->regs[2]);
+ }
+
cat6_todo: T_OP_G2L { new_instr(OPC_G2L); }
| T_OP_L2G { new_instr(OPC_L2G); }
| T_OP_RESFMT { new_instr(OPC_RESFMT); }
| T_OP_LDGB { new_instr(OPC_LDGB); }
| T_OP_STGB { new_instr(OPC_STGB); }
-| T_OP_LDC { new_instr(OPC_LDC); }
cat6_instr: cat6_load
| cat6_store
| cat6_prefetch
| cat6_atomic
| cat6_id
+| cat6_bindless_ldc
| cat6_bindless_ibo
| cat6_todo
/* LDC. Our disasm differs greatly from qcom here, and we've got some
* important info they lack(?!), but same goes the other way.
*/
+#if 0
+ /* TODO our encoding differs in b23 for these four.. unsure if that is dontcare bit */
/* dEQP-GLES31.functional.shaders.opaque_type_indexing.ubo.uniform_fragment */
INSTR_6XX(c0260000_00c78040, "ldc.offset0.1.uniform r0.x, r0.x, r0.x"), /* ldc.1.mode1.base0 r0.x, 0, r0.x */
INSTR_6XX(c0260201_00c78040, "ldc.offset0.1.uniform r0.y, r0.x, r0.y"), /* ldc.1.mode1.base0 r0.y, 0, r0.y */
/* dEQP-GLES31.functional.shaders.opaque_type_indexing.ubo.dynamically_uniform_fragment */
INSTR_6XX(c0260000_00c78080, "ldc.offset0.1.nonuniform r0.x, r0.x, r0.x"), /* ldc.1.mode2.base0 r0.x, 0, r0.x */
INSTR_6XX(c0260201_00c78080, "ldc.offset0.1.nonuniform r0.y, r0.x, r0.y"), /* ldc.1.mode2.base0 r0.y, 0, r0.y */
+#else
+ /* dEQP-GLES31.functional.shaders.opaque_type_indexing.ubo.uniform_fragment */
+ INSTR_6XX(c0260000_00478040, "ldc.offset0.1.uniform r0.x, r0.x, r0.x"), /* ldc.1.mode1.base0 r0.x, 0, r0.x */
+ INSTR_6XX(c0260201_00478040, "ldc.offset0.1.uniform r0.y, r0.x, r0.y"), /* ldc.1.mode1.base0 r0.y, 0, r0.y */
+ /* dEQP-GLES31.functional.shaders.opaque_type_indexing.ubo.dynamically_uniform_fragment */
+ INSTR_6XX(c0260000_00478080, "ldc.offset0.1.nonuniform r0.x, r0.x, r0.x"), /* ldc.1.mode2.base0 r0.x, 0, r0.x */
+ INSTR_6XX(c0260201_00478080, "ldc.offset0.1.nonuniform r0.y, r0.x, r0.y"), /* ldc.1.mode2.base0 r0.y, 0, r0.y */
+#endif
/* custom shaders, loading .x, .y, .z, .w from an array of vec4 in block 0 */
INSTR_6XX(c0260000_00478000, "ldc.offset0.1.imm r0.x, r0.x, 0"), /* ldc.1.mode0.base0 r0.x, r0.x, 0 */
INSTR_6XX(c0260000_00478200, "ldc.offset1.1.imm r0.x, r0.x, 0"), /* ldc.1.mode0.base0 r0.x, r0.x, 0 */