xref: /aosp_15_r20/external/mesa3d/src/panfrost/compiler/bifrost/disassemble.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright (C) 2019 Connor Abbott <[email protected]>
3*61046927SAndroid Build Coastguard Worker  * Copyright (C) 2019 Lyude Paul <[email protected]>
4*61046927SAndroid Build Coastguard Worker  * Copyright (C) 2019 Ryan Houdek <[email protected]>
5*61046927SAndroid Build Coastguard Worker  *
6*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
7*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
8*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
9*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
11*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
12*61046927SAndroid Build Coastguard Worker  *
13*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
14*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
15*61046927SAndroid Build Coastguard Worker  * Software.
16*61046927SAndroid Build Coastguard Worker  *
17*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22*61046927SAndroid Build Coastguard Worker  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23*61046927SAndroid Build Coastguard Worker  * SOFTWARE.
24*61046927SAndroid Build Coastguard Worker  */
25*61046927SAndroid Build Coastguard Worker 
26*61046927SAndroid Build Coastguard Worker #include <assert.h>
27*61046927SAndroid Build Coastguard Worker #include <inttypes.h>
28*61046927SAndroid Build Coastguard Worker #include <stdbool.h>
29*61046927SAndroid Build Coastguard Worker #include <stdint.h>
30*61046927SAndroid Build Coastguard Worker #include <stdio.h>
31*61046927SAndroid Build Coastguard Worker #include <string.h>
32*61046927SAndroid Build Coastguard Worker 
33*61046927SAndroid Build Coastguard Worker #include "util/compiler.h"
34*61046927SAndroid Build Coastguard Worker #include "util/macros.h"
35*61046927SAndroid Build Coastguard Worker #include "bi_disasm.h"
36*61046927SAndroid Build Coastguard Worker #include "bi_print_common.h"
37*61046927SAndroid Build Coastguard Worker #include "bifrost.h"
38*61046927SAndroid Build Coastguard Worker #include "disassemble.h"
39*61046927SAndroid Build Coastguard Worker #include "../bifrost.h"
40*61046927SAndroid Build Coastguard Worker 
41*61046927SAndroid Build Coastguard Worker // return bits (high, lo]
42*61046927SAndroid Build Coastguard Worker static uint64_t
bits(uint32_t word,unsigned lo,unsigned high)43*61046927SAndroid Build Coastguard Worker bits(uint32_t word, unsigned lo, unsigned high)
44*61046927SAndroid Build Coastguard Worker {
45*61046927SAndroid Build Coastguard Worker    if (high == 32)
46*61046927SAndroid Build Coastguard Worker       return word >> lo;
47*61046927SAndroid Build Coastguard Worker    return (word & ((1 << high) - 1)) >> lo;
48*61046927SAndroid Build Coastguard Worker }
49*61046927SAndroid Build Coastguard Worker 
50*61046927SAndroid Build Coastguard Worker // each of these structs represents an instruction that's dispatched in one
51*61046927SAndroid Build Coastguard Worker // cycle. Note that these instructions are packed in funny ways within the
52*61046927SAndroid Build Coastguard Worker // clause, hence the need for a separate struct.
53*61046927SAndroid Build Coastguard Worker struct bifrost_alu_inst {
54*61046927SAndroid Build Coastguard Worker    uint32_t fma_bits;
55*61046927SAndroid Build Coastguard Worker    uint32_t add_bits;
56*61046927SAndroid Build Coastguard Worker    uint64_t reg_bits;
57*61046927SAndroid Build Coastguard Worker };
58*61046927SAndroid Build Coastguard Worker 
59*61046927SAndroid Build Coastguard Worker static unsigned
get_reg0(struct bifrost_regs regs)60*61046927SAndroid Build Coastguard Worker get_reg0(struct bifrost_regs regs)
61*61046927SAndroid Build Coastguard Worker {
62*61046927SAndroid Build Coastguard Worker    if (regs.ctrl == 0)
63*61046927SAndroid Build Coastguard Worker       return regs.reg0 | ((regs.reg1 & 0x1) << 5);
64*61046927SAndroid Build Coastguard Worker 
65*61046927SAndroid Build Coastguard Worker    return regs.reg0 <= regs.reg1 ? regs.reg0 : 63 - regs.reg0;
66*61046927SAndroid Build Coastguard Worker }
67*61046927SAndroid Build Coastguard Worker 
68*61046927SAndroid Build Coastguard Worker static unsigned
get_reg1(struct bifrost_regs regs)69*61046927SAndroid Build Coastguard Worker get_reg1(struct bifrost_regs regs)
70*61046927SAndroid Build Coastguard Worker {
71*61046927SAndroid Build Coastguard Worker    return regs.reg0 <= regs.reg1 ? regs.reg1 : 63 - regs.reg1;
72*61046927SAndroid Build Coastguard Worker }
73*61046927SAndroid Build Coastguard Worker 
74*61046927SAndroid Build Coastguard Worker // this represents the decoded version of the ctrl register field.
75*61046927SAndroid Build Coastguard Worker struct bifrost_reg_ctrl {
76*61046927SAndroid Build Coastguard Worker    bool read_reg0;
77*61046927SAndroid Build Coastguard Worker    bool read_reg1;
78*61046927SAndroid Build Coastguard Worker    struct bifrost_reg_ctrl_23 slot23;
79*61046927SAndroid Build Coastguard Worker };
80*61046927SAndroid Build Coastguard Worker 
81*61046927SAndroid Build Coastguard Worker static void
dump_header(FILE * fp,struct bifrost_header header,bool verbose)82*61046927SAndroid Build Coastguard Worker dump_header(FILE *fp, struct bifrost_header header, bool verbose)
83*61046927SAndroid Build Coastguard Worker {
84*61046927SAndroid Build Coastguard Worker    fprintf(fp, "ds(%u) ", header.dependency_slot);
85*61046927SAndroid Build Coastguard Worker 
86*61046927SAndroid Build Coastguard Worker    if (header.staging_barrier)
87*61046927SAndroid Build Coastguard Worker       fprintf(fp, "osrb ");
88*61046927SAndroid Build Coastguard Worker 
89*61046927SAndroid Build Coastguard Worker    fprintf(fp, "%s ", bi_flow_control_name(header.flow_control));
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker    if (header.suppress_inf)
92*61046927SAndroid Build Coastguard Worker       fprintf(fp, "inf_suppress ");
93*61046927SAndroid Build Coastguard Worker    if (header.suppress_nan)
94*61046927SAndroid Build Coastguard Worker       fprintf(fp, "nan_suppress ");
95*61046927SAndroid Build Coastguard Worker 
96*61046927SAndroid Build Coastguard Worker    if (header.flush_to_zero == BIFROST_FTZ_DX11)
97*61046927SAndroid Build Coastguard Worker       fprintf(fp, "ftz_dx11 ");
98*61046927SAndroid Build Coastguard Worker    else if (header.flush_to_zero == BIFROST_FTZ_ALWAYS)
99*61046927SAndroid Build Coastguard Worker       fprintf(fp, "ftz_hsa ");
100*61046927SAndroid Build Coastguard Worker    if (header.flush_to_zero == BIFROST_FTZ_ABRUPT)
101*61046927SAndroid Build Coastguard Worker       fprintf(fp, "ftz_au ");
102*61046927SAndroid Build Coastguard Worker 
103*61046927SAndroid Build Coastguard Worker    assert(!header.zero1);
104*61046927SAndroid Build Coastguard Worker    assert(!header.zero2);
105*61046927SAndroid Build Coastguard Worker 
106*61046927SAndroid Build Coastguard Worker    if (header.float_exceptions == BIFROST_EXCEPTIONS_DISABLED)
107*61046927SAndroid Build Coastguard Worker       fprintf(fp, "fpe_ts ");
108*61046927SAndroid Build Coastguard Worker    else if (header.float_exceptions == BIFROST_EXCEPTIONS_PRECISE_DIVISION)
109*61046927SAndroid Build Coastguard Worker       fprintf(fp, "fpe_pd ");
110*61046927SAndroid Build Coastguard Worker    else if (header.float_exceptions == BIFROST_EXCEPTIONS_PRECISE_SQRT)
111*61046927SAndroid Build Coastguard Worker       fprintf(fp, "fpe_psqr ");
112*61046927SAndroid Build Coastguard Worker 
113*61046927SAndroid Build Coastguard Worker    if (header.message_type)
114*61046927SAndroid Build Coastguard Worker       fprintf(fp, "%s ", bi_message_type_name(header.message_type));
115*61046927SAndroid Build Coastguard Worker 
116*61046927SAndroid Build Coastguard Worker    if (header.terminate_discarded_threads)
117*61046927SAndroid Build Coastguard Worker       fprintf(fp, "td ");
118*61046927SAndroid Build Coastguard Worker 
119*61046927SAndroid Build Coastguard Worker    if (header.next_clause_prefetch)
120*61046927SAndroid Build Coastguard Worker       fprintf(fp, "ncph ");
121*61046927SAndroid Build Coastguard Worker 
122*61046927SAndroid Build Coastguard Worker    if (header.next_message_type)
123*61046927SAndroid Build Coastguard Worker       fprintf(fp, "next_%s ", bi_message_type_name(header.next_message_type));
124*61046927SAndroid Build Coastguard Worker    if (header.dependency_wait != 0) {
125*61046927SAndroid Build Coastguard Worker       fprintf(fp, "dwb(");
126*61046927SAndroid Build Coastguard Worker       bool first = true;
127*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < 8; i++) {
128*61046927SAndroid Build Coastguard Worker          if (header.dependency_wait & (1 << i)) {
129*61046927SAndroid Build Coastguard Worker             if (!first) {
130*61046927SAndroid Build Coastguard Worker                fprintf(fp, ", ");
131*61046927SAndroid Build Coastguard Worker             }
132*61046927SAndroid Build Coastguard Worker             fprintf(fp, "%u", i);
133*61046927SAndroid Build Coastguard Worker             first = false;
134*61046927SAndroid Build Coastguard Worker          }
135*61046927SAndroid Build Coastguard Worker       }
136*61046927SAndroid Build Coastguard Worker       fprintf(fp, ") ");
137*61046927SAndroid Build Coastguard Worker    }
138*61046927SAndroid Build Coastguard Worker 
139*61046927SAndroid Build Coastguard Worker    fprintf(fp, "\n");
140*61046927SAndroid Build Coastguard Worker }
141*61046927SAndroid Build Coastguard Worker 
142*61046927SAndroid Build Coastguard Worker static struct bifrost_reg_ctrl
DecodeRegCtrl(FILE * fp,struct bifrost_regs regs,bool first)143*61046927SAndroid Build Coastguard Worker DecodeRegCtrl(FILE *fp, struct bifrost_regs regs, bool first)
144*61046927SAndroid Build Coastguard Worker {
145*61046927SAndroid Build Coastguard Worker    struct bifrost_reg_ctrl decoded = {};
146*61046927SAndroid Build Coastguard Worker    unsigned ctrl;
147*61046927SAndroid Build Coastguard Worker    if (regs.ctrl == 0) {
148*61046927SAndroid Build Coastguard Worker       ctrl = regs.reg1 >> 2;
149*61046927SAndroid Build Coastguard Worker       decoded.read_reg0 = !(regs.reg1 & 0x2);
150*61046927SAndroid Build Coastguard Worker       decoded.read_reg1 = false;
151*61046927SAndroid Build Coastguard Worker    } else {
152*61046927SAndroid Build Coastguard Worker       ctrl = regs.ctrl;
153*61046927SAndroid Build Coastguard Worker       decoded.read_reg0 = decoded.read_reg1 = true;
154*61046927SAndroid Build Coastguard Worker    }
155*61046927SAndroid Build Coastguard Worker 
156*61046927SAndroid Build Coastguard Worker    /* Modify control based on state */
157*61046927SAndroid Build Coastguard Worker    if (first)
158*61046927SAndroid Build Coastguard Worker       ctrl = (ctrl & 0x7) | ((ctrl & 0x8) << 1);
159*61046927SAndroid Build Coastguard Worker    else if (regs.reg2 == regs.reg3)
160*61046927SAndroid Build Coastguard Worker       ctrl += 16;
161*61046927SAndroid Build Coastguard Worker 
162*61046927SAndroid Build Coastguard Worker    decoded.slot23 = bifrost_reg_ctrl_lut[ctrl];
163*61046927SAndroid Build Coastguard Worker    ASSERTED struct bifrost_reg_ctrl_23 reserved = {0};
164*61046927SAndroid Build Coastguard Worker    assert(memcmp(&decoded.slot23, &reserved, sizeof(reserved)));
165*61046927SAndroid Build Coastguard Worker 
166*61046927SAndroid Build Coastguard Worker    return decoded;
167*61046927SAndroid Build Coastguard Worker }
168*61046927SAndroid Build Coastguard Worker 
169*61046927SAndroid Build Coastguard Worker static void
dump_regs(FILE * fp,struct bifrost_regs srcs,bool first)170*61046927SAndroid Build Coastguard Worker dump_regs(FILE *fp, struct bifrost_regs srcs, bool first)
171*61046927SAndroid Build Coastguard Worker {
172*61046927SAndroid Build Coastguard Worker    struct bifrost_reg_ctrl ctrl = DecodeRegCtrl(fp, srcs, first);
173*61046927SAndroid Build Coastguard Worker    fprintf(fp, "    # ");
174*61046927SAndroid Build Coastguard Worker    if (ctrl.read_reg0)
175*61046927SAndroid Build Coastguard Worker       fprintf(fp, "slot 0: r%u ", get_reg0(srcs));
176*61046927SAndroid Build Coastguard Worker    if (ctrl.read_reg1)
177*61046927SAndroid Build Coastguard Worker       fprintf(fp, "slot 1: r%u ", get_reg1(srcs));
178*61046927SAndroid Build Coastguard Worker 
179*61046927SAndroid Build Coastguard Worker    const char *slot3_fma = ctrl.slot23.slot3_fma ? "FMA" : "ADD";
180*61046927SAndroid Build Coastguard Worker 
181*61046927SAndroid Build Coastguard Worker    if (ctrl.slot23.slot2 == BIFROST_OP_WRITE)
182*61046927SAndroid Build Coastguard Worker       fprintf(fp, "slot 2: r%u (write FMA) ", srcs.reg2);
183*61046927SAndroid Build Coastguard Worker    else if (ctrl.slot23.slot2 == BIFROST_OP_WRITE_LO)
184*61046927SAndroid Build Coastguard Worker       fprintf(fp, "slot 2: r%u (write lo FMA) ", srcs.reg2);
185*61046927SAndroid Build Coastguard Worker    else if (ctrl.slot23.slot2 == BIFROST_OP_WRITE_HI)
186*61046927SAndroid Build Coastguard Worker       fprintf(fp, "slot 2: r%u (write hi FMA) ", srcs.reg2);
187*61046927SAndroid Build Coastguard Worker    else if (ctrl.slot23.slot2 == BIFROST_OP_READ)
188*61046927SAndroid Build Coastguard Worker       fprintf(fp, "slot 2: r%u (read) ", srcs.reg2);
189*61046927SAndroid Build Coastguard Worker 
190*61046927SAndroid Build Coastguard Worker    if (ctrl.slot23.slot3 == BIFROST_OP_WRITE)
191*61046927SAndroid Build Coastguard Worker       fprintf(fp, "slot 3: r%u (write %s) ", srcs.reg3, slot3_fma);
192*61046927SAndroid Build Coastguard Worker    else if (ctrl.slot23.slot3 == BIFROST_OP_WRITE_LO)
193*61046927SAndroid Build Coastguard Worker       fprintf(fp, "slot 3: r%u (write lo %s) ", srcs.reg3, slot3_fma);
194*61046927SAndroid Build Coastguard Worker    else if (ctrl.slot23.slot3 == BIFROST_OP_WRITE_HI)
195*61046927SAndroid Build Coastguard Worker       fprintf(fp, "slot 3: r%u (write hi %s) ", srcs.reg3, slot3_fma);
196*61046927SAndroid Build Coastguard Worker 
197*61046927SAndroid Build Coastguard Worker    if (srcs.fau_idx)
198*61046927SAndroid Build Coastguard Worker       fprintf(fp, "fau %X ", srcs.fau_idx);
199*61046927SAndroid Build Coastguard Worker 
200*61046927SAndroid Build Coastguard Worker    fprintf(fp, "\n");
201*61046927SAndroid Build Coastguard Worker }
202*61046927SAndroid Build Coastguard Worker 
203*61046927SAndroid Build Coastguard Worker static void
bi_disasm_dest_mask(FILE * fp,enum bifrost_reg_op op)204*61046927SAndroid Build Coastguard Worker bi_disasm_dest_mask(FILE *fp, enum bifrost_reg_op op)
205*61046927SAndroid Build Coastguard Worker {
206*61046927SAndroid Build Coastguard Worker    if (op == BIFROST_OP_WRITE_LO)
207*61046927SAndroid Build Coastguard Worker       fprintf(fp, ".h0");
208*61046927SAndroid Build Coastguard Worker    else if (op == BIFROST_OP_WRITE_HI)
209*61046927SAndroid Build Coastguard Worker       fprintf(fp, ".h1");
210*61046927SAndroid Build Coastguard Worker }
211*61046927SAndroid Build Coastguard Worker 
212*61046927SAndroid Build Coastguard Worker void
bi_disasm_dest_fma(FILE * fp,struct bifrost_regs * next_regs,bool last)213*61046927SAndroid Build Coastguard Worker bi_disasm_dest_fma(FILE *fp, struct bifrost_regs *next_regs, bool last)
214*61046927SAndroid Build Coastguard Worker {
215*61046927SAndroid Build Coastguard Worker    /* If this is the last instruction, next_regs points to the first reg entry. */
216*61046927SAndroid Build Coastguard Worker    struct bifrost_reg_ctrl ctrl = DecodeRegCtrl(fp, *next_regs, last);
217*61046927SAndroid Build Coastguard Worker    if (ctrl.slot23.slot2 >= BIFROST_OP_WRITE) {
218*61046927SAndroid Build Coastguard Worker       fprintf(fp, "r%u:t0", next_regs->reg2);
219*61046927SAndroid Build Coastguard Worker       bi_disasm_dest_mask(fp, ctrl.slot23.slot2);
220*61046927SAndroid Build Coastguard Worker    } else if (ctrl.slot23.slot3 >= BIFROST_OP_WRITE && ctrl.slot23.slot3_fma) {
221*61046927SAndroid Build Coastguard Worker       fprintf(fp, "r%u:t0", next_regs->reg3);
222*61046927SAndroid Build Coastguard Worker       bi_disasm_dest_mask(fp, ctrl.slot23.slot3);
223*61046927SAndroid Build Coastguard Worker    } else
224*61046927SAndroid Build Coastguard Worker       fprintf(fp, "t0");
225*61046927SAndroid Build Coastguard Worker }
226*61046927SAndroid Build Coastguard Worker 
227*61046927SAndroid Build Coastguard Worker void
bi_disasm_dest_add(FILE * fp,struct bifrost_regs * next_regs,bool last)228*61046927SAndroid Build Coastguard Worker bi_disasm_dest_add(FILE *fp, struct bifrost_regs *next_regs, bool last)
229*61046927SAndroid Build Coastguard Worker {
230*61046927SAndroid Build Coastguard Worker    /* If this is the last instruction, next_regs points to the first reg entry. */
231*61046927SAndroid Build Coastguard Worker    struct bifrost_reg_ctrl ctrl = DecodeRegCtrl(fp, *next_regs, last);
232*61046927SAndroid Build Coastguard Worker 
233*61046927SAndroid Build Coastguard Worker    if (ctrl.slot23.slot3 >= BIFROST_OP_WRITE && !ctrl.slot23.slot3_fma) {
234*61046927SAndroid Build Coastguard Worker       fprintf(fp, "r%u:t1", next_regs->reg3);
235*61046927SAndroid Build Coastguard Worker       bi_disasm_dest_mask(fp, ctrl.slot23.slot3);
236*61046927SAndroid Build Coastguard Worker    } else
237*61046927SAndroid Build Coastguard Worker       fprintf(fp, "t1");
238*61046927SAndroid Build Coastguard Worker }
239*61046927SAndroid Build Coastguard Worker 
240*61046927SAndroid Build Coastguard Worker static void
dump_const_imm(FILE * fp,uint32_t imm)241*61046927SAndroid Build Coastguard Worker dump_const_imm(FILE *fp, uint32_t imm)
242*61046927SAndroid Build Coastguard Worker {
243*61046927SAndroid Build Coastguard Worker    union {
244*61046927SAndroid Build Coastguard Worker       float f;
245*61046927SAndroid Build Coastguard Worker       uint32_t i;
246*61046927SAndroid Build Coastguard Worker    } fi;
247*61046927SAndroid Build Coastguard Worker    fi.i = imm;
248*61046927SAndroid Build Coastguard Worker    fprintf(fp, "0x%08x /* %f */", imm, fi.f);
249*61046927SAndroid Build Coastguard Worker }
250*61046927SAndroid Build Coastguard Worker 
251*61046927SAndroid Build Coastguard Worker static void
dump_pc_imm(FILE * fp,uint64_t imm,unsigned branch_offset,enum bi_constmod mod,bool high32)252*61046927SAndroid Build Coastguard Worker dump_pc_imm(FILE *fp, uint64_t imm, unsigned branch_offset,
253*61046927SAndroid Build Coastguard Worker             enum bi_constmod mod, bool high32)
254*61046927SAndroid Build Coastguard Worker {
255*61046927SAndroid Build Coastguard Worker    if (mod == BI_CONSTMOD_PC_HI && !high32) {
256*61046927SAndroid Build Coastguard Worker       dump_const_imm(fp, imm);
257*61046927SAndroid Build Coastguard Worker       return;
258*61046927SAndroid Build Coastguard Worker    }
259*61046927SAndroid Build Coastguard Worker 
260*61046927SAndroid Build Coastguard Worker    /* 60-bit sign-extend */
261*61046927SAndroid Build Coastguard Worker    uint64_t zx64 = (imm << 4);
262*61046927SAndroid Build Coastguard Worker    int64_t sx64 = zx64;
263*61046927SAndroid Build Coastguard Worker    sx64 >>= 4;
264*61046927SAndroid Build Coastguard Worker 
265*61046927SAndroid Build Coastguard Worker    /* 28-bit sign extend x 2 */
266*61046927SAndroid Build Coastguard Worker    uint32_t imm32[2] = {(uint32_t)imm, (uint32_t)(imm >> 32)};
267*61046927SAndroid Build Coastguard Worker    uint32_t zx32[2] = {imm32[0] << 4, imm32[1] << 4};
268*61046927SAndroid Build Coastguard Worker    int32_t sx32[2] = {zx32[0], zx32[1]};
269*61046927SAndroid Build Coastguard Worker    sx32[0] >>= 4;
270*61046927SAndroid Build Coastguard Worker    sx32[1] >>= 4;
271*61046927SAndroid Build Coastguard Worker 
272*61046927SAndroid Build Coastguard Worker    int64_t offs = 0;
273*61046927SAndroid Build Coastguard Worker 
274*61046927SAndroid Build Coastguard Worker    switch (mod) {
275*61046927SAndroid Build Coastguard Worker    case BI_CONSTMOD_PC_LO:
276*61046927SAndroid Build Coastguard Worker       offs = sx64;
277*61046927SAndroid Build Coastguard Worker       break;
278*61046927SAndroid Build Coastguard Worker    case BI_CONSTMOD_PC_HI:
279*61046927SAndroid Build Coastguard Worker       offs = sx32[1];
280*61046927SAndroid Build Coastguard Worker       break;
281*61046927SAndroid Build Coastguard Worker    case BI_CONSTMOD_PC_LO_HI:
282*61046927SAndroid Build Coastguard Worker       offs = sx32[high32];
283*61046927SAndroid Build Coastguard Worker       break;
284*61046927SAndroid Build Coastguard Worker    default:
285*61046927SAndroid Build Coastguard Worker       unreachable("Invalid PC modifier");
286*61046927SAndroid Build Coastguard Worker    }
287*61046927SAndroid Build Coastguard Worker 
288*61046927SAndroid Build Coastguard Worker    assert((offs & 15) == 0);
289*61046927SAndroid Build Coastguard Worker    fprintf(fp, "clause_%" PRId64, branch_offset + (offs / 16));
290*61046927SAndroid Build Coastguard Worker 
291*61046927SAndroid Build Coastguard Worker    if (mod == BI_CONSTMOD_PC_LO && high32)
292*61046927SAndroid Build Coastguard Worker       fprintf(fp, " >> 32");
293*61046927SAndroid Build Coastguard Worker 
294*61046927SAndroid Build Coastguard Worker    /* While technically in spec, referencing the current clause as (pc +
295*61046927SAndroid Build Coastguard Worker     * 0) likely indicates an unintended infinite loop  */
296*61046927SAndroid Build Coastguard Worker    if (offs == 0)
297*61046927SAndroid Build Coastguard Worker       fprintf(fp, " /* XXX: likely an infinite loop */");
298*61046927SAndroid Build Coastguard Worker }
299*61046927SAndroid Build Coastguard Worker 
300*61046927SAndroid Build Coastguard Worker /* Convert an index to an embedded constant in FAU-RAM to the index of the
301*61046927SAndroid Build Coastguard Worker  * embedded constant. No, it's not in order. Yes, really. */
302*61046927SAndroid Build Coastguard Worker 
303*61046927SAndroid Build Coastguard Worker static unsigned
const_fau_to_idx(unsigned fau_value)304*61046927SAndroid Build Coastguard Worker const_fau_to_idx(unsigned fau_value)
305*61046927SAndroid Build Coastguard Worker {
306*61046927SAndroid Build Coastguard Worker    unsigned map[8] = {~0, ~0, 4, 5, 0, 1, 2, 3};
307*61046927SAndroid Build Coastguard Worker 
308*61046927SAndroid Build Coastguard Worker    assert(map[fau_value] < 6);
309*61046927SAndroid Build Coastguard Worker    return map[fau_value];
310*61046927SAndroid Build Coastguard Worker }
311*61046927SAndroid Build Coastguard Worker 
312*61046927SAndroid Build Coastguard Worker static void
dump_fau_src(FILE * fp,struct bifrost_regs srcs,unsigned branch_offset,struct bi_constants * consts,bool high32)313*61046927SAndroid Build Coastguard Worker dump_fau_src(FILE *fp, struct bifrost_regs srcs, unsigned branch_offset,
314*61046927SAndroid Build Coastguard Worker              struct bi_constants *consts, bool high32)
315*61046927SAndroid Build Coastguard Worker {
316*61046927SAndroid Build Coastguard Worker    if (srcs.fau_idx & 0x80) {
317*61046927SAndroid Build Coastguard Worker       unsigned uniform = (srcs.fau_idx & 0x7f);
318*61046927SAndroid Build Coastguard Worker       fprintf(fp, "u%u.w%u", uniform, high32);
319*61046927SAndroid Build Coastguard Worker    } else if (srcs.fau_idx >= 0x20) {
320*61046927SAndroid Build Coastguard Worker       unsigned idx = const_fau_to_idx(srcs.fau_idx >> 4);
321*61046927SAndroid Build Coastguard Worker       uint64_t imm = consts->raw[idx];
322*61046927SAndroid Build Coastguard Worker       imm |= (srcs.fau_idx & 0xf);
323*61046927SAndroid Build Coastguard Worker       if (consts->mods[idx] != BI_CONSTMOD_NONE)
324*61046927SAndroid Build Coastguard Worker          dump_pc_imm(fp, imm, branch_offset, consts->mods[idx], high32);
325*61046927SAndroid Build Coastguard Worker       else if (high32)
326*61046927SAndroid Build Coastguard Worker          dump_const_imm(fp, imm >> 32);
327*61046927SAndroid Build Coastguard Worker       else
328*61046927SAndroid Build Coastguard Worker          dump_const_imm(fp, imm);
329*61046927SAndroid Build Coastguard Worker    } else {
330*61046927SAndroid Build Coastguard Worker       switch (srcs.fau_idx) {
331*61046927SAndroid Build Coastguard Worker       case 0:
332*61046927SAndroid Build Coastguard Worker          fprintf(fp, "#0");
333*61046927SAndroid Build Coastguard Worker          break;
334*61046927SAndroid Build Coastguard Worker       case 1:
335*61046927SAndroid Build Coastguard Worker          fprintf(fp, "lane_id");
336*61046927SAndroid Build Coastguard Worker          break;
337*61046927SAndroid Build Coastguard Worker       case 2:
338*61046927SAndroid Build Coastguard Worker          fprintf(fp, "warp_id");
339*61046927SAndroid Build Coastguard Worker          break;
340*61046927SAndroid Build Coastguard Worker       case 3:
341*61046927SAndroid Build Coastguard Worker          fprintf(fp, "core_id");
342*61046927SAndroid Build Coastguard Worker          break;
343*61046927SAndroid Build Coastguard Worker       case 4:
344*61046927SAndroid Build Coastguard Worker          fprintf(fp, "framebuffer_size");
345*61046927SAndroid Build Coastguard Worker          break;
346*61046927SAndroid Build Coastguard Worker       case 5:
347*61046927SAndroid Build Coastguard Worker          fprintf(fp, "atest_datum");
348*61046927SAndroid Build Coastguard Worker          break;
349*61046927SAndroid Build Coastguard Worker       case 6:
350*61046927SAndroid Build Coastguard Worker          fprintf(fp, "sample");
351*61046927SAndroid Build Coastguard Worker          break;
352*61046927SAndroid Build Coastguard Worker       case 8:
353*61046927SAndroid Build Coastguard Worker       case 9:
354*61046927SAndroid Build Coastguard Worker       case 10:
355*61046927SAndroid Build Coastguard Worker       case 11:
356*61046927SAndroid Build Coastguard Worker       case 12:
357*61046927SAndroid Build Coastguard Worker       case 13:
358*61046927SAndroid Build Coastguard Worker       case 14:
359*61046927SAndroid Build Coastguard Worker       case 15:
360*61046927SAndroid Build Coastguard Worker          fprintf(fp, "blend_descriptor_%u", (unsigned)srcs.fau_idx - 8);
361*61046927SAndroid Build Coastguard Worker          break;
362*61046927SAndroid Build Coastguard Worker       default:
363*61046927SAndroid Build Coastguard Worker          fprintf(fp, "XXX - reserved%u", (unsigned)srcs.fau_idx);
364*61046927SAndroid Build Coastguard Worker          break;
365*61046927SAndroid Build Coastguard Worker       }
366*61046927SAndroid Build Coastguard Worker 
367*61046927SAndroid Build Coastguard Worker       if (high32)
368*61046927SAndroid Build Coastguard Worker          fprintf(fp, ".y");
369*61046927SAndroid Build Coastguard Worker       else
370*61046927SAndroid Build Coastguard Worker          fprintf(fp, ".x");
371*61046927SAndroid Build Coastguard Worker    }
372*61046927SAndroid Build Coastguard Worker }
373*61046927SAndroid Build Coastguard Worker 
374*61046927SAndroid Build Coastguard Worker void
dump_src(FILE * fp,unsigned src,struct bifrost_regs srcs,unsigned branch_offset,struct bi_constants * consts,bool isFMA)375*61046927SAndroid Build Coastguard Worker dump_src(FILE *fp, unsigned src, struct bifrost_regs srcs,
376*61046927SAndroid Build Coastguard Worker          unsigned branch_offset, struct bi_constants *consts, bool isFMA)
377*61046927SAndroid Build Coastguard Worker {
378*61046927SAndroid Build Coastguard Worker    switch (src) {
379*61046927SAndroid Build Coastguard Worker    case 0:
380*61046927SAndroid Build Coastguard Worker       fprintf(fp, "r%u", get_reg0(srcs));
381*61046927SAndroid Build Coastguard Worker       break;
382*61046927SAndroid Build Coastguard Worker    case 1:
383*61046927SAndroid Build Coastguard Worker       fprintf(fp, "r%u", get_reg1(srcs));
384*61046927SAndroid Build Coastguard Worker       break;
385*61046927SAndroid Build Coastguard Worker    case 2:
386*61046927SAndroid Build Coastguard Worker       fprintf(fp, "r%u", srcs.reg2);
387*61046927SAndroid Build Coastguard Worker       break;
388*61046927SAndroid Build Coastguard Worker    case 3:
389*61046927SAndroid Build Coastguard Worker       if (isFMA)
390*61046927SAndroid Build Coastguard Worker          fprintf(fp, "#0");
391*61046927SAndroid Build Coastguard Worker       else
392*61046927SAndroid Build Coastguard Worker          fprintf(fp, "t"); // i.e. the output of FMA this cycle
393*61046927SAndroid Build Coastguard Worker       break;
394*61046927SAndroid Build Coastguard Worker    case 4:
395*61046927SAndroid Build Coastguard Worker       dump_fau_src(fp, srcs, branch_offset, consts, false);
396*61046927SAndroid Build Coastguard Worker       break;
397*61046927SAndroid Build Coastguard Worker    case 5:
398*61046927SAndroid Build Coastguard Worker       dump_fau_src(fp, srcs, branch_offset, consts, true);
399*61046927SAndroid Build Coastguard Worker       break;
400*61046927SAndroid Build Coastguard Worker    case 6:
401*61046927SAndroid Build Coastguard Worker       fprintf(fp, "t0");
402*61046927SAndroid Build Coastguard Worker       break;
403*61046927SAndroid Build Coastguard Worker    case 7:
404*61046927SAndroid Build Coastguard Worker       fprintf(fp, "t1");
405*61046927SAndroid Build Coastguard Worker       break;
406*61046927SAndroid Build Coastguard Worker    }
407*61046927SAndroid Build Coastguard Worker }
408*61046927SAndroid Build Coastguard Worker 
409*61046927SAndroid Build Coastguard Worker /* Tables for decoding M0, or if M0 == 7, M1 respectively.
410*61046927SAndroid Build Coastguard Worker  *
411*61046927SAndroid Build Coastguard Worker  * XXX: It's not clear if the third entry of M1_table corresponding to (7, 2)
412*61046927SAndroid Build Coastguard Worker  * should have PC_LO_HI in the EC1 slot, or it's a weird hybrid mode? I would
413*61046927SAndroid Build Coastguard Worker  * say this needs testing but no code should ever actually use this mode.
414*61046927SAndroid Build Coastguard Worker  */
415*61046927SAndroid Build Coastguard Worker 
416*61046927SAndroid Build Coastguard Worker static const enum bi_constmod M1_table[7][2] = {
417*61046927SAndroid Build Coastguard Worker    {BI_CONSTMOD_NONE, BI_CONSTMOD_NONE},
418*61046927SAndroid Build Coastguard Worker    {BI_CONSTMOD_PC_LO, BI_CONSTMOD_NONE},
419*61046927SAndroid Build Coastguard Worker    {BI_CONSTMOD_PC_LO, BI_CONSTMOD_PC_LO},
420*61046927SAndroid Build Coastguard Worker    {~0, ~0},
421*61046927SAndroid Build Coastguard Worker    {BI_CONSTMOD_PC_HI, BI_CONSTMOD_NONE},
422*61046927SAndroid Build Coastguard Worker    {BI_CONSTMOD_PC_HI, BI_CONSTMOD_PC_HI},
423*61046927SAndroid Build Coastguard Worker    {BI_CONSTMOD_PC_LO, BI_CONSTMOD_NONE},
424*61046927SAndroid Build Coastguard Worker };
425*61046927SAndroid Build Coastguard Worker 
426*61046927SAndroid Build Coastguard Worker static const enum bi_constmod M2_table[4][2] = {
427*61046927SAndroid Build Coastguard Worker    {BI_CONSTMOD_PC_LO_HI, BI_CONSTMOD_NONE},
428*61046927SAndroid Build Coastguard Worker    {BI_CONSTMOD_PC_LO_HI, BI_CONSTMOD_PC_HI},
429*61046927SAndroid Build Coastguard Worker    {BI_CONSTMOD_PC_LO_HI, BI_CONSTMOD_PC_LO_HI},
430*61046927SAndroid Build Coastguard Worker    {BI_CONSTMOD_PC_LO_HI, BI_CONSTMOD_PC_HI},
431*61046927SAndroid Build Coastguard Worker };
432*61046927SAndroid Build Coastguard Worker 
433*61046927SAndroid Build Coastguard Worker static void
decode_M(enum bi_constmod * mod,unsigned M1,unsigned M2,bool single)434*61046927SAndroid Build Coastguard Worker decode_M(enum bi_constmod *mod, unsigned M1, unsigned M2, bool single)
435*61046927SAndroid Build Coastguard Worker {
436*61046927SAndroid Build Coastguard Worker    if (M1 >= 8) {
437*61046927SAndroid Build Coastguard Worker       mod[0] = BI_CONSTMOD_NONE;
438*61046927SAndroid Build Coastguard Worker 
439*61046927SAndroid Build Coastguard Worker       if (!single)
440*61046927SAndroid Build Coastguard Worker          mod[1] = BI_CONSTMOD_NONE;
441*61046927SAndroid Build Coastguard Worker 
442*61046927SAndroid Build Coastguard Worker       return;
443*61046927SAndroid Build Coastguard Worker    } else if (M1 == 7) {
444*61046927SAndroid Build Coastguard Worker       assert(M2 < 4);
445*61046927SAndroid Build Coastguard Worker       memcpy(mod, M2_table[M2], sizeof(*mod) * (single ? 1 : 2));
446*61046927SAndroid Build Coastguard Worker    } else {
447*61046927SAndroid Build Coastguard Worker       assert(M1 != 3);
448*61046927SAndroid Build Coastguard Worker       memcpy(mod, M1_table[M1], sizeof(*mod) * (single ? 1 : 2));
449*61046927SAndroid Build Coastguard Worker    }
450*61046927SAndroid Build Coastguard Worker }
451*61046927SAndroid Build Coastguard Worker 
452*61046927SAndroid Build Coastguard Worker static void
dump_clause(FILE * fp,const uint32_t * words,unsigned * size,unsigned offset,bool verbose)453*61046927SAndroid Build Coastguard Worker dump_clause(FILE *fp, const uint32_t *words, unsigned *size, unsigned offset,
454*61046927SAndroid Build Coastguard Worker             bool verbose)
455*61046927SAndroid Build Coastguard Worker {
456*61046927SAndroid Build Coastguard Worker    // State for a decoded clause
457*61046927SAndroid Build Coastguard Worker    struct bifrost_alu_inst instrs[8] = {};
458*61046927SAndroid Build Coastguard Worker    struct bi_constants consts = {};
459*61046927SAndroid Build Coastguard Worker    unsigned num_instrs = 0;
460*61046927SAndroid Build Coastguard Worker    unsigned num_consts = 0;
461*61046927SAndroid Build Coastguard Worker    uint64_t header_bits = 0;
462*61046927SAndroid Build Coastguard Worker 
463*61046927SAndroid Build Coastguard Worker    unsigned i;
464*61046927SAndroid Build Coastguard Worker    for (i = 0;; i++, words += 4) {
465*61046927SAndroid Build Coastguard Worker       if (verbose) {
466*61046927SAndroid Build Coastguard Worker          fprintf(fp, "# ");
467*61046927SAndroid Build Coastguard Worker          for (int j = 0; j < 4; j++)
468*61046927SAndroid Build Coastguard Worker             fprintf(fp, "%08x ", words[3 - j]); // low bit on the right
469*61046927SAndroid Build Coastguard Worker          fprintf(fp, "\n");
470*61046927SAndroid Build Coastguard Worker       }
471*61046927SAndroid Build Coastguard Worker       unsigned tag = bits(words[0], 0, 8);
472*61046927SAndroid Build Coastguard Worker 
473*61046927SAndroid Build Coastguard Worker       // speculatively decode some things that are common between many formats,
474*61046927SAndroid Build Coastguard Worker       // so we can share some code
475*61046927SAndroid Build Coastguard Worker       struct bifrost_alu_inst main_instr = {};
476*61046927SAndroid Build Coastguard Worker       // 20 bits
477*61046927SAndroid Build Coastguard Worker       main_instr.add_bits = bits(words[2], 2, 32 - 13);
478*61046927SAndroid Build Coastguard Worker       // 23 bits
479*61046927SAndroid Build Coastguard Worker       main_instr.fma_bits = bits(words[1], 11, 32) | bits(words[2], 0, 2)
480*61046927SAndroid Build Coastguard Worker                                                         << (32 - 11);
481*61046927SAndroid Build Coastguard Worker       // 35 bits
482*61046927SAndroid Build Coastguard Worker       main_instr.reg_bits = ((uint64_t)bits(words[1], 0, 11)) << 24 |
483*61046927SAndroid Build Coastguard Worker                             (uint64_t)bits(words[0], 8, 32);
484*61046927SAndroid Build Coastguard Worker 
485*61046927SAndroid Build Coastguard Worker       uint64_t const0 = bits(words[0], 8, 32) << 4 | (uint64_t)words[1] << 28 |
486*61046927SAndroid Build Coastguard Worker                         bits(words[2], 0, 4) << 60;
487*61046927SAndroid Build Coastguard Worker       uint64_t const1 = bits(words[2], 4, 32) << 4 | (uint64_t)words[3] << 32;
488*61046927SAndroid Build Coastguard Worker 
489*61046927SAndroid Build Coastguard Worker       /* Z-bit */
490*61046927SAndroid Build Coastguard Worker       bool stop = tag & 0x40;
491*61046927SAndroid Build Coastguard Worker 
492*61046927SAndroid Build Coastguard Worker       if (verbose) {
493*61046927SAndroid Build Coastguard Worker          fprintf(fp, "# tag: 0x%02x\n", tag);
494*61046927SAndroid Build Coastguard Worker       }
495*61046927SAndroid Build Coastguard Worker       if (tag & 0x80) {
496*61046927SAndroid Build Coastguard Worker          /* Format 5 or 10 */
497*61046927SAndroid Build Coastguard Worker          unsigned idx = stop ? 5 : 2;
498*61046927SAndroid Build Coastguard Worker          main_instr.add_bits |= ((tag >> 3) & 0x7) << 17;
499*61046927SAndroid Build Coastguard Worker          instrs[idx + 1] = main_instr;
500*61046927SAndroid Build Coastguard Worker          instrs[idx].add_bits = bits(words[3], 0, 17) | ((tag & 0x7) << 17);
501*61046927SAndroid Build Coastguard Worker          instrs[idx].fma_bits |= bits(words[2], 19, 32) << 10;
502*61046927SAndroid Build Coastguard Worker          consts.raw[0] = bits(words[3], 17, 32) << 4;
503*61046927SAndroid Build Coastguard Worker       } else {
504*61046927SAndroid Build Coastguard Worker          bool done = false;
505*61046927SAndroid Build Coastguard Worker          switch ((tag >> 3) & 0x7) {
506*61046927SAndroid Build Coastguard Worker          case 0x0:
507*61046927SAndroid Build Coastguard Worker             switch (tag & 0x7) {
508*61046927SAndroid Build Coastguard Worker             case 0x3:
509*61046927SAndroid Build Coastguard Worker                /* Format 1 */
510*61046927SAndroid Build Coastguard Worker                main_instr.add_bits |= bits(words[3], 29, 32) << 17;
511*61046927SAndroid Build Coastguard Worker                instrs[1] = main_instr;
512*61046927SAndroid Build Coastguard Worker                num_instrs = 2;
513*61046927SAndroid Build Coastguard Worker                done = stop;
514*61046927SAndroid Build Coastguard Worker                break;
515*61046927SAndroid Build Coastguard Worker             case 0x4:
516*61046927SAndroid Build Coastguard Worker                /* Format 3 */
517*61046927SAndroid Build Coastguard Worker                instrs[2].add_bits =
518*61046927SAndroid Build Coastguard Worker                   bits(words[3], 0, 17) | bits(words[3], 29, 32) << 17;
519*61046927SAndroid Build Coastguard Worker                instrs[2].fma_bits |= bits(words[2], 19, 32) << 10;
520*61046927SAndroid Build Coastguard Worker                consts.raw[0] = const0;
521*61046927SAndroid Build Coastguard Worker                decode_M(&consts.mods[0], bits(words[2], 4, 8),
522*61046927SAndroid Build Coastguard Worker                         bits(words[2], 8, 12), true);
523*61046927SAndroid Build Coastguard Worker                num_instrs = 3;
524*61046927SAndroid Build Coastguard Worker                num_consts = 1;
525*61046927SAndroid Build Coastguard Worker                done = stop;
526*61046927SAndroid Build Coastguard Worker                break;
527*61046927SAndroid Build Coastguard Worker             case 0x1:
528*61046927SAndroid Build Coastguard Worker             case 0x5:
529*61046927SAndroid Build Coastguard Worker                /* Format 4 */
530*61046927SAndroid Build Coastguard Worker                instrs[2].add_bits =
531*61046927SAndroid Build Coastguard Worker                   bits(words[3], 0, 17) | bits(words[3], 29, 32) << 17;
532*61046927SAndroid Build Coastguard Worker                instrs[2].fma_bits |= bits(words[2], 19, 32) << 10;
533*61046927SAndroid Build Coastguard Worker                main_instr.add_bits |= bits(words[3], 26, 29) << 17;
534*61046927SAndroid Build Coastguard Worker                instrs[3] = main_instr;
535*61046927SAndroid Build Coastguard Worker                if ((tag & 0x7) == 0x5) {
536*61046927SAndroid Build Coastguard Worker                   num_instrs = 4;
537*61046927SAndroid Build Coastguard Worker                   done = stop;
538*61046927SAndroid Build Coastguard Worker                }
539*61046927SAndroid Build Coastguard Worker                break;
540*61046927SAndroid Build Coastguard Worker             case 0x6:
541*61046927SAndroid Build Coastguard Worker                /* Format 8 */
542*61046927SAndroid Build Coastguard Worker                instrs[5].add_bits =
543*61046927SAndroid Build Coastguard Worker                   bits(words[3], 0, 17) | bits(words[3], 29, 32) << 17;
544*61046927SAndroid Build Coastguard Worker                instrs[5].fma_bits |= bits(words[2], 19, 32) << 10;
545*61046927SAndroid Build Coastguard Worker                consts.raw[0] = const0;
546*61046927SAndroid Build Coastguard Worker                decode_M(&consts.mods[0], bits(words[2], 4, 8),
547*61046927SAndroid Build Coastguard Worker                         bits(words[2], 8, 12), true);
548*61046927SAndroid Build Coastguard Worker                num_instrs = 6;
549*61046927SAndroid Build Coastguard Worker                num_consts = 1;
550*61046927SAndroid Build Coastguard Worker                done = stop;
551*61046927SAndroid Build Coastguard Worker                break;
552*61046927SAndroid Build Coastguard Worker             case 0x7:
553*61046927SAndroid Build Coastguard Worker                /* Format 9 */
554*61046927SAndroid Build Coastguard Worker                instrs[5].add_bits =
555*61046927SAndroid Build Coastguard Worker                   bits(words[3], 0, 17) | bits(words[3], 29, 32) << 17;
556*61046927SAndroid Build Coastguard Worker                instrs[5].fma_bits |= bits(words[2], 19, 32) << 10;
557*61046927SAndroid Build Coastguard Worker                main_instr.add_bits |= bits(words[3], 26, 29) << 17;
558*61046927SAndroid Build Coastguard Worker                instrs[6] = main_instr;
559*61046927SAndroid Build Coastguard Worker                num_instrs = 7;
560*61046927SAndroid Build Coastguard Worker                done = stop;
561*61046927SAndroid Build Coastguard Worker                break;
562*61046927SAndroid Build Coastguard Worker             default:
563*61046927SAndroid Build Coastguard Worker                unreachable("[INSTR_INVALID_ENC] Invalid tag bits");
564*61046927SAndroid Build Coastguard Worker             }
565*61046927SAndroid Build Coastguard Worker             break;
566*61046927SAndroid Build Coastguard Worker          case 0x2:
567*61046927SAndroid Build Coastguard Worker          case 0x3: {
568*61046927SAndroid Build Coastguard Worker             /* Format 6 or 11 */
569*61046927SAndroid Build Coastguard Worker             unsigned idx = ((tag >> 3) & 0x7) == 2 ? 4 : 7;
570*61046927SAndroid Build Coastguard Worker             main_instr.add_bits |= (tag & 0x7) << 17;
571*61046927SAndroid Build Coastguard Worker             instrs[idx] = main_instr;
572*61046927SAndroid Build Coastguard Worker             consts.raw[0] |=
573*61046927SAndroid Build Coastguard Worker                (bits(words[2], 19, 32) | ((uint64_t)words[3] << 13)) << 19;
574*61046927SAndroid Build Coastguard Worker             num_consts = 1;
575*61046927SAndroid Build Coastguard Worker             num_instrs = idx + 1;
576*61046927SAndroid Build Coastguard Worker             done = stop;
577*61046927SAndroid Build Coastguard Worker             break;
578*61046927SAndroid Build Coastguard Worker          }
579*61046927SAndroid Build Coastguard Worker          case 0x4: {
580*61046927SAndroid Build Coastguard Worker             /* Format 2 */
581*61046927SAndroid Build Coastguard Worker             unsigned idx = stop ? 4 : 1;
582*61046927SAndroid Build Coastguard Worker             main_instr.add_bits |= (tag & 0x7) << 17;
583*61046927SAndroid Build Coastguard Worker             instrs[idx] = main_instr;
584*61046927SAndroid Build Coastguard Worker             instrs[idx + 1].fma_bits |= bits(words[3], 22, 32);
585*61046927SAndroid Build Coastguard Worker             instrs[idx + 1].reg_bits =
586*61046927SAndroid Build Coastguard Worker                bits(words[2], 19, 32) | (bits(words[3], 0, 22) << (32 - 19));
587*61046927SAndroid Build Coastguard Worker             break;
588*61046927SAndroid Build Coastguard Worker          }
589*61046927SAndroid Build Coastguard Worker          case 0x1:
590*61046927SAndroid Build Coastguard Worker             /* Format 0 - followed by constants */
591*61046927SAndroid Build Coastguard Worker             num_instrs = 1;
592*61046927SAndroid Build Coastguard Worker             done = stop;
593*61046927SAndroid Build Coastguard Worker             FALLTHROUGH;
594*61046927SAndroid Build Coastguard Worker          case 0x5:
595*61046927SAndroid Build Coastguard Worker             /* Format 0 - followed by instructions */
596*61046927SAndroid Build Coastguard Worker             header_bits =
597*61046927SAndroid Build Coastguard Worker                bits(words[2], 19, 32) | ((uint64_t)words[3] << (32 - 19));
598*61046927SAndroid Build Coastguard Worker             main_instr.add_bits |= (tag & 0x7) << 17;
599*61046927SAndroid Build Coastguard Worker             instrs[0] = main_instr;
600*61046927SAndroid Build Coastguard Worker             break;
601*61046927SAndroid Build Coastguard Worker          case 0x6:
602*61046927SAndroid Build Coastguard Worker          case 0x7: {
603*61046927SAndroid Build Coastguard Worker             /* Format 12 */
604*61046927SAndroid Build Coastguard Worker             unsigned pos = tag & 0xf;
605*61046927SAndroid Build Coastguard Worker 
606*61046927SAndroid Build Coastguard Worker             struct {
607*61046927SAndroid Build Coastguard Worker                unsigned const_idx;
608*61046927SAndroid Build Coastguard Worker                unsigned nr_tuples;
609*61046927SAndroid Build Coastguard Worker             } pos_table[0x10] = {{0, 1}, {0, 2}, {0, 4}, {1, 3},
610*61046927SAndroid Build Coastguard Worker                                  {1, 5}, {2, 4}, {0, 7}, {1, 6},
611*61046927SAndroid Build Coastguard Worker                                  {3, 5}, {1, 8}, {2, 7}, {3, 6},
612*61046927SAndroid Build Coastguard Worker                                  {3, 8}, {4, 7}, {5, 6}, {~0, ~0}};
613*61046927SAndroid Build Coastguard Worker 
614*61046927SAndroid Build Coastguard Worker             ASSERTED bool valid_count = pos_table[pos].nr_tuples == num_instrs;
615*61046927SAndroid Build Coastguard Worker             assert(valid_count && "INSTR_INVALID_ENC");
616*61046927SAndroid Build Coastguard Worker 
617*61046927SAndroid Build Coastguard Worker             unsigned const_idx = pos_table[pos].const_idx;
618*61046927SAndroid Build Coastguard Worker 
619*61046927SAndroid Build Coastguard Worker             if (num_consts < const_idx + 2)
620*61046927SAndroid Build Coastguard Worker                num_consts = const_idx + 2;
621*61046927SAndroid Build Coastguard Worker 
622*61046927SAndroid Build Coastguard Worker             consts.raw[const_idx] = const0;
623*61046927SAndroid Build Coastguard Worker             consts.raw[const_idx + 1] = const1;
624*61046927SAndroid Build Coastguard Worker 
625*61046927SAndroid Build Coastguard Worker             /* Calculate M values from A, B and 4-bit
626*61046927SAndroid Build Coastguard Worker              * unsigned arithmetic. Mathematically it
627*61046927SAndroid Build Coastguard Worker              * should be (A - B) % 16 but we use this
628*61046927SAndroid Build Coastguard Worker              * alternate form to avoid sign issues */
629*61046927SAndroid Build Coastguard Worker 
630*61046927SAndroid Build Coastguard Worker             unsigned A1 = bits(words[2], 0, 4);
631*61046927SAndroid Build Coastguard Worker             unsigned B1 = bits(words[3], 28, 32);
632*61046927SAndroid Build Coastguard Worker             unsigned A2 = bits(words[1], 0, 4);
633*61046927SAndroid Build Coastguard Worker             unsigned B2 = bits(words[2], 28, 32);
634*61046927SAndroid Build Coastguard Worker 
635*61046927SAndroid Build Coastguard Worker             unsigned M1 = (16 + A1 - B1) & 0xF;
636*61046927SAndroid Build Coastguard Worker             unsigned M2 = (16 + A2 - B2) & 0xF;
637*61046927SAndroid Build Coastguard Worker 
638*61046927SAndroid Build Coastguard Worker             decode_M(&consts.mods[const_idx], M1, M2, false);
639*61046927SAndroid Build Coastguard Worker 
640*61046927SAndroid Build Coastguard Worker             done = stop;
641*61046927SAndroid Build Coastguard Worker             break;
642*61046927SAndroid Build Coastguard Worker          }
643*61046927SAndroid Build Coastguard Worker          default:
644*61046927SAndroid Build Coastguard Worker             break;
645*61046927SAndroid Build Coastguard Worker          }
646*61046927SAndroid Build Coastguard Worker 
647*61046927SAndroid Build Coastguard Worker          if (done)
648*61046927SAndroid Build Coastguard Worker             break;
649*61046927SAndroid Build Coastguard Worker       }
650*61046927SAndroid Build Coastguard Worker    }
651*61046927SAndroid Build Coastguard Worker 
652*61046927SAndroid Build Coastguard Worker    *size = i + 1;
653*61046927SAndroid Build Coastguard Worker 
654*61046927SAndroid Build Coastguard Worker    if (verbose) {
655*61046927SAndroid Build Coastguard Worker       fprintf(fp, "# header: %012" PRIx64 "\n", header_bits);
656*61046927SAndroid Build Coastguard Worker    }
657*61046927SAndroid Build Coastguard Worker 
658*61046927SAndroid Build Coastguard Worker    struct bifrost_header header;
659*61046927SAndroid Build Coastguard Worker    memcpy((char *)&header, (char *)&header_bits, sizeof(struct bifrost_header));
660*61046927SAndroid Build Coastguard Worker    dump_header(fp, header, verbose);
661*61046927SAndroid Build Coastguard Worker 
662*61046927SAndroid Build Coastguard Worker    fprintf(fp, "{\n");
663*61046927SAndroid Build Coastguard Worker    for (i = 0; i < num_instrs; i++) {
664*61046927SAndroid Build Coastguard Worker       struct bifrost_regs regs, next_regs;
665*61046927SAndroid Build Coastguard Worker       if (i + 1 == num_instrs) {
666*61046927SAndroid Build Coastguard Worker          memcpy((char *)&next_regs, (char *)&instrs[0].reg_bits,
667*61046927SAndroid Build Coastguard Worker                 sizeof(next_regs));
668*61046927SAndroid Build Coastguard Worker       } else {
669*61046927SAndroid Build Coastguard Worker          memcpy((char *)&next_regs, (char *)&instrs[i + 1].reg_bits,
670*61046927SAndroid Build Coastguard Worker                 sizeof(next_regs));
671*61046927SAndroid Build Coastguard Worker       }
672*61046927SAndroid Build Coastguard Worker 
673*61046927SAndroid Build Coastguard Worker       memcpy((char *)&regs, (char *)&instrs[i].reg_bits, sizeof(regs));
674*61046927SAndroid Build Coastguard Worker 
675*61046927SAndroid Build Coastguard Worker       if (verbose) {
676*61046927SAndroid Build Coastguard Worker          fprintf(fp, "    # regs: %016" PRIx64 "\n", instrs[i].reg_bits);
677*61046927SAndroid Build Coastguard Worker          dump_regs(fp, regs, i == 0);
678*61046927SAndroid Build Coastguard Worker       }
679*61046927SAndroid Build Coastguard Worker 
680*61046927SAndroid Build Coastguard Worker       bi_disasm_fma(fp, instrs[i].fma_bits, &regs, &next_regs,
681*61046927SAndroid Build Coastguard Worker                     header.staging_register, offset, &consts,
682*61046927SAndroid Build Coastguard Worker                     i + 1 == num_instrs);
683*61046927SAndroid Build Coastguard Worker 
684*61046927SAndroid Build Coastguard Worker       bi_disasm_add(fp, instrs[i].add_bits, &regs, &next_regs,
685*61046927SAndroid Build Coastguard Worker                     header.staging_register, offset, &consts,
686*61046927SAndroid Build Coastguard Worker                     i + 1 == num_instrs);
687*61046927SAndroid Build Coastguard Worker    }
688*61046927SAndroid Build Coastguard Worker    fprintf(fp, "}\n");
689*61046927SAndroid Build Coastguard Worker 
690*61046927SAndroid Build Coastguard Worker    if (verbose) {
691*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_consts; i++) {
692*61046927SAndroid Build Coastguard Worker          fprintf(fp, "# const%d: %08" PRIx64 "\n", 2 * i,
693*61046927SAndroid Build Coastguard Worker                  consts.raw[i] & 0xffffffff);
694*61046927SAndroid Build Coastguard Worker          fprintf(fp, "# const%d: %08" PRIx64 "\n", 2 * i + 1,
695*61046927SAndroid Build Coastguard Worker                  consts.raw[i] >> 32);
696*61046927SAndroid Build Coastguard Worker       }
697*61046927SAndroid Build Coastguard Worker    }
698*61046927SAndroid Build Coastguard Worker 
699*61046927SAndroid Build Coastguard Worker    fprintf(fp, "\n");
700*61046927SAndroid Build Coastguard Worker    return;
701*61046927SAndroid Build Coastguard Worker }
702*61046927SAndroid Build Coastguard Worker 
703*61046927SAndroid Build Coastguard Worker void
disassemble_bifrost(FILE * fp,const void * code,size_t size,bool verbose)704*61046927SAndroid Build Coastguard Worker disassemble_bifrost(FILE *fp, const void *code, size_t size, bool verbose)
705*61046927SAndroid Build Coastguard Worker {
706*61046927SAndroid Build Coastguard Worker    const uint32_t *words = (const uint32_t *)code;
707*61046927SAndroid Build Coastguard Worker    const uint32_t *words_end = words + (size / 4);
708*61046927SAndroid Build Coastguard Worker    // used for displaying branch targets
709*61046927SAndroid Build Coastguard Worker    unsigned offset = 0;
710*61046927SAndroid Build Coastguard Worker    while (words != words_end) {
711*61046927SAndroid Build Coastguard Worker       /* Shaders have zero bytes at the end for padding; stop
712*61046927SAndroid Build Coastguard Worker        * disassembling when we hit them. */
713*61046927SAndroid Build Coastguard Worker       if (*words == 0)
714*61046927SAndroid Build Coastguard Worker          break;
715*61046927SAndroid Build Coastguard Worker 
716*61046927SAndroid Build Coastguard Worker       fprintf(fp, "clause_%u:\n", offset);
717*61046927SAndroid Build Coastguard Worker 
718*61046927SAndroid Build Coastguard Worker       unsigned size;
719*61046927SAndroid Build Coastguard Worker       dump_clause(fp, words, &size, offset, verbose);
720*61046927SAndroid Build Coastguard Worker 
721*61046927SAndroid Build Coastguard Worker       words += size * 4;
722*61046927SAndroid Build Coastguard Worker       offset += size;
723*61046927SAndroid Build Coastguard Worker    }
724*61046927SAndroid Build Coastguard Worker }
725