panfrost/midgard/disasm: Handle dest_override generalized
authorAlyssa Rosenzweig <alyssa@rosenzweig.io>
Wed, 1 May 2019 02:00:08 +0000 (02:00 +0000)
committerAlyssa Rosenzweig <alyssa@rosenzweig.io>
Sat, 4 May 2019 19:08:50 +0000 (19:08 +0000)
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
src/gallium/drivers/panfrost/midgard/disassemble.c

index 8466a90b8d6322910cc80d2895af97b7ecce4586..c893bc89a6cacfb0d278af316fcde0501e86ee4d 100644 (file)
@@ -274,6 +274,70 @@ print_immediate(uint16_t imm)
                 printf("#%g", _mesa_half_to_float(imm));
 }
 
+static int
+bits_for_mode(midgard_reg_mode mode)
+{
+        switch (mode) {
+                case midgard_reg_mode_8:
+                        return 8;
+                case midgard_reg_mode_16:
+                        return 16;
+                case midgard_reg_mode_32:
+                        return 32;
+                case midgard_reg_mode_64:
+                        return 64;
+                default:
+                        return 0;
+        }
+}
+
+static void
+print_dest(unsigned reg, midgard_reg_mode mode, midgard_dest_override override, bool out_high)
+{
+        bool overriden = override != midgard_dest_override_none;
+        bool overriden_up = override == midgard_dest_override_upper;
+
+        /* Depending on the mode and override, we determine the type of
+         * destination addressed. Absent an override, we address just the
+         * type of the operation itself, directly at the out_reg register
+         * (scaled if necessary to disambiguate, raised if necessary) */
+
+        unsigned bits = bits_for_mode(mode);
+
+        if (overriden)
+                bits /= 2;
+
+        /* Sanity check the override */
+
+        if (overriden) {
+                bool modeable = (mode == midgard_reg_mode_32) || (mode == midgard_reg_mode_16);
+                bool known = override != 0x3; /* Unused value */
+                bool uppable = !overriden_up || (mode == midgard_reg_mode_32);
+
+                if (!(modeable && known && uppable))
+                        printf("/* do%d */ ", override);
+        }
+
+        switch (mode) {
+                case midgard_reg_mode_8:
+                case midgard_reg_mode_16:
+                        reg = reg * 2 + out_high;
+                        break;
+
+                case midgard_reg_mode_32:
+                        if (overriden) {
+                                reg = (reg * 2) + overriden_up;
+                        }
+
+                        break;
+
+                default:
+                        break;
+        }
+
+        print_reg(reg, bits);
+}
+
 static void
 print_vector_field(const char *name, uint16_t *words, uint16_t reg_word,
                    unsigned tabs)
@@ -329,29 +393,11 @@ print_vector_field(const char *name, uint16_t *words, uint16_t reg_word,
         }
 
         /* First, print the destination */
-        {
-                int out_reg = reg_info->out_reg;
-                unsigned bits = 32;
-
-                if (alu_field->dest_override != midgard_dest_override_none) {
-                        printf("/* do%d */ ", alu_field->dest_override);
-                }
-
-                if (mode == midgard_reg_mode_16) {
-                        bits = 16;
-                        out_reg *= 2;
-                        out_reg += out_high;
-                } else if (mode == midgard_reg_mode_8) {
-                        bits = 8;
-                        out_reg *= 2;
-                        out_reg += out_high;
-                } else if (mode == midgard_reg_mode_64) {
-                        bits = 64;
-                        /* TODO */
-                }
+        print_dest(reg_info->out_reg, mode, alu_field->dest_override, out_high);
 
-                print_reg(out_reg, bits);
-        }
+        /* The semantics here are not totally grokked yet */
+        if (alu_field->dest_override == midgard_dest_override_upper)
+                out_high = true;
 
         if (mask != 0xF) {
                 unsigned i;