pan/mdg: Refactor texture op/mode handling
[mesa.git] / src / panfrost / midgard / helpers.h
index b86001182602633a3d5a71865f07fe420fab4399..e0a595c2c3d02d8d29f284fddb497565d5e51fd7 100644 (file)
@@ -23,6 +23,7 @@
 #define __MDG_HELPERS_H
 
 #include "util/macros.h"
+#include <stdio.h>
 #include <string.h>
 
 #define OP_IS_LOAD_VARY_F(op) (\
                 op == midgard_alu_op_fcsel \
         )
 
-#define OP_IS_DERIVATIVE(op) ( \
-                op == TEXTURE_OP_DFDX || \
-                op == TEXTURE_OP_DFDY \
+#define OP_IS_UNSIGNED_CMP(op) ( \
+                op == midgard_alu_op_ult || \
+                op == midgard_alu_op_ule \
+        )
+
+#define OP_IS_INTEGER_CMP(op) ( \
+                op == midgard_alu_op_ieq || \
+                op == midgard_alu_op_ine || \
+                op == midgard_alu_op_ilt || \
+                op == midgard_alu_op_ile || \
+                OP_IS_UNSIGNED_CMP(op) \
         )
 
 /* ALU control words are single bit fields with a lot of space */
 /* Does the op convert types between int- and float- space (i2f/f2u/etc) */
 #define OP_TYPE_CONVERT (1 << 4)
 
+/* Is this opcode the first in a f2x (rte, rtz, rtn, rtp) sequence? If so,
+ * takes a roundmode argument in the IR. This has the semantic of rounding the
+ * source (it's all fused in), which is why it doesn't necessarily make sense
+ * for i2f (though folding there might be necessary for OpenCL reasons). Comes
+ * up in format conversion, i.e. f2u_rte */
+#define MIDGARD_ROUNDS (1 << 5)
+
 /* Vector-independant shorthands for the above; these numbers are arbitrary and
  * not from the ISA. Convert to the above with unit_enum_to_midgard */
 
 #define UNIT_ADD 1
 #define UNIT_LUT 2
 
-/* 4-bit type tags */
-
-#define TAG_TEXTURE_4_VTX 0x2
-#define TAG_TEXTURE_4 0x3
-#define TAG_LOAD_STORE_4 0x5
-#define TAG_ALU_4 0x8
-#define TAG_ALU_8 0x9
-#define TAG_ALU_12 0xA
-#define TAG_ALU_16 0xB
-
-static inline int
-quadword_size(int tag)
-{
-        switch (tag) {
-        case TAG_ALU_4:
-        case TAG_LOAD_STORE_4:
-        case TAG_TEXTURE_4:
-        case TAG_TEXTURE_4_VTX:
-                return 1;
-        case TAG_ALU_8:
-                return 2;
-        case TAG_ALU_12:
-                return 3;
-        case TAG_ALU_16:
-                return 4;
-        default:
-                unreachable("Unknown tag");
-        }
-}
-
-#define IS_ALU(tag) (tag == TAG_ALU_4 || tag == TAG_ALU_8 ||  \
-                    tag == TAG_ALU_12 || tag == TAG_ALU_16)
+#define IS_ALU(tag) (tag >= TAG_ALU_4)
 
 /* Special register aliases */
 
@@ -153,6 +138,9 @@ quadword_size(int tag)
 /* Uniforms are begin at (REGISTER_UNIFORMS - uniform_count) */
 #define REGISTER_UNIFORMS 24
 
+/* r24 and r25 are special registers that only exist during the pipeline,
+ * by using them when we don't care about the register we skip a roundtrip
+ * to the register file. */
 #define REGISTER_UNUSED 24
 #define REGISTER_CONSTANT 26
 #define REGISTER_LDST_BASE 26
@@ -161,7 +149,6 @@ quadword_size(int tag)
 
 /* SSA helper aliases to mimic the registers. */
 
-#define SSA_UNUSED ~0
 #define SSA_FIXED_SHIFT 24
 #define SSA_FIXED_REGISTER(reg) (((1 + (reg)) << SSA_FIXED_SHIFT) | 1)
 #define SSA_REG_FROM_FIXED(reg) ((((reg) & ~1) >> SSA_FIXED_SHIFT) - 1)
