pan/bi: Setup initial clause packing

At the moment, we just iterate the clauses in the post-RA, post-sched IR
and generate a dummy clause corresponding, passing the results to the
disassembler to verify.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4242>
diff --git a/src/panfrost/bifrost/bi_pack.c b/src/panfrost/bifrost/bi_pack.c
new file mode 100644
index 0000000..016046b
--- /dev/null
+++ b/src/panfrost/bifrost/bi_pack.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2020 Collabora, Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "compiler.h"
+
+/* This file contains the final passes of the compiler. Running after
+ * scheduling and RA, the IR is now finalized, so we need to emit it to actual
+ * bits on the wire (as well as fixup branches) */
+
+static uint64_t
+bi_pack_header(bi_clause *clause, bi_clause *next)
+{
+        struct bifrost_header header = {
+                /* stub */
+                .no_end_of_shader = (next != NULL),
+        };
+
+        uint64_t u = 0;
+        memcpy(&u, &header, sizeof(header));
+        return u;
+}
+
+static void
+bi_pack_clause(bi_context *ctx, bi_clause *clause, bi_clause *next,
+                struct util_dynarray *emission)
+{
+        
+        struct bifrost_fmt1 quad_1 = {
+                .tag = BIFROST_FMT1_FINAL,
+                .header = bi_pack_header(clause, next) 
+        };
+
+        util_dynarray_append(emission, struct bifrost_fmt1, quad_1);
+}
+
+static bi_clause *
+bi_next_clause(bi_context *ctx, pan_block *block, bi_clause *clause)
+{
+        /* Try the next clause in this block */
+        if (clause->link.next != &((bi_block *) block)->clauses)
+                return list_first_entry(&(clause->link), bi_clause, link);
+
+        /* Try the next block, or the one after that if it's empty, etc .*/
+        pan_block *next_block = pan_next_block(block);
+
+        bi_foreach_block_from(ctx, next_block, block) {
+                bi_block *blk = (bi_block *) block;
+
+                if (!list_is_empty(&blk->clauses))
+                        return list_first_entry(&(blk->clauses), bi_clause, link);
+        }
+
+        return NULL;
+}
+
+void
+bi_pack(bi_context *ctx, struct util_dynarray *emission)
+{
+        util_dynarray_init(emission, NULL);
+
+        bi_foreach_block(ctx, _block) {
+                bi_block *block = (bi_block *) _block;
+
+                bi_foreach_clause_in_block(block, clause) {
+                        bi_clause *next = bi_next_clause(ctx, _block, clause);
+                        bi_pack_clause(ctx, clause, next, emission);
+                }
+        }
+}
diff --git a/src/panfrost/bifrost/bifrost.h b/src/panfrost/bifrost/bifrost.h
index d8a1cff..959c951 100644
--- a/src/panfrost/bifrost/bifrost.h
+++ b/src/panfrost/bifrost/bifrost.h
@@ -321,4 +321,18 @@
         unsigned op : 5;
 };
 
+/* Clause packing */
+
+struct bifrost_fmt1 {
+        unsigned ins_0 : 3;
+        unsigned tag : 5;
+        uint64_t ins_1 : 64;
+        unsigned ins_2 : 11;
+        uint64_t header : 45;
+} __attribute__((packed));
+
+#define BIFROST_FMT1_INSTRUCTIONS    0b00101
+#define BIFROST_FMT1_FINAL           0b01001
+#define BIFROST_FMT1_CONSTANTS       0b00001
+
 #endif
diff --git a/src/panfrost/bifrost/bifrost_compile.c b/src/panfrost/bifrost/bifrost_compile.c
index f25f742..d19cc65 100644
--- a/src/panfrost/bifrost/bifrost_compile.c
+++ b/src/panfrost/bifrost/bifrost_compile.c
@@ -865,6 +865,8 @@
         bi_schedule(ctx);
         bi_register_allocate(ctx);
         bi_print_shader(ctx, stdout);
+        bi_pack(ctx, &program->compiled);
+        disassemble_bifrost(stdout, program->compiled.data, program->compiled.size, true);
 
         ralloc_free(ctx);
 }
diff --git a/src/panfrost/bifrost/compiler.h b/src/panfrost/bifrost/compiler.h
index 499fa9a..9ff728c 100644
--- a/src/panfrost/bifrost/compiler.h
+++ b/src/panfrost/bifrost/compiler.h
@@ -494,6 +494,12 @@
         return list_first_entry(&(ins->link), bi_instruction, link);
 }
 
+static inline pan_block *
+pan_next_block(pan_block *block)
+{
+        return list_first_entry(&(block->link), pan_block, link);
+}
+
 /* BIR manipulation */
 
 bool bi_has_outmod(bi_instruction *ins);
@@ -517,4 +523,8 @@
 void bi_invalidate_liveness(bi_context *ctx);
 bool bi_is_live_after(bi_context *ctx, bi_block *block, bi_instruction *start, int src);
 
+/* Code emit */
+
+void bi_pack(bi_context *ctx, struct util_dynarray *emission);
+
 #endif
diff --git a/src/panfrost/bifrost/meson.build b/src/panfrost/bifrost/meson.build
index 8695526..8f14d25 100644
--- a/src/panfrost/bifrost/meson.build
+++ b/src/panfrost/bifrost/meson.build
@@ -24,6 +24,7 @@
   'bi_liveness.c',
   'bi_print.c',
   'bi_opt_dce.c',
+  'bi_pack.c',
   'bi_ra.c',
   'bi_schedule.c',
   'bi_tables.c',