panfrost/midgard: Add shifting int modifiers
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Wed, 5 Jun 2019 22:20:26 +0000 (15:20 -0700)
committerAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Mon, 10 Jun 2019 13:50:11 +0000 (06:50 -0700)
As a source modifier, shift allows shifting a value left by the bit
size, useful in conjunction with a greater register mode, for instance
to implement `upsample`. As a concrete example, the following OpenCL:

   ushort hr0 = /* ... */, uint r1 = /* ... */;
   uint r2 = (convert_uint(hr0) << 16) ^ b;

compiles to the following Midgard assembly:

   ixor r, (hr0) << 16, b

In reverse, the ".hi" output modifier shifts the value right by the bit
size, leaving just the carry/overflow at the bottom. To implement *_hi
functions in OpenCL (for <64-bit), we do arithmetic in the 2x higher
mode with the .hi modifier. (For 64-bit, things are hairier, since there
is not an 128-bit int mode).

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
src/gallium/drivers/panfrost/midgard/disassemble.c
src/gallium/drivers/panfrost/midgard/midgard.h

index bf66d1a7da7ed1d79343f738035db649e4eafc7f..7b6ab9ecd68af32cb49b3d7d1bff2148d994f927 100644 (file)
@@ -143,7 +143,14 @@ static char *outmod_names_int[4] = {
         ".isat",
         ".usat",
         "",
-        ".unk3"
+        ".hi"
+};
+
+static char *srcmod_names_int[4] = {
+        "sext(",
+        "zext(",
+        "",
+        "("
 };
 
 static void
@@ -176,20 +183,7 @@ print_vector_src(unsigned src_binary, bool out_high,
         midgard_int_mod int_mod = src->mod;
 
         if (is_int) {
-                switch (int_mod) {
-                        case midgard_int_sign_extend:
-                                printf("sext(");
-                                break;
-                        case midgard_int_zero_extend:
-                                printf("zext(");
-                                break;
-                        case midgard_int_reserved:
-                                printf("unk(");
-                                break;
-                        case midgard_int_normal:
-                                /* Implicit */
-                                break;
-                }
+                printf("%s", srcmod_names_int[int_mod]);
         } else {
                 if (src->mod & MIDGARD_FLOAT_MOD_NEG)
                         printf("-");
@@ -284,7 +278,9 @@ print_vector_src(unsigned src_binary, bool out_high,
 
         /* Since we wrapped with a function-looking thing */
 
-        if ((is_int && (int_mod != midgard_int_normal))
+        if (is_int && int_mod == midgard_int_shift)
+                printf(") << %d", bits);
+        else if ((is_int && (int_mod != midgard_int_normal))
                         || (!is_int && src->mod & MIDGARD_FLOAT_MOD_ABS))
                 printf(")");
 }
index ff853a197333e16a8830f3110e22a29c33459c36..995eaa9a90a2a89c2cdaf0fc6b25ef7cf528077a 100644 (file)
@@ -180,7 +180,7 @@ typedef enum {
         midgard_outmod_int_saturate = 0,
         midgard_outmod_uint_saturate = 1,
         midgard_outmod_int_wrap = 2,
-        /* 0x3 unknown */
+        midgard_outmod_int_high = 3, /* Overflowed portion */
 } midgard_outmod_int;
 
 typedef enum {
@@ -200,7 +200,7 @@ typedef enum {
         midgard_int_sign_extend = 0,
         midgard_int_zero_extend = 1,
         midgard_int_normal = 2,
-        midgard_int_reserved = 3
+        midgard_int_shift = 3
 } midgard_int_mod;
 
 #define MIDGARD_FLOAT_MOD_ABS (1 << 0)