@@ -173,6 +160,7 @@ quadword_size(int tag)
 #define COMPONENT_W 0x3
 
 #define SWIZZLE_IDENTITY { \
+        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, \
         { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, \
         { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, \
         { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } \
@@ -182,6 +170,7 @@ quadword_size(int tag)
         { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0 }, \
         { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0 }, \
         { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0 }, \
+        { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0 }, \
 }
 
 static inline unsigned
@@ -228,6 +217,11 @@ struct mir_ldst_op_props {
         unsigned props;
 };
 
+struct mir_tag_props {
+        const char *name;
+        unsigned size;
+};
+
 /* Lower 2-bits are a midgard_reg_mode */
 #define GET_LDST_SIZE(c) (c & 3)
 
@@ -241,20 +235,25 @@ struct mir_ldst_op_props {
  * its mask is 0 */
 #define LDST_SIDE_FX (1 << 4)
 
+/* Computes an address according to indirects/zext/shift/etc */
+#define LDST_ADDRESS (1 << 5)
+
 /* This file is common, so don't define the tables themselves. #include
  * midgard_op.h if you need that, or edit midgard_ops.c directly */
 
-/* Duplicate bits to convert a 4-bit writemask to duplicated 8-bit format,
- * which is used for 32-bit vector units */
+/* Duplicate bits to convert a per-component to duplicated 8-bit format,
+ * which is used for vector units */
 
 static inline unsigned
-expand_writemask_32(unsigned mask)
+expand_writemask(unsigned mask, unsigned log2_channels)
 {
         unsigned o = 0;
+        unsigned factor = 8 >> log2_channels;
+        unsigned expanded = (1 << factor) - 1;
 
-        for (int i = 0; i < 4; ++i)
+        for (unsigned i = 0; i < (1 << log2_channels); ++i)
                 if (mask & (1 << i))
-                        o |= (3 << (2 * i));
+                        o |= (expanded << (factor * i));
 
         return o;
 }
@@ -306,9 +305,19 @@ mir_is_simple_swizzle(unsigned *swizzle, unsigned mask)
 /* Packs a load/store argument */
 
 static inline uint8_t
-midgard_ldst_reg(unsigned reg, unsigned component)
+midgard_ldst_reg(unsigned reg, unsigned component, unsigned size)
 {
         assert((reg == REGISTER_LDST_BASE) || (reg == REGISTER_LDST_BASE + 1));
+        assert(size == 16 || size == 32 || size == 64);
+
+        /* Shift so everything is in terms of 32-bit units */
+        if (size == 64) {
+                assert(component < 2);
+                component <<= 1;
+        } else if (size == 16) {
+                assert((component & 1) == 0);
+                component >>= 1;
+        }
 
         midgard_ldst_register_select sel = {
                 .component = component,
@@ -321,22 +330,19 @@ midgard_ldst_reg(unsigned reg, unsigned component)
         return packed;
 }
 
-/* Unpacks a load/store argument */
-
-static inline midgard_ldst_register_select
-midgard_ldst_select(uint8_t u)
+static inline bool
+midgard_is_branch_unit(unsigned unit)
 {
-        midgard_ldst_register_select sel;
-        memcpy(&sel, &u, sizeof(u));
-        return sel;
+        return (unit == ALU_ENAB_BRANCH) || (unit == ALU_ENAB_BR_COMPACT);
 }
 
-static inline uint8_t
-midgard_ldst_pack(midgard_ldst_register_select sel)
-{
-        uint8_t packed;
-        memcpy(&packed, &sel, sizeof(packed));
-        return packed;
-}
+/* Packs ALU mod argument */
+struct midgard_instruction;
+unsigned mir_pack_mod(struct midgard_instruction *ins, unsigned i, bool scalar);
+
+void
+mir_print_constant_component(FILE *fp, const midgard_constants *consts,
+                             unsigned c, midgard_reg_mode reg_mode, bool half,
+                             unsigned mod, midgard_alu_op op);
 
 #endif