1b8e80941Smrg/* Author(s):
2b8e80941Smrg *   Connor Abbott
3b8e80941Smrg *   Alyssa Rosenzweig
4b8e80941Smrg *
5b8e80941Smrg * Copyright (c) 2013 Connor Abbott (connor@abbott.cx)
6b8e80941Smrg * Copyright (c) 2018 Alyssa Rosenzweig (alyssa@rosenzweig.io)
7b8e80941Smrg *
8b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a copy
9b8e80941Smrg * of this software and associated documentation files (the "Software"), to deal
10b8e80941Smrg * in the Software without restriction, including without limitation the rights
11b8e80941Smrg * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12b8e80941Smrg * copies of the Software, and to permit persons to whom the Software is
13b8e80941Smrg * furnished to do so, subject to the following conditions:
14b8e80941Smrg *
15b8e80941Smrg * The above copyright notice and this permission notice shall be included in
16b8e80941Smrg * all copies or substantial portions of the Software.
17b8e80941Smrg *
18b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21b8e80941Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23b8e80941Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24b8e80941Smrg * THE SOFTWARE.
25b8e80941Smrg */
26b8e80941Smrg
27b8e80941Smrg#include <stdio.h>
28b8e80941Smrg#include <stdint.h>
29b8e80941Smrg#include <assert.h>
30b8e80941Smrg#include <inttypes.h>
31b8e80941Smrg#include <string.h>
32b8e80941Smrg#include "midgard.h"
33b8e80941Smrg#include "midgard-parse.h"
34b8e80941Smrg#include "disassemble.h"
35b8e80941Smrg#include "helpers.h"
36b8e80941Smrg#include "util/half_float.h"
37b8e80941Smrg
38b8e80941Smrg#define DEFINE_CASE(define, str) case define: { printf(str); break; }
39b8e80941Smrg
40b8e80941Smrgstatic bool is_instruction_int = false;
41b8e80941Smrg
42b8e80941Smrgstatic void
43b8e80941Smrgprint_alu_opcode(midgard_alu_op op)
44b8e80941Smrg{
45b8e80941Smrg        bool int_op = false;
46b8e80941Smrg
47b8e80941Smrg        if (alu_opcode_props[op].name) {
48b8e80941Smrg                printf("%s", alu_opcode_props[op].name);
49b8e80941Smrg
50b8e80941Smrg                int_op = midgard_is_integer_op(op);
51b8e80941Smrg        } else
52b8e80941Smrg                printf("alu_op_%02X", op);
53b8e80941Smrg
54b8e80941Smrg        /* For constant analysis */
55b8e80941Smrg        is_instruction_int = int_op;
56b8e80941Smrg}
57b8e80941Smrg
58b8e80941Smrgstatic void
59b8e80941Smrgprint_ld_st_opcode(midgard_load_store_op op)
60b8e80941Smrg{
61b8e80941Smrg        if (load_store_opcode_names[op])
62b8e80941Smrg                printf("%s", load_store_opcode_names[op]);
63b8e80941Smrg        else
64b8e80941Smrg                printf("ldst_op_%02X", op);
65b8e80941Smrg}
66b8e80941Smrg
67b8e80941Smrgstatic bool is_embedded_constant_half = false;
68b8e80941Smrgstatic bool is_embedded_constant_int = false;
69b8e80941Smrg
70b8e80941Smrgstatic char
71b8e80941Smrgprefix_for_bits(unsigned bits)
72b8e80941Smrg{
73b8e80941Smrg        switch (bits) {
74b8e80941Smrg                case 8:
75b8e80941Smrg                        return 'q';
76b8e80941Smrg                case 16:
77b8e80941Smrg                        return 'h';
78b8e80941Smrg                case 64:
79b8e80941Smrg                        return 'd';
80b8e80941Smrg                default:
81b8e80941Smrg                        return 0;
82b8e80941Smrg        }
83b8e80941Smrg}
84b8e80941Smrg
85b8e80941Smrgstatic void
86b8e80941Smrgprint_reg(unsigned reg, unsigned bits)
87b8e80941Smrg{
88b8e80941Smrg        /* Perform basic static analysis for expanding constants correctly */
89b8e80941Smrg
90b8e80941Smrg        if ((bits == 16) && (reg >> 1) == 26) {
91b8e80941Smrg                is_embedded_constant_half = true;
92b8e80941Smrg                is_embedded_constant_int = is_instruction_int;
93b8e80941Smrg        } else if ((bits == 32) && reg == 26) {
94b8e80941Smrg                is_embedded_constant_int = is_instruction_int;
95b8e80941Smrg        } else if (bits == 8) {
96b8e80941Smrg                /* TODO */
97b8e80941Smrg        } else if (bits == 64) {
98b8e80941Smrg                /* TODO */
99b8e80941Smrg        }
100b8e80941Smrg
101b8e80941Smrg        char prefix = prefix_for_bits(bits);
102b8e80941Smrg
103b8e80941Smrg        if (prefix)
104b8e80941Smrg                putchar(prefix);
105b8e80941Smrg
106b8e80941Smrg        printf("r%u", reg);
107b8e80941Smrg}
108b8e80941Smrg
109b8e80941Smrgstatic char *outmod_names[4] = {
110b8e80941Smrg        "",
111b8e80941Smrg        ".pos",
112b8e80941Smrg        ".int",
113b8e80941Smrg        ".sat"
114b8e80941Smrg};
115b8e80941Smrg
116b8e80941Smrgstatic void
117b8e80941Smrgprint_outmod(midgard_outmod outmod)
118b8e80941Smrg{
119b8e80941Smrg        printf("%s", outmod_names[outmod]);
120b8e80941Smrg}
121b8e80941Smrg
122b8e80941Smrgstatic void
123b8e80941Smrgprint_quad_word(uint32_t *words, unsigned tabs)
124b8e80941Smrg{
125b8e80941Smrg        unsigned i;
126b8e80941Smrg
127b8e80941Smrg        for (i = 0; i < 4; i++)
128b8e80941Smrg                printf("0x%08X%s ", words[i], i == 3 ? "" : ",");
129b8e80941Smrg
130b8e80941Smrg        printf("\n");
131b8e80941Smrg}
132b8e80941Smrg
133b8e80941Smrgstatic void
134b8e80941Smrgprint_vector_src(unsigned src_binary, bool out_high,
135b8e80941Smrg                 midgard_reg_mode mode, unsigned reg,
136b8e80941Smrg                 bool is_int)
137b8e80941Smrg{
138b8e80941Smrg        midgard_vector_alu_src *src = (midgard_vector_alu_src *)&src_binary;
139b8e80941Smrg
140b8e80941Smrg        /* Modifiers change meaning depending on the op's context */
141b8e80941Smrg
142b8e80941Smrg        midgard_int_mod int_mod = src->mod;
143b8e80941Smrg
144b8e80941Smrg        if (is_int) {
145b8e80941Smrg                switch (int_mod) {
146b8e80941Smrg                        case midgard_int_sign_extend:
147b8e80941Smrg                                printf("sext(");
148b8e80941Smrg                                break;
149b8e80941Smrg                        case midgard_int_zero_extend:
150b8e80941Smrg                                printf("zext(");
151b8e80941Smrg                                break;
152b8e80941Smrg                        case midgard_int_reserved:
153b8e80941Smrg                                printf("unk(");
154b8e80941Smrg                                break;
155b8e80941Smrg                        case midgard_int_normal:
156b8e80941Smrg                                /* Implicit */
157b8e80941Smrg                                break;
158b8e80941Smrg                }
159b8e80941Smrg        } else {
160b8e80941Smrg                if (src->mod & MIDGARD_FLOAT_MOD_NEG)
161b8e80941Smrg                        printf("-");
162b8e80941Smrg
163b8e80941Smrg                if (src->mod & MIDGARD_FLOAT_MOD_ABS)
164b8e80941Smrg                        printf("abs(");
165b8e80941Smrg        }
166b8e80941Smrg
167b8e80941Smrg        //register
168b8e80941Smrg
169b8e80941Smrg        if (mode == midgard_reg_mode_8) {
170b8e80941Smrg                if (src->half)
171b8e80941Smrg                        printf(" /* half */ ");
172b8e80941Smrg
173b8e80941Smrg                unsigned quarter_reg = reg * 2;
174b8e80941Smrg
175b8e80941Smrg                if (out_high) {
176b8e80941Smrg                        if (!src->rep_low)
177b8e80941Smrg                                quarter_reg++;
178b8e80941Smrg
179b8e80941Smrg                        if (src->rep_high)
180b8e80941Smrg                                printf(" /* rep_high */ ");
181b8e80941Smrg                } else {
182b8e80941Smrg                        if (src->rep_high)
183b8e80941Smrg                                quarter_reg++;
184b8e80941Smrg
185b8e80941Smrg                        if (src->rep_low)
186b8e80941Smrg                                printf(" /* rep_low */ ");
187b8e80941Smrg                }
188b8e80941Smrg
189b8e80941Smrg                print_reg(quarter_reg, 8);
190b8e80941Smrg        } else if (mode == midgard_reg_mode_16) {
191b8e80941Smrg                if (src->half)
192b8e80941Smrg                        printf(" /* half */ ");
193b8e80941Smrg
194b8e80941Smrg                unsigned half_reg = reg * 2;
195b8e80941Smrg
196b8e80941Smrg                if (out_high) {
197b8e80941Smrg                        if (!src->rep_low)
198b8e80941Smrg                                half_reg++;
199b8e80941Smrg
200b8e80941Smrg                        if (src->rep_high)
201b8e80941Smrg                                printf(" /* rep_high */ ");
202b8e80941Smrg                } else {
203b8e80941Smrg                        if (src->rep_high)
204b8e80941Smrg                                half_reg++;
205b8e80941Smrg
206b8e80941Smrg                        if (src->rep_low)
207b8e80941Smrg                                printf(" /* rep_low */ ");
208b8e80941Smrg                }
209b8e80941Smrg
210b8e80941Smrg                print_reg(half_reg, 16);
211b8e80941Smrg        } else if (mode == midgard_reg_mode_32) {
212b8e80941Smrg                if (src->rep_high)
213b8e80941Smrg                        printf(" /* rep_high */ ");
214b8e80941Smrg
215b8e80941Smrg                if (src->half)
216b8e80941Smrg                        print_reg(reg * 2 + src->rep_low, 16);
217b8e80941Smrg                else {
218b8e80941Smrg                        if (src->rep_low)
219b8e80941Smrg                                printf(" /* rep_low */ ");
220b8e80941Smrg
221b8e80941Smrg                        print_reg(reg, 32);
222b8e80941Smrg                }
223b8e80941Smrg        } else if (mode == midgard_reg_mode_64) {
224b8e80941Smrg                if (src->rep_high)
225b8e80941Smrg                        printf(" /* rep_high */ ");
226b8e80941Smrg
227b8e80941Smrg                if (src->rep_low)
228b8e80941Smrg                        printf(" /* rep_low */ ");
229b8e80941Smrg
230b8e80941Smrg                if (src->half)
231b8e80941Smrg                        printf(" /* half */ ");
232b8e80941Smrg
233b8e80941Smrg                if (out_high)
234b8e80941Smrg                        printf(" /* out_high */ ");
235b8e80941Smrg
236b8e80941Smrg                print_reg(reg, 64);
237b8e80941Smrg        }
238b8e80941Smrg
239b8e80941Smrg        //swizzle
240b8e80941Smrg
241b8e80941Smrg        if (src->swizzle != 0xE4) { //default swizzle
242b8e80941Smrg                unsigned i;
243b8e80941Smrg                static const char c[4] = "xyzw";
244b8e80941Smrg
245b8e80941Smrg                printf(".");
246b8e80941Smrg
247b8e80941Smrg                for (i = 0; i < 4; i++)
248b8e80941Smrg                        printf("%c", c[(src->swizzle >> (i * 2)) & 3]);
249b8e80941Smrg        }
250b8e80941Smrg
251b8e80941Smrg        /* Since we wrapped with a function-looking thing */
252b8e80941Smrg
253b8e80941Smrg        if ((is_int && (int_mod != midgard_int_normal))
254b8e80941Smrg                        || (!is_int && src->mod & MIDGARD_FLOAT_MOD_ABS))
255b8e80941Smrg                printf(")");
256b8e80941Smrg}
257b8e80941Smrg
258b8e80941Smrgstatic uint16_t
259b8e80941Smrgdecode_vector_imm(unsigned src2_reg, unsigned imm)
260b8e80941Smrg{
261b8e80941Smrg        uint16_t ret;
262b8e80941Smrg        ret = src2_reg << 11;
263b8e80941Smrg        ret |= (imm & 0x7) << 8;
264b8e80941Smrg        ret |= (imm >> 3) & 0xFF;
265b8e80941Smrg        return ret;
266b8e80941Smrg}
267b8e80941Smrg
268b8e80941Smrgstatic void
269b8e80941Smrgprint_immediate(uint16_t imm)
270b8e80941Smrg{
271b8e80941Smrg        if (is_instruction_int)
272b8e80941Smrg                printf("#%d", imm);
273b8e80941Smrg        else
274b8e80941Smrg                printf("#%g", _mesa_half_to_float(imm));
275b8e80941Smrg}
276b8e80941Smrg
277b8e80941Smrgstatic int
278b8e80941Smrgbits_for_mode(midgard_reg_mode mode)
279b8e80941Smrg{
280b8e80941Smrg        switch (mode) {
281b8e80941Smrg                case midgard_reg_mode_8:
282b8e80941Smrg                        return 8;
283b8e80941Smrg                case midgard_reg_mode_16:
284b8e80941Smrg                        return 16;
285b8e80941Smrg                case midgard_reg_mode_32:
286b8e80941Smrg                        return 32;
287b8e80941Smrg                case midgard_reg_mode_64:
288b8e80941Smrg                        return 64;
289b8e80941Smrg                default:
290b8e80941Smrg                        return 0;
291b8e80941Smrg        }
292b8e80941Smrg}
293b8e80941Smrg
294b8e80941Smrgstatic void
295b8e80941Smrgprint_dest(unsigned reg, midgard_reg_mode mode, midgard_dest_override override, bool out_high)
296b8e80941Smrg{
297b8e80941Smrg        bool overriden = override != midgard_dest_override_none;
298b8e80941Smrg        bool overriden_up = override == midgard_dest_override_upper;
299b8e80941Smrg
300b8e80941Smrg        /* Depending on the mode and override, we determine the type of
301b8e80941Smrg         * destination addressed. Absent an override, we address just the
302b8e80941Smrg         * type of the operation itself, directly at the out_reg register
303b8e80941Smrg         * (scaled if necessary to disambiguate, raised if necessary) */
304b8e80941Smrg
305b8e80941Smrg        unsigned bits = bits_for_mode(mode);
306b8e80941Smrg
307b8e80941Smrg        if (overriden)
308b8e80941Smrg                bits /= 2;
309b8e80941Smrg
310b8e80941Smrg        /* Sanity check the override */
311b8e80941Smrg
312b8e80941Smrg        if (overriden) {
313b8e80941Smrg                bool modeable = (mode == midgard_reg_mode_32) || (mode == midgard_reg_mode_16);
314b8e80941Smrg                bool known = override != 0x3; /* Unused value */
315b8e80941Smrg                bool uppable = !overriden_up || (mode == midgard_reg_mode_32);
316b8e80941Smrg
317b8e80941Smrg                if (!(modeable && known && uppable))
318b8e80941Smrg                        printf("/* do%d */ ", override);
319b8e80941Smrg        }
320b8e80941Smrg
321b8e80941Smrg        switch (mode) {
322b8e80941Smrg                case midgard_reg_mode_8:
323b8e80941Smrg                case midgard_reg_mode_16:
324b8e80941Smrg                        reg = reg * 2 + out_high;
325b8e80941Smrg                        break;
326b8e80941Smrg
327b8e80941Smrg                case midgard_reg_mode_32:
328b8e80941Smrg                        if (overriden) {
329b8e80941Smrg                                reg = (reg * 2) + overriden_up;
330b8e80941Smrg                        }
331b8e80941Smrg
332b8e80941Smrg                        break;
333b8e80941Smrg
334b8e80941Smrg                default:
335b8e80941Smrg                        break;
336b8e80941Smrg        }
337b8e80941Smrg
338b8e80941Smrg        print_reg(reg, bits);
339b8e80941Smrg}
340b8e80941Smrg
341b8e80941Smrgstatic void
342b8e80941Smrgprint_vector_field(const char *name, uint16_t *words, uint16_t reg_word,
343b8e80941Smrg                   unsigned tabs)
344b8e80941Smrg{
345b8e80941Smrg        midgard_reg_info *reg_info = (midgard_reg_info *)&reg_word;
346b8e80941Smrg        midgard_vector_alu *alu_field = (midgard_vector_alu *) words;
347b8e80941Smrg        midgard_reg_mode mode = alu_field->reg_mode;
348b8e80941Smrg
349b8e80941Smrg        /* For now, prefix instruction names with their unit, until we
350b8e80941Smrg         * understand how this works on a deeper level */
351b8e80941Smrg        printf("%s.", name);
352b8e80941Smrg
353b8e80941Smrg        print_alu_opcode(alu_field->op);
354b8e80941Smrg        print_outmod(alu_field->outmod);
355b8e80941Smrg        printf(" ");
356b8e80941Smrg
357b8e80941Smrg        bool out_high = false;
358b8e80941Smrg        unsigned mask;
359b8e80941Smrg
360b8e80941Smrg        if (mode == midgard_reg_mode_16
361b8e80941Smrg                || mode == midgard_reg_mode_8) {
362b8e80941Smrg
363b8e80941Smrg                /* For partial views, the mask denotes which adjacent register
364b8e80941Smrg                 * is used as the window into the larger register */
365b8e80941Smrg
366b8e80941Smrg                if (alu_field->mask & 0xF) {
367b8e80941Smrg                        out_high = false;
368b8e80941Smrg
369b8e80941Smrg                        if ((alu_field->mask & 0xF0))
370b8e80941Smrg                                printf("/* %X */ ", alu_field->mask);
371b8e80941Smrg
372b8e80941Smrg                        mask = alu_field->mask;
373b8e80941Smrg                } else {
374b8e80941Smrg                        out_high = true;
375b8e80941Smrg                        mask = alu_field->mask >> 4;
376b8e80941Smrg                }
377b8e80941Smrg        } else {
378b8e80941Smrg                /* For full 32-bit, every other bit is duplicated, so we only
379b8e80941Smrg                 * pick every other to find the effective mask */
380b8e80941Smrg
381b8e80941Smrg                mask = alu_field->mask & 1;
382b8e80941Smrg                mask |= (alu_field->mask & 4) >> 1;
383b8e80941Smrg                mask |= (alu_field->mask & 16) >> 2;
384b8e80941Smrg                mask |= (alu_field->mask & 64) >> 3;
385b8e80941Smrg
386b8e80941Smrg                /* ... but verify! */
387b8e80941Smrg
388b8e80941Smrg                unsigned checked = alu_field->mask & 0x55;
389b8e80941Smrg                unsigned opposite = alu_field->mask & 0xAA;
390b8e80941Smrg
391b8e80941Smrg                if ((checked << 1) != opposite)
392b8e80941Smrg                        printf("/* %X */ ", alu_field->mask);
393b8e80941Smrg        }
394b8e80941Smrg
395b8e80941Smrg        /* First, print the destination */
396b8e80941Smrg        print_dest(reg_info->out_reg, mode, alu_field->dest_override, out_high);
397b8e80941Smrg
398b8e80941Smrg        /* The semantics here are not totally grokked yet */
399b8e80941Smrg        if (alu_field->dest_override == midgard_dest_override_upper)
400b8e80941Smrg                out_high = true;
401b8e80941Smrg
402b8e80941Smrg        if (mask != 0xF) {
403b8e80941Smrg                unsigned i;
404b8e80941Smrg                static const char c[4] = "xyzw";
405b8e80941Smrg
406b8e80941Smrg                printf(".");
407b8e80941Smrg
408b8e80941Smrg                for (i = 0; i < 4; i++)
409b8e80941Smrg                        if (mask & (1 << i))
410b8e80941Smrg                                printf("%c", c[i]);
411b8e80941Smrg        }
412b8e80941Smrg
413b8e80941Smrg        printf(", ");
414b8e80941Smrg
415b8e80941Smrg        bool is_int = midgard_is_integer_op(alu_field->op);
416b8e80941Smrg        print_vector_src(alu_field->src1, out_high, mode, reg_info->src1_reg, is_int);
417b8e80941Smrg
418b8e80941Smrg        printf(", ");
419b8e80941Smrg
420b8e80941Smrg        if (reg_info->src2_imm) {
421b8e80941Smrg                uint16_t imm = decode_vector_imm(reg_info->src2_reg, alu_field->src2 >> 2);
422b8e80941Smrg                print_immediate(imm);
423b8e80941Smrg        } else {
424b8e80941Smrg                print_vector_src(alu_field->src2, out_high, mode,
425b8e80941Smrg                                 reg_info->src2_reg, is_int);
426b8e80941Smrg        }
427b8e80941Smrg
428b8e80941Smrg        printf("\n");
429b8e80941Smrg}
430b8e80941Smrg
431b8e80941Smrgstatic void
432b8e80941Smrgprint_scalar_src(unsigned src_binary, unsigned reg)
433b8e80941Smrg{
434b8e80941Smrg        midgard_scalar_alu_src *src = (midgard_scalar_alu_src *)&src_binary;
435b8e80941Smrg
436b8e80941Smrg        if (src->negate)
437b8e80941Smrg                printf("-");
438b8e80941Smrg
439b8e80941Smrg        if (src->abs)
440b8e80941Smrg                printf("abs(");
441b8e80941Smrg
442b8e80941Smrg        if (src->full)
443b8e80941Smrg                print_reg(reg, 32);
444b8e80941Smrg        else
445b8e80941Smrg                print_reg(reg * 2 + (src->component >> 2), 16);
446b8e80941Smrg
447b8e80941Smrg        static const char c[4] = "xyzw";
448b8e80941Smrg        \
449b8e80941Smrg        printf(".%c", c[src->full ? src->component >> 1 : src->component & 3]);
450b8e80941Smrg
451b8e80941Smrg        if (src->abs)
452b8e80941Smrg                printf(")");
453b8e80941Smrg
454b8e80941Smrg}
455b8e80941Smrg
456b8e80941Smrgstatic uint16_t
457b8e80941Smrgdecode_scalar_imm(unsigned src2_reg, unsigned imm)
458b8e80941Smrg{
459b8e80941Smrg        uint16_t ret;
460b8e80941Smrg        ret = src2_reg << 11;
461b8e80941Smrg        ret |= (imm & 3) << 9;
462b8e80941Smrg        ret |= (imm & 4) << 6;
463b8e80941Smrg        ret |= (imm & 0x38) << 2;
464b8e80941Smrg        ret |= imm >> 6;
465b8e80941Smrg        return ret;
466b8e80941Smrg}
467b8e80941Smrg
468b8e80941Smrgstatic void
469b8e80941Smrgprint_scalar_field(const char *name, uint16_t *words, uint16_t reg_word,
470b8e80941Smrg                   unsigned tabs)
471b8e80941Smrg{
472b8e80941Smrg        midgard_reg_info *reg_info = (midgard_reg_info *)&reg_word;
473b8e80941Smrg        midgard_scalar_alu *alu_field = (midgard_scalar_alu *) words;
474b8e80941Smrg
475b8e80941Smrg        if (alu_field->unknown)
476b8e80941Smrg                printf("scalar ALU unknown bit set\n");
477b8e80941Smrg
478b8e80941Smrg        printf("%s.", name);
479b8e80941Smrg        print_alu_opcode(alu_field->op);
480b8e80941Smrg        print_outmod(alu_field->outmod);
481b8e80941Smrg        printf(" ");
482b8e80941Smrg
483b8e80941Smrg        if (alu_field->output_full)
484b8e80941Smrg                print_reg(reg_info->out_reg, 32);
485b8e80941Smrg        else
486b8e80941Smrg                print_reg(reg_info->out_reg * 2 + (alu_field->output_component >> 2),
487b8e80941Smrg                          16);
488b8e80941Smrg
489b8e80941Smrg        static const char c[4] = "xyzw";
490b8e80941Smrg        printf(".%c, ",
491b8e80941Smrg               c[alu_field->output_full ? alu_field->output_component >> 1 :
492b8e80941Smrg                                        alu_field->output_component & 3]);
493b8e80941Smrg
494b8e80941Smrg        print_scalar_src(alu_field->src1, reg_info->src1_reg);
495b8e80941Smrg
496b8e80941Smrg        printf(", ");
497b8e80941Smrg
498b8e80941Smrg        if (reg_info->src2_imm) {
499b8e80941Smrg                uint16_t imm = decode_scalar_imm(reg_info->src2_reg,
500b8e80941Smrg                                                 alu_field->src2);
501b8e80941Smrg                print_immediate(imm);
502b8e80941Smrg        } else
503b8e80941Smrg                print_scalar_src(alu_field->src2, reg_info->src2_reg);
504b8e80941Smrg
505b8e80941Smrg        printf("\n");
506b8e80941Smrg}
507b8e80941Smrg
508b8e80941Smrgstatic void
509b8e80941Smrgprint_branch_op(int op)
510b8e80941Smrg{
511b8e80941Smrg        switch (op) {
512b8e80941Smrg        case midgard_jmp_writeout_op_branch_uncond:
513b8e80941Smrg                printf("uncond.");
514b8e80941Smrg                break;
515b8e80941Smrg
516b8e80941Smrg        case midgard_jmp_writeout_op_branch_cond:
517b8e80941Smrg                printf("cond.");
518b8e80941Smrg                break;
519b8e80941Smrg
520b8e80941Smrg        case midgard_jmp_writeout_op_writeout:
521b8e80941Smrg                printf("write.");
522b8e80941Smrg                break;
523b8e80941Smrg
524b8e80941Smrg        case midgard_jmp_writeout_op_tilebuffer_pending:
525b8e80941Smrg                printf("tilebuffer.");
526b8e80941Smrg                break;
527b8e80941Smrg
528b8e80941Smrg        case midgard_jmp_writeout_op_discard:
529b8e80941Smrg                printf("discard.");
530b8e80941Smrg                break;
531b8e80941Smrg
532b8e80941Smrg        default:
533b8e80941Smrg                printf("unk%d.", op);
534b8e80941Smrg                break;
535b8e80941Smrg        }
536b8e80941Smrg}
537b8e80941Smrg
538b8e80941Smrgstatic void
539b8e80941Smrgprint_branch_cond(int cond)
540b8e80941Smrg{
541b8e80941Smrg        switch (cond) {
542b8e80941Smrg        case midgard_condition_write0:
543b8e80941Smrg                printf("write0");
544b8e80941Smrg                break;
545b8e80941Smrg
546b8e80941Smrg        case midgard_condition_false:
547b8e80941Smrg                printf("false");
548b8e80941Smrg                break;
549b8e80941Smrg
550b8e80941Smrg        case midgard_condition_true:
551b8e80941Smrg                printf("true");
552b8e80941Smrg                break;
553b8e80941Smrg
554b8e80941Smrg        case midgard_condition_always:
555b8e80941Smrg                printf("always");
556b8e80941Smrg                break;
557b8e80941Smrg
558b8e80941Smrg        default:
559b8e80941Smrg                printf("unk%X", cond);
560b8e80941Smrg                break;
561b8e80941Smrg        }
562b8e80941Smrg}
563b8e80941Smrg
564b8e80941Smrgstatic void
565b8e80941Smrgprint_compact_branch_writeout_field(uint16_t word)
566b8e80941Smrg{
567b8e80941Smrg        midgard_jmp_writeout_op op = word & 0x7;
568b8e80941Smrg
569b8e80941Smrg        switch (op) {
570b8e80941Smrg        case midgard_jmp_writeout_op_branch_uncond: {
571b8e80941Smrg                midgard_branch_uncond br_uncond;
572b8e80941Smrg                memcpy((char *) &br_uncond, (char *) &word, sizeof(br_uncond));
573b8e80941Smrg                printf("br.uncond ");
574b8e80941Smrg
575b8e80941Smrg                if (br_uncond.unknown != 1)
576b8e80941Smrg                        printf("unknown:%d, ", br_uncond.unknown);
577b8e80941Smrg
578b8e80941Smrg                if (br_uncond.offset >= 0)
579b8e80941Smrg                        printf("+");
580b8e80941Smrg
581b8e80941Smrg                printf("%d", br_uncond.offset);
582b8e80941Smrg
583b8e80941Smrg                printf(" -> %X\n", br_uncond.dest_tag);
584b8e80941Smrg                break;
585b8e80941Smrg        }
586b8e80941Smrg
587b8e80941Smrg        case midgard_jmp_writeout_op_branch_cond:
588b8e80941Smrg        case midgard_jmp_writeout_op_writeout:
589b8e80941Smrg        case midgard_jmp_writeout_op_discard:
590b8e80941Smrg        default: {
591b8e80941Smrg                midgard_branch_cond br_cond;
592b8e80941Smrg                memcpy((char *) &br_cond, (char *) &word, sizeof(br_cond));
593b8e80941Smrg
594b8e80941Smrg                printf("br.");
595b8e80941Smrg
596b8e80941Smrg                print_branch_op(br_cond.op);
597b8e80941Smrg                print_branch_cond(br_cond.cond);
598b8e80941Smrg
599b8e80941Smrg                printf(" ");
600b8e80941Smrg
601b8e80941Smrg                if (br_cond.offset >= 0)
602b8e80941Smrg                        printf("+");
603b8e80941Smrg
604b8e80941Smrg                printf("%d", br_cond.offset);
605b8e80941Smrg
606b8e80941Smrg                printf(" -> %X\n", br_cond.dest_tag);
607b8e80941Smrg                break;
608b8e80941Smrg        }
609b8e80941Smrg        }
610b8e80941Smrg}
611b8e80941Smrg
612b8e80941Smrgstatic void
613b8e80941Smrgprint_extended_branch_writeout_field(uint8_t *words)
614b8e80941Smrg{
615b8e80941Smrg        midgard_branch_extended br;
616b8e80941Smrg        memcpy((char *) &br, (char *) words, sizeof(br));
617b8e80941Smrg
618b8e80941Smrg        printf("brx.");
619b8e80941Smrg
620b8e80941Smrg        print_branch_op(br.op);
621b8e80941Smrg
622b8e80941Smrg        /* Condition repeated 8 times in all known cases. Check this. */
623b8e80941Smrg
624b8e80941Smrg        unsigned cond = br.cond & 0x3;
625b8e80941Smrg
626b8e80941Smrg        for (unsigned i = 0; i < 16; i += 2) {
627b8e80941Smrg                assert(((br.cond >> i) & 0x3) == cond);
628b8e80941Smrg        }
629b8e80941Smrg
630b8e80941Smrg        print_branch_cond(cond);
631b8e80941Smrg
632b8e80941Smrg        if (br.unknown)
633b8e80941Smrg                printf(".unknown%d", br.unknown);
634b8e80941Smrg
635b8e80941Smrg        printf(" ");
636b8e80941Smrg
637b8e80941Smrg        if (br.offset >= 0)
638b8e80941Smrg                printf("+");
639b8e80941Smrg
640b8e80941Smrg        printf("%d", br.offset);
641b8e80941Smrg
642b8e80941Smrg        printf(" -> %X\n", br.dest_tag);
643b8e80941Smrg}
644b8e80941Smrg
645b8e80941Smrgstatic unsigned
646b8e80941Smrgnum_alu_fields_enabled(uint32_t control_word)
647b8e80941Smrg{
648b8e80941Smrg        unsigned ret = 0;
649b8e80941Smrg
650b8e80941Smrg        if ((control_word >> 17) & 1)
651b8e80941Smrg                ret++;
652b8e80941Smrg
653b8e80941Smrg        if ((control_word >> 19) & 1)
654b8e80941Smrg                ret++;
655b8e80941Smrg
656b8e80941Smrg        if ((control_word >> 21) & 1)
657b8e80941Smrg                ret++;
658b8e80941Smrg
659b8e80941Smrg        if ((control_word >> 23) & 1)
660b8e80941Smrg                ret++;
661b8e80941Smrg
662b8e80941Smrg        if ((control_word >> 25) & 1)
663b8e80941Smrg                ret++;
664b8e80941Smrg
665b8e80941Smrg        return ret;
666b8e80941Smrg}
667b8e80941Smrg
668b8e80941Smrgstatic float
669b8e80941Smrgfloat_bitcast(uint32_t integer)
670b8e80941Smrg{
671b8e80941Smrg        union {
672b8e80941Smrg                uint32_t i;
673b8e80941Smrg                float f;
674b8e80941Smrg        } v;
675b8e80941Smrg
676b8e80941Smrg        v.i = integer;
677b8e80941Smrg        return v.f;
678b8e80941Smrg}
679b8e80941Smrg
680b8e80941Smrgstatic void
681b8e80941Smrgprint_alu_word(uint32_t *words, unsigned num_quad_words,
682b8e80941Smrg               unsigned tabs)
683b8e80941Smrg{
684b8e80941Smrg        uint32_t control_word = words[0];
685b8e80941Smrg        uint16_t *beginning_ptr = (uint16_t *)(words + 1);
686b8e80941Smrg        unsigned num_fields = num_alu_fields_enabled(control_word);
687b8e80941Smrg        uint16_t *word_ptr = beginning_ptr + num_fields;
688b8e80941Smrg        unsigned num_words = 2 + num_fields;
689b8e80941Smrg
690b8e80941Smrg        if ((control_word >> 16) & 1)
691b8e80941Smrg                printf("unknown bit 16 enabled\n");
692b8e80941Smrg
693b8e80941Smrg        if ((control_word >> 17) & 1) {
694b8e80941Smrg                print_vector_field("vmul", word_ptr, *beginning_ptr, tabs);
695b8e80941Smrg                beginning_ptr += 1;
696b8e80941Smrg                word_ptr += 3;
697b8e80941Smrg                num_words += 3;
698b8e80941Smrg        }
699b8e80941Smrg
700b8e80941Smrg        if ((control_word >> 18) & 1)
701b8e80941Smrg                printf("unknown bit 18 enabled\n");
702b8e80941Smrg
703b8e80941Smrg        if ((control_word >> 19) & 1) {
704b8e80941Smrg                print_scalar_field("sadd", word_ptr, *beginning_ptr, tabs);
705b8e80941Smrg                beginning_ptr += 1;
706b8e80941Smrg                word_ptr += 2;
707b8e80941Smrg                num_words += 2;
708b8e80941Smrg        }
709b8e80941Smrg
710b8e80941Smrg        if ((control_word >> 20) & 1)
711b8e80941Smrg                printf("unknown bit 20 enabled\n");
712b8e80941Smrg
713b8e80941Smrg        if ((control_word >> 21) & 1) {
714b8e80941Smrg                print_vector_field("vadd", word_ptr, *beginning_ptr, tabs);
715b8e80941Smrg                beginning_ptr += 1;
716b8e80941Smrg                word_ptr += 3;
717b8e80941Smrg                num_words += 3;
718b8e80941Smrg        }
719b8e80941Smrg
720b8e80941Smrg        if ((control_word >> 22) & 1)
721b8e80941Smrg                printf("unknown bit 22 enabled\n");
722b8e80941Smrg
723b8e80941Smrg        if ((control_word >> 23) & 1) {
724b8e80941Smrg                print_scalar_field("smul", word_ptr, *beginning_ptr, tabs);
725b8e80941Smrg                beginning_ptr += 1;
726b8e80941Smrg                word_ptr += 2;
727b8e80941Smrg                num_words += 2;
728b8e80941Smrg        }
729b8e80941Smrg
730b8e80941Smrg        if ((control_word >> 24) & 1)
731b8e80941Smrg                printf("unknown bit 24 enabled\n");
732b8e80941Smrg
733b8e80941Smrg        if ((control_word >> 25) & 1) {
734b8e80941Smrg                print_vector_field("lut", word_ptr, *beginning_ptr, tabs);
735b8e80941Smrg                beginning_ptr += 1;
736b8e80941Smrg                word_ptr += 3;
737b8e80941Smrg                num_words += 3;
738b8e80941Smrg        }
739b8e80941Smrg
740b8e80941Smrg        if ((control_word >> 26) & 1) {
741b8e80941Smrg                print_compact_branch_writeout_field(*word_ptr);
742b8e80941Smrg                word_ptr += 1;
743b8e80941Smrg                num_words += 1;
744b8e80941Smrg        }
745b8e80941Smrg
746b8e80941Smrg        if ((control_word >> 27) & 1) {
747b8e80941Smrg                print_extended_branch_writeout_field((uint8_t *) word_ptr);
748b8e80941Smrg                word_ptr += 3;
749b8e80941Smrg                num_words += 3;
750b8e80941Smrg        }
751b8e80941Smrg
752b8e80941Smrg        if (num_quad_words > (num_words + 7) / 8) {
753b8e80941Smrg                assert(num_quad_words == (num_words + 15) / 8);
754b8e80941Smrg                //Assume that the extra quadword is constants
755b8e80941Smrg                void *consts = words + (4 * num_quad_words - 4);
756b8e80941Smrg
757b8e80941Smrg                if (is_embedded_constant_int) {
758b8e80941Smrg                        if (is_embedded_constant_half) {
759b8e80941Smrg                                int16_t *sconsts = (int16_t *) consts;
760b8e80941Smrg                                printf("sconstants %d, %d, %d, %d\n",
761b8e80941Smrg                                       sconsts[0],
762b8e80941Smrg                                       sconsts[1],
763b8e80941Smrg                                       sconsts[2],
764b8e80941Smrg                                       sconsts[3]);
765b8e80941Smrg                        } else {
766b8e80941Smrg                                int32_t *iconsts = (int32_t *) consts;
767b8e80941Smrg                                printf("iconstants %d, %d, %d, %d\n",
768b8e80941Smrg                                       iconsts[0],
769b8e80941Smrg                                       iconsts[1],
770b8e80941Smrg                                       iconsts[2],
771b8e80941Smrg                                       iconsts[3]);
772b8e80941Smrg                        }
773b8e80941Smrg                } else {
774b8e80941Smrg                        if (is_embedded_constant_half) {
775b8e80941Smrg                                uint16_t *hconsts = (uint16_t *) consts;
776b8e80941Smrg                                printf("hconstants %g, %g, %g, %g\n",
777b8e80941Smrg                                       _mesa_half_to_float(hconsts[0]),
778b8e80941Smrg                                       _mesa_half_to_float(hconsts[1]),
779b8e80941Smrg                                       _mesa_half_to_float(hconsts[2]),
780b8e80941Smrg                                       _mesa_half_to_float(hconsts[3]));
781b8e80941Smrg                        } else {
782b8e80941Smrg                                uint32_t *fconsts = (uint32_t *) consts;
783b8e80941Smrg                                printf("fconstants %g, %g, %g, %g\n",
784b8e80941Smrg                                       float_bitcast(fconsts[0]),
785b8e80941Smrg                                       float_bitcast(fconsts[1]),
786b8e80941Smrg                                       float_bitcast(fconsts[2]),
787b8e80941Smrg                                       float_bitcast(fconsts[3]));
788b8e80941Smrg                        }
789b8e80941Smrg
790b8e80941Smrg                }
791b8e80941Smrg        }
792b8e80941Smrg}
793b8e80941Smrg
794b8e80941Smrg/* Swizzle/mask formats are common between load/store ops and texture ops, it
795b8e80941Smrg * looks like... */
796b8e80941Smrg
797b8e80941Smrgstatic void
798b8e80941Smrgprint_swizzle(uint32_t swizzle)
799b8e80941Smrg{
800b8e80941Smrg        unsigned i;
801b8e80941Smrg
802b8e80941Smrg        if (swizzle != 0xE4) {
803b8e80941Smrg                printf(".");
804b8e80941Smrg
805b8e80941Smrg                for (i = 0; i < 4; i++)
806b8e80941Smrg                        printf("%c", "xyzw"[(swizzle >> (2 * i)) & 3]);
807b8e80941Smrg        }
808b8e80941Smrg}
809b8e80941Smrg
810b8e80941Smrgstatic void
811b8e80941Smrgprint_mask(uint32_t mask)
812b8e80941Smrg{
813b8e80941Smrg        unsigned i;
814b8e80941Smrg
815b8e80941Smrg        if (mask != 0xF) {
816b8e80941Smrg                printf(".");
817b8e80941Smrg
818b8e80941Smrg                for (i = 0; i < 4; i++)
819b8e80941Smrg                        if (mask & (1 << i))
820b8e80941Smrg                                printf("%c", "xyzw"[i]);
821b8e80941Smrg
822b8e80941Smrg                /* Handle degenerate case */
823b8e80941Smrg                if (mask == 0)
824b8e80941Smrg                        printf("0");
825b8e80941Smrg        }
826b8e80941Smrg}
827b8e80941Smrg
828b8e80941Smrgstatic void
829b8e80941Smrgprint_varying_parameters(midgard_load_store_word *word)
830b8e80941Smrg{
831b8e80941Smrg        midgard_varying_parameter param;
832b8e80941Smrg        unsigned v = word->varying_parameters;
833b8e80941Smrg        memcpy(&param, &v, sizeof(param));
834b8e80941Smrg
835b8e80941Smrg        if (param.is_varying) {
836b8e80941Smrg                /* If a varying, there are qualifiers */
837b8e80941Smrg                if (param.flat)
838b8e80941Smrg                        printf(".flat");
839b8e80941Smrg
840b8e80941Smrg                if (param.interpolation != midgard_interp_default) {
841b8e80941Smrg                        if (param.interpolation == midgard_interp_centroid)
842b8e80941Smrg                                printf(".centroid");
843b8e80941Smrg                        else
844b8e80941Smrg                                printf(".interp%d", param.interpolation);
845b8e80941Smrg                }
846b8e80941Smrg        } else if (param.flat || param.interpolation) {
847b8e80941Smrg                printf(" /* is_varying not set but varying metadata attached */");
848b8e80941Smrg        }
849b8e80941Smrg
850b8e80941Smrg        if (param.zero1 || param.zero2)
851b8e80941Smrg                printf(" /* zero tripped, %d %d */ ", param.zero1, param.zero2);
852b8e80941Smrg}
853b8e80941Smrg
854b8e80941Smrgstatic bool
855b8e80941Smrgis_op_varying(unsigned op)
856b8e80941Smrg{
857b8e80941Smrg        switch (op) {
858b8e80941Smrg        case midgard_op_store_vary_16:
859b8e80941Smrg        case midgard_op_store_vary_32:
860b8e80941Smrg        case midgard_op_load_vary_16:
861b8e80941Smrg        case midgard_op_load_vary_32:
862b8e80941Smrg                return true;
863b8e80941Smrg        }
864b8e80941Smrg
865b8e80941Smrg        return false;
866b8e80941Smrg}
867b8e80941Smrg
868b8e80941Smrgstatic void
869b8e80941Smrgprint_load_store_instr(uint64_t data,
870b8e80941Smrg                       unsigned tabs)
871b8e80941Smrg{
872b8e80941Smrg        midgard_load_store_word *word = (midgard_load_store_word *) &data;
873b8e80941Smrg
874b8e80941Smrg        print_ld_st_opcode(word->op);
875b8e80941Smrg
876b8e80941Smrg        if (is_op_varying(word->op))
877b8e80941Smrg                print_varying_parameters(word);
878b8e80941Smrg
879b8e80941Smrg        printf(" r%d", word->reg);
880b8e80941Smrg        print_mask(word->mask);
881b8e80941Smrg
882b8e80941Smrg        int address = word->address;
883b8e80941Smrg
884b8e80941Smrg        if (word->op == midgard_op_load_uniform_32) {
885b8e80941Smrg                /* Uniforms use their own addressing scheme */
886b8e80941Smrg
887b8e80941Smrg                int lo = word->varying_parameters >> 7;
888b8e80941Smrg                int hi = word->address;
889b8e80941Smrg
890b8e80941Smrg                /* TODO: Combine fields logically */
891b8e80941Smrg                address = (hi << 3) | lo;
892b8e80941Smrg        }
893b8e80941Smrg
894b8e80941Smrg        printf(", %d", address);
895b8e80941Smrg
896b8e80941Smrg        print_swizzle(word->swizzle);
897b8e80941Smrg
898b8e80941Smrg        printf(", 0x%X /* %X */\n", word->unknown, word->varying_parameters);
899b8e80941Smrg}
900b8e80941Smrg
901b8e80941Smrgstatic void
902b8e80941Smrgprint_load_store_word(uint32_t *word, unsigned tabs)
903b8e80941Smrg{
904b8e80941Smrg        midgard_load_store *load_store = (midgard_load_store *) word;
905b8e80941Smrg
906b8e80941Smrg        if (load_store->word1 != 3) {
907b8e80941Smrg                print_load_store_instr(load_store->word1, tabs);
908b8e80941Smrg        }
909b8e80941Smrg
910b8e80941Smrg        if (load_store->word2 != 3) {
911b8e80941Smrg                print_load_store_instr(load_store->word2, tabs);
912b8e80941Smrg        }
913b8e80941Smrg}
914b8e80941Smrg
915b8e80941Smrgstatic void
916b8e80941Smrgprint_texture_reg(bool full, bool select, bool upper)
917b8e80941Smrg{
918b8e80941Smrg        if (full)
919b8e80941Smrg                printf("r%d", REG_TEX_BASE + select);
920b8e80941Smrg        else
921b8e80941Smrg                printf("hr%d", (REG_TEX_BASE + select) * 2 + upper);
922b8e80941Smrg
923b8e80941Smrg        if (full && upper)
924b8e80941Smrg                printf("// error: out full / upper mutually exclusive\n");
925b8e80941Smrg
926b8e80941Smrg}
927b8e80941Smrg
928b8e80941Smrgstatic void
929b8e80941Smrgprint_texture_format(int format)
930b8e80941Smrg{
931b8e80941Smrg        /* Act like a modifier */
932b8e80941Smrg        printf(".");
933b8e80941Smrg
934b8e80941Smrg        switch (format) {
935b8e80941Smrg                DEFINE_CASE(TEXTURE_2D, "2d");
936b8e80941Smrg                DEFINE_CASE(TEXTURE_3D, "3d");
937b8e80941Smrg                DEFINE_CASE(TEXTURE_CUBE, "cube");
938b8e80941Smrg
939b8e80941Smrg        default:
940b8e80941Smrg                printf("fmt_%d", format);
941b8e80941Smrg                break;
942b8e80941Smrg        }
943b8e80941Smrg}
944b8e80941Smrg
945b8e80941Smrgstatic void
946b8e80941Smrgprint_texture_op(int format)
947b8e80941Smrg{
948b8e80941Smrg        /* Act like a modifier */
949b8e80941Smrg        printf(".");
950b8e80941Smrg
951b8e80941Smrg        switch (format) {
952b8e80941Smrg                DEFINE_CASE(TEXTURE_OP_NORMAL, "normal");
953b8e80941Smrg                DEFINE_CASE(TEXTURE_OP_TEXEL_FETCH, "texelfetch");
954b8e80941Smrg
955b8e80941Smrg        default:
956b8e80941Smrg                printf("op_%d", format);
957b8e80941Smrg                break;
958b8e80941Smrg        }
959b8e80941Smrg}
960b8e80941Smrg
961b8e80941Smrg#undef DEFINE_CASE
962b8e80941Smrg
963b8e80941Smrgstatic void
964b8e80941Smrgprint_texture_word(uint32_t *word, unsigned tabs)
965b8e80941Smrg{
966b8e80941Smrg        midgard_texture_word *texture = (midgard_texture_word *) word;
967b8e80941Smrg
968b8e80941Smrg        /* Instruction family, like ALU words have theirs */
969b8e80941Smrg        printf("texture");
970b8e80941Smrg
971b8e80941Smrg        /* Broad category of texture operation in question */
972b8e80941Smrg        print_texture_op(texture->op);
973b8e80941Smrg
974b8e80941Smrg        /* Specific format in question */
975b8e80941Smrg        print_texture_format(texture->format);
976b8e80941Smrg
977b8e80941Smrg        /* Instruction "modifiers" parallel the ALU instructions. First group
978b8e80941Smrg         * are modifiers that act alone */
979b8e80941Smrg
980b8e80941Smrg        if (!texture->filter)
981b8e80941Smrg                printf(".raw");
982b8e80941Smrg
983b8e80941Smrg        if (texture->shadow)
984b8e80941Smrg                printf(".shadow");
985b8e80941Smrg
986b8e80941Smrg        if (texture->cont)
987b8e80941Smrg                printf(".cont");
988b8e80941Smrg
989b8e80941Smrg        if (texture->last)
990b8e80941Smrg                printf(".last");
991b8e80941Smrg
992b8e80941Smrg        /* Second set are modifiers which take an extra argument each */
993b8e80941Smrg
994b8e80941Smrg        if (texture->has_offset)
995b8e80941Smrg                printf(".offset");
996b8e80941Smrg
997b8e80941Smrg        if (texture->bias)
998b8e80941Smrg                printf(".bias");
999b8e80941Smrg
1000b8e80941Smrg        printf(" ");
1001b8e80941Smrg
1002b8e80941Smrg        print_texture_reg(texture->out_full, texture->out_reg_select, texture->out_upper);
1003b8e80941Smrg        print_mask(texture->mask);
1004b8e80941Smrg        printf(", ");
1005b8e80941Smrg
1006b8e80941Smrg        printf("texture%d, ", texture->texture_handle);
1007b8e80941Smrg
1008b8e80941Smrg        printf("sampler%d", texture->sampler_handle);
1009b8e80941Smrg        print_swizzle(texture->swizzle);
1010b8e80941Smrg        printf(", ");
1011b8e80941Smrg
1012b8e80941Smrg        print_texture_reg(/*texture->in_reg_full*/true, texture->in_reg_select, texture->in_reg_upper);
1013b8e80941Smrg        printf(".%c%c, ", "xyzw"[texture->in_reg_swizzle_left],
1014b8e80941Smrg               "xyzw"[texture->in_reg_swizzle_right]);
1015b8e80941Smrg
1016b8e80941Smrg        /* TODO: can offsets be full words? */
1017b8e80941Smrg        if (texture->has_offset) {
1018b8e80941Smrg                print_texture_reg(false, texture->offset_reg_select, texture->offset_reg_upper);
1019b8e80941Smrg                printf(", ");
1020b8e80941Smrg        }
1021b8e80941Smrg
1022b8e80941Smrg        if (texture->bias)
1023b8e80941Smrg                printf("%f, ", texture->bias / 256.0f);
1024b8e80941Smrg
1025b8e80941Smrg        printf("\n");
1026b8e80941Smrg
1027b8e80941Smrg        /* While not zero in general, for these simple instructions the
1028b8e80941Smrg         * following unknowns are zero, so we don't include them */
1029b8e80941Smrg
1030b8e80941Smrg        if (texture->unknown1 ||
1031b8e80941Smrg                        texture->unknown2 ||
1032b8e80941Smrg                        texture->unknown3 ||
1033b8e80941Smrg                        texture->unknown4 ||
1034b8e80941Smrg                        texture->unknownA ||
1035b8e80941Smrg                        texture->unknownB ||
1036b8e80941Smrg                        texture->unknown8 ||
1037b8e80941Smrg                        texture->unknown9) {
1038b8e80941Smrg                printf("// unknown1 = 0x%x\n", texture->unknown1);
1039b8e80941Smrg                printf("// unknown2 = 0x%x\n", texture->unknown2);
1040b8e80941Smrg                printf("// unknown3 = 0x%x\n", texture->unknown3);
1041b8e80941Smrg                printf("// unknown4 = 0x%x\n", texture->unknown4);
1042b8e80941Smrg                printf("// unknownA = 0x%x\n", texture->unknownA);
1043b8e80941Smrg                printf("// unknownB = 0x%x\n", texture->unknownB);
1044b8e80941Smrg                printf("// unknown8 = 0x%x\n", texture->unknown8);
1045b8e80941Smrg                printf("// unknown9 = 0x%x\n", texture->unknown9);
1046b8e80941Smrg        }
1047b8e80941Smrg
1048b8e80941Smrg        /* Similarly, if no offset is applied, these are zero. If an offset
1049b8e80941Smrg         * -is- applied, or gradients are used, etc, these are nonzero but
1050b8e80941Smrg         *  largely unknown still. */
1051b8e80941Smrg
1052b8e80941Smrg        if (texture->offset_unknown1 ||
1053b8e80941Smrg                        texture->offset_reg_select ||
1054b8e80941Smrg                        texture->offset_reg_upper ||
1055b8e80941Smrg                        texture->offset_unknown4 ||
1056b8e80941Smrg                        texture->offset_unknown5 ||
1057b8e80941Smrg                        texture->offset_unknown6 ||
1058b8e80941Smrg                        texture->offset_unknown7 ||
1059b8e80941Smrg                        texture->offset_unknown8 ||
1060b8e80941Smrg                        texture->offset_unknown9) {
1061b8e80941Smrg                printf("// offset_unknown1 = 0x%x\n", texture->offset_unknown1);
1062b8e80941Smrg                printf("// offset_reg_select = 0x%x\n", texture->offset_reg_select);
1063b8e80941Smrg                printf("// offset_reg_upper = 0x%x\n", texture->offset_reg_upper);
1064b8e80941Smrg                printf("// offset_unknown4 = 0x%x\n", texture->offset_unknown4);
1065b8e80941Smrg                printf("// offset_unknown5 = 0x%x\n", texture->offset_unknown5);
1066b8e80941Smrg                printf("// offset_unknown6 = 0x%x\n", texture->offset_unknown6);
1067b8e80941Smrg                printf("// offset_unknown7 = 0x%x\n", texture->offset_unknown7);
1068b8e80941Smrg                printf("// offset_unknown8 = 0x%x\n", texture->offset_unknown8);
1069b8e80941Smrg                printf("// offset_unknown9 = 0x%x\n", texture->offset_unknown9);
1070b8e80941Smrg        }
1071b8e80941Smrg
1072b8e80941Smrg        /* Don't blow up */
1073b8e80941Smrg        if (texture->unknown7 != 0x1)
1074b8e80941Smrg                printf("// (!) unknown7 = %d\n", texture->unknown7);
1075b8e80941Smrg}
1076b8e80941Smrg
1077b8e80941Smrgvoid
1078b8e80941Smrgdisassemble_midgard(uint8_t *code, size_t size)
1079b8e80941Smrg{
1080b8e80941Smrg        uint32_t *words = (uint32_t *) code;
1081b8e80941Smrg        unsigned num_words = size / 4;
1082b8e80941Smrg        int tabs = 0;
1083b8e80941Smrg
1084b8e80941Smrg        bool prefetch_flag = false;
1085b8e80941Smrg
1086b8e80941Smrg        unsigned i = 0;
1087b8e80941Smrg
1088b8e80941Smrg        while (i < num_words) {
1089b8e80941Smrg                unsigned num_quad_words = midgard_word_size[words[i] & 0xF];
1090b8e80941Smrg
1091b8e80941Smrg                switch (midgard_word_types[words[i] & 0xF]) {
1092b8e80941Smrg                case midgard_word_type_texture:
1093b8e80941Smrg                        print_texture_word(&words[i], tabs);
1094b8e80941Smrg                        break;
1095b8e80941Smrg
1096b8e80941Smrg                case midgard_word_type_load_store:
1097b8e80941Smrg                        print_load_store_word(&words[i], tabs);
1098b8e80941Smrg                        break;
1099b8e80941Smrg
1100b8e80941Smrg                case midgard_word_type_alu:
1101b8e80941Smrg                        print_alu_word(&words[i], num_quad_words, tabs);
1102b8e80941Smrg
1103b8e80941Smrg                        if (prefetch_flag)
1104b8e80941Smrg                                return;
1105b8e80941Smrg
1106b8e80941Smrg                        /* Reset word static analysis state */
1107b8e80941Smrg                        is_embedded_constant_half = false;
1108b8e80941Smrg                        is_embedded_constant_int = false;
1109b8e80941Smrg
1110b8e80941Smrg                        break;
1111b8e80941Smrg
1112b8e80941Smrg                default:
1113b8e80941Smrg                        printf("Unknown word type %u:\n", words[i] & 0xF);
1114b8e80941Smrg                        num_quad_words = 1;
1115b8e80941Smrg                        print_quad_word(&words[i], tabs);
1116b8e80941Smrg                        printf("\n");
1117b8e80941Smrg                        break;
1118b8e80941Smrg                }
1119b8e80941Smrg
1120b8e80941Smrg                printf("\n");
1121b8e80941Smrg
1122b8e80941Smrg                unsigned next = (words[i] & 0xF0) >> 4;
1123b8e80941Smrg
1124b8e80941Smrg                i += 4 * num_quad_words;
1125b8e80941Smrg
1126b8e80941Smrg                /* Break based on instruction prefetch flag */
1127b8e80941Smrg
1128b8e80941Smrg                if (i < num_words && next == 1) {
1129b8e80941Smrg                        prefetch_flag = true;
1130b8e80941Smrg
1131b8e80941Smrg                        if (midgard_word_types[words[i] & 0xF] != midgard_word_type_alu)
1132b8e80941Smrg                                return;
1133b8e80941Smrg                }
1134b8e80941Smrg        }
1135b8e80941Smrg
1136b8e80941Smrg        return;
1137b8e80941Smrg}
1